Updated Upstream and Sidestream(s) (Paper/Tuinity/Purpur) (#435)

* Updated Upstream and Sidestream(s) (Paper/Tuinity/Purpur)

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:
d80e43647 [CI-SKIP] Removal from the MIT list (#5345)

Tuinity Changes:
c303521 Change license from MIT to LGPLv3

Purpur Changes:
3044036 Re-enable timings by default
4f85cbe Include all Airplane patches
7b5feba [ci-skip] Tuinity license change
210ff8f [ci-skip] revert last commit. wasnt what i thought it was :3
47e8965 [ci-skip] Add maven repositories for Adventure API
3930ac4 It's muffin time!
e535225 Updated Upstream (Paper & Tuinity)

* whoops

* this actually fixes it (I was being stupid)

* [CI-SKIP] fix akarin link in Licensing/LICENSE.md

* Updated Upstream and Sidestream(s) (Paper/Airplane/Akarin/Empirecraft)

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:
39c487b37 Add per-command perms for paper command
cdbf2578c Add Item Rarity API (#5352)

Airplane Changes:
5df9825 Remove iterators from inventory contains
18d2be1 Merge pull request #14 from violetwtf/patch-1
f716d4c Merge pull request #13 from violetwtf/master
128cbe5 Reduce entity chunk ticking checks from 3 to 1
03ac093 Skip copying unloading tile entities
97dd027 Smaller pool size for tracking
9e9f57b Only set up Flare if token is available
580f380 Updated Upstream (Tuinity)
97df206 Update README to reflect support changes
cf161dd Change blog URL to more helpful one

Akarin Changes:
6be3d57 Update Jenkinsfile
3aa2e99 Merge pull request #198 from HookWoods/ver/1.16.5
c548038 try to fix velocity repo
5b03eb1 Update patches to 1.16.5

Empirecraft Changes:
81545aaf Updated Paper

Airplane Changes:
82253fd Early return optimization for target finding
9572643 Cache entityhuman display name

* Updated Upstream and Sidestream(s) (Tuinity/Purpur/Airplane)

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.

Tuinity Changes:
aea6b83 Merge dev/playerchunkloading
722c7ca Use hash table for maintaing changed block set
98ae59d Custom table implementation for blockstate state lookups
8b8704f Oprimise map impl for tracked players
ea71d6b Optimise snow & ice in chunk ticking
9871d4c Remove chunk lookup & lambda allocation from counting mobs
5a4a35f Add patreon
7d93d96 Refactor data management for region manager

Purpur Changes:
37591fe Add config to use no-tick vd for tracker (#195)

Airplane Changes:
cc00c69 Updated Upstream (Tuinity)
This commit is contained in:
Simon Gardling 2021-03-14 15:20:20 -04:00 committed by GitHub
parent 7b34115801
commit c4a68471e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
154 changed files with 5377 additions and 1211 deletions

View File

@ -4,4 +4,4 @@ All patches (.patch files) marked with "lithium" are licensed under LGPL3 found
All patches (.patch files) marked with "hydrogen" are licensed under LGPL3 found [here](https://github.com/CaffeineMC/hydrogen-fabric/blob/1.16.x/LICENSE.txt).<br>
All patches (.patch files) marked with "krypton" are licensed under MIT found [here](https://github.com/astei/krypton/blob/master/LICENSE).<br>
All other patches (.patch files) included in this repo are licensed under the MIT license found [here](MIT.md).<br>
See [EMC](https://github.com/starlis/empirecraft/blob/master/README.md), [Akarin](https://github.com/Akarin-project/Akarin/blob/1.16.3/LICENSE.md), [Purpur](https://github.com/pl3xgaming/Purpur/blob/ver/1.16.5/LICENSE), [Airplane](https://github.com/Technove/Airplane/blob/master/PATCHES-LICENSE), [Origami](https://github.com/Minebench/Origami/blob/1.16/PATCHES-LICENSE), and [Tuinity](https://github.com/Spottedleaf/Tuinity/blob/master/PATCHES-LICENSE) for the license of patches automatically pulled during upstream updates.
See [EMC](https://github.com/starlis/empirecraft/blob/master/README.md), [Akarin](https://github.com/Akarin-project/Akarin/blob/1.16.5/LICENSE.md), [Purpur](https://github.com/pl3xgaming/Purpur/blob/ver/1.16.5/LICENSE), [Airplane](https://github.com/Technove/Airplane/blob/master/PATCHES-LICENSE), [Origami](https://github.com/Minebench/Origami/blob/1.16/PATCHES-LICENSE), and [Tuinity](https://github.com/Spottedleaf/Tuinity/blob/master/PATCHES-LICENSE) for the license of patches automatically pulled during upstream updates.

View File

@ -96,6 +96,7 @@ This is an overview over all patches that are currently used.
| server | Breedable Polar Bears | William Blake Galbreath | |
| server | Bring back server name | William Blake Galbreath | |
| api | Bring back server name | William Blake Galbreath | |
| server | Cache entityhuman display name | Paul Sauve | |
| server | Cache palette array | Paul Sauve | |
| server | Cat spawning options | William Blake Galbreath | |
| server | Change writes to use NORMAL priority rather than LOW | Spottedleaf | |
@ -137,6 +138,7 @@ This is an overview over all patches that are currently used.
| server | Cows eat mushrooms | William Blake Galbreath | |
| server | Crying obsidian valid for portal frames | William Blake Galbreath | |
| server | Custom Locale Support | Zoe | |
| server | Custom table implementation for blockstate state lookups | Spottedleaf | |
| server | Customizable wither health and healing | jmp | |
| api | Default permissions | William Blake Galbreath | |
| server | Delay chunk unloads | Spottedleaf | |
@ -167,6 +169,7 @@ This is an overview over all patches that are currently used.
| server | EMC - Configurable disable give dropping | Aikar | |
| server | EMC - MonsterEggSpawnEvent | Aikar | |
| api | EMC - MonsterEggSpawnEvent | Aikar | |
| server | Early return optimization for target finding | Paul Sauve | |
| server | End crystal explosion options | Ben Kerllenevich | |
| server | End gateway should check if entity can use portal | William Blake Galbreath | |
| server | Ender dragon always drop full exp | William Blake Galbreath | |
@ -261,14 +264,16 @@ This is an overview over all patches that are currently used.
| server | Nuke streams off BlockPosition | Ivan Pekov | |
| server | Nuke streams off SectionPosition | Ivan Pekov | |
| server | One Punch Man! | Fourmisain | |
| server | Oprimise map impl for tracked players | Spottedleaf | |
| server | Optimise WorldServer#notify | Spottedleaf | |
| server | Optimise chunk tick iteration | 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 general POI access | Spottedleaf | |
| server | Optimise nearby player lookups | Spottedleaf | |
| server | Optimise non-flush packet sending | Spottedleaf | |
| server | Optimise portals | Ivan Pekov | |
| server | Optimise snow &amp; ice in chunk ticking | Spottedleaf | |
| server | Optimise tab complete | Spottedleaf | |
| server | Optimised hallowen checker | Ivan Pekov | |
| server | Optimize BehaviorController | MrIvanPlays | |
@ -288,6 +293,7 @@ This is an overview over all patches that are currently used.
| server | PaperPR - Config option for Piglins guarding chests | jmp | |
| server | Per World Spawn Limits | Chase Whipple | |
| server | Per entity (type) collision settings | MrIvanPlays | tr7zw |
| api | Per player viewdistances | Spottedleaf | |
| server | Persistent TileEntity Lore and DisplayName | jmp | |
| server | Phantom flames on swoop | BillyGalbreath | |
| server | Phantoms attracted to crystals and crystals shoot phantoms | William Blake Galbreath | |
@ -321,12 +327,16 @@ This is an overview over all patches that are currently used.
| server | Reduce allocation rate from crammed entities | Spottedleaf | |
| server | Reduce allocs &amp; improve perf of StructureManager | Paul Sauve | |
| server | Reduce chunk loading &amp; lookups | Paul Sauve | |
| server | Reduce entity chunk ticking checks from 3 to 1 | Paul Sauve | |
| server | Reduce iterator allocation from chunk gen | Spottedleaf | |
| server | Reduce pathfinder branches | Spottedleaf | |
| server | Reduce projectile chunk loading | Paul Sauve | |
| server | Remove chunk lookup &amp; lambda allocation from counting mobs | Spottedleaf | |
| server | Remove iterators from inventory contains | Paul Sauve | |
| server | Remove some streams and object allocations | Phoenix616 | |
| server | Remove streams | Paul Sauve | |
| server | Remove streams for villager AI | Spottedleaf | |
| server | Replace player chunk loader system | Spottedleaf | |
| server | Revert MC-4 fix | Spottedleaf | |
| server | Revert getChunkAt(Async) retaining chunks for long periods of | Spottedleaf | |
| server | Rework PlayerChunk main thread checks | Spottedleaf | |
@ -343,6 +353,7 @@ This is an overview over all patches that are currently used.
| server | Silk touch spawners | William Blake Galbreath | |
| server | Simpler ShapelessRecipes comparison for Vanilla | Paul Sauve | |
| server | Skip POI finding if stuck in vehicle | Paul Sauve | |
| server | Skip copying unloading tile entities | Paul Sauve | |
| server | Skip events if there&#39;s no listeners | William Blake Galbreath | |
| server | Smarter statistics ticking | Mykyta Komarnytskyy | |
| server | Smol entity optimisations | Ivan Pekov | |
@ -359,6 +370,7 @@ This is an overview over all patches that are currently used.
| server | Suspected plugins report | ishland | |
| api | Suspected plugins report | ishland | |
| server | Swap priority of checks in chunk ticking | Paul Sauve | |
| server | Swaps the predicate order of collision | ㄗㄠˋ ㄑㄧˊ | |
| server | Time scoreboard search | Spottedleaf | |
| server | Timings stuff | William Blake Galbreath | |
| server | Toggle for Zombified Piglin death always counting as player | jmp | |
@ -372,6 +384,7 @@ This is an overview over all patches that are currently used.
| server | Update version fetcher repo | JRoy | |
| server | Use configured height for nether surface builders | William Blake Galbreath | |
| server | Use entity ticking chunk map for entity tracker | Spottedleaf | |
| server | Use hash table for maintaing changed block set | Spottedleaf | |
| server | Use unmodifiableMap instead of making copy | Paul Sauve | |
| server | Util patch | Spottedleaf | |
| server | Utilities | YatopiaMC | Mykyta Komarnytskyy, Ivan Pekov |

2
Paper

@ -1 +1 @@
Subproject commit 808bd9198664938af58e98e622c41902343587e0
Subproject commit 39c487b37d51944997aa2eea8ce62e3f5bc07d52

View File

@ -88,7 +88,7 @@ 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 87766db4e3c2e522b738fa304a861dc0985d878a..44f52fb6e3aedeadec4be3979ad1c625643cf9fa 100644
index abd415f02d8b4c28602b6c4aefc0914b5a83165b..9d6ddfec93f49f80fdc88248fc5aaf5ad6ee48da 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -363,6 +363,91 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

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 2c73ddae3df32eea175fb1779104441b49796939..9ae0d37d41700f9fb1e13d1b61b07c7bc09b9d75 100644
index 877ba68edec7b8b444ea7cd849fdcb337cfbc60d..63dd6aba40506014b15efecfb8562c4f455ac04e 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1134,7 +1134,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1137,7 +1137,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 8fda4702764e80dae93ef9c0eb53abc198642ab1..0924f6b484468f3cf3c2d405101c0158c12d69e6 100644
index 8e59a794f6190930cb7bb81a2fe1a1d374dacce7..045b4af6721817b3dbfb05b9aec0bf382de9fcf5 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 {
@ -65,10 +65,10 @@ index 8fda4702764e80dae93ef9c0eb53abc198642ab1..0924f6b484468f3cf3c2d405101c0158
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 e26389d8d9ee4fedb32767fce3aed071af412304..9cf3cd69661a140d34d17195c2cd6dc299c95ddf 100644
index b55f7dece329dbb3ff27d57a39c32c69e5baea74..5897d462d350dfbd1464feb92ecf77725651c694 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -974,6 +974,7 @@ public class ChunkProviderServer extends IChunkProvider {
@@ -975,6 +975,7 @@ public class ChunkProviderServer extends IChunkProvider {
}
// Paper end - optimize isOutisdeRange
this.world.getMethodProfiler().enter("pollingChunks");
@ -77,19 +77,19 @@ index e26389d8d9ee4fedb32767fce3aed071af412304..9cf3cd69661a140d34d17195c2cd6dc2
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 9ae0d37d41700f9fb1e13d1b61b07c7bc09b9d75..fe6611e480c18e97061268690d067a811b13bb1b 100644
index 63dd6aba40506014b15efecfb8562c4f455ac04e..7660d098046100a4ab168149604ec196a4eea03d 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -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
@@ -1127,6 +1127,8 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final BiomeBase[] biomeBaseCache = new BiomeBase[1];
// Tuinity end - optimise chunk ice snow ticking
+ private int currentIceAndSnowTick = 0; protected void resetIceAndSnowTick() { this.currentIceAndSnowTick = this.randomTickRandom.nextInt(16); } // Airplane
+
public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
boolean flag = this.isRaining();
@@ -1134,7 +1136,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1137,7 +1139,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,12 +98,12 @@ index 9ae0d37d41700f9fb1e13d1b61b07c7bc09b9d75..fe6611e480c18e97061268690d067a81
blockposition.setValues(this.a(this.a(j, 0, k, 15))); // Paper
if (this.isRainingAt(blockposition)) {
DifficultyDamageScaler difficultydamagescaler = this.getDamageScaler(blockposition);
@@ -1164,7 +1166,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1167,7 +1169,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
gameprofilerfiller.exitEnter("iceandsnow");
- if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
+ if (!this.paperConfig.disableIceAndSnow && (this.currentIceAndSnowTick++ & 15) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking // Airplane - optimize further random ticking
// Paper start - optimise chunk ticking
this.getRandomBlockPosition(j, 0, k, 15, blockposition);
int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15);
// Tuinity start - optimise chunk ice snow ticking
BiomeBase[] biomeCache = this.biomeBaseCache;

View File

@ -30,10 +30,10 @@ index df4d5ed5957658ee9ca083ac79b38a1202fe7015..e7568e3df10bc07e9b3b05caa9d41398
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 ae17950438132c5084210252bd345517131d5a99..1016305a571a2fc211cd0e58b7210d8cfb4461d5 100644
index ad520cb36afd0f011b6337f3e42efb01f740a950..b5b0f295d63eb245a6221f88110f1bb1694c641c 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 {
@@ -381,7 +381,10 @@ public final class SpawnerCreature {
}
private static List<BiomeSettingsMobs.c> a(WorldServer worldserver, StructureManager structuremanager, ChunkGenerator chunkgenerator, EnumCreatureType enumcreaturetype, BlockPosition blockposition, @Nullable BiomeBase biomebase) {

View File

@ -20,10 +20,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/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
index 8d445e9c0875db6cf45e4d8bcfce7cd3d5094d94..0594b0bb12c553edbb6284b48328a3dcf5a64ba4 100644
index 83702e07dff72b639af32c8ba9e831e58da92a10..a48f2f82517bc391d5d5b7961e3c7a75175abb65 100644
--- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java
+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
@@ -278,6 +278,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
@@ -57,6 +57,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) {
this.f = i + 20L + (long) worldserver.getRandom().nextInt(20);
@ -32,7 +32,7 @@ index 8d445e9c0875db6cf45e4d8bcfce7cd3d5094d94..0594b0bb12c553edbb6284b48328a3dc
this.g.long2ObjectEntrySet().removeIf((entry) -> {
diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index 1208464fba96daf276c9cc0c1c9b18db75b03abc..b5ea7997040b5bfd98925a146e446aa3c56574da 100644
index cba6f414d1a673e735f80662620a8bec78cd09ab..88368ae1633cf8bfb845d52b38110a6828fcf699 100644
--- a/src/main/java/net/minecraft/server/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java
@@ -412,6 +412,7 @@ public abstract class NavigationAbstract {

View File

@ -50,10 +50,10 @@ index 752d62eb3b87ab24260ec2c029bae0d2b0e3b908..02bbe784d0a062dd643e37f3ad04b77a
<pluginRepositories>
diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
index c39c9929a251b41ab60e1509b4e6c90d0825dc0c..3a5a65a2f282b00602643470520fd05fba5907fb 100644
index c39c9929a251b41ab60e1509b4e6c90d0825dc0c..4f87df936d0092cbf8cb2a6db9b57f235c287beb 100644
--- a/src/main/java/gg/airplane/AirplaneConfig.java
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -68,4 +68,23 @@ public class AirplaneConfig {
@@ -68,4 +68,26 @@ public class AirplaneConfig {
dynamicHoglinBehavior = manual.get("behavior-activation.hoglin", dynamicHoglinBehavior);
}
@ -74,6 +74,9 @@ index c39c9929a251b41ab60e1509b4e6c90d0825dc0c..3a5a65a2f282b00602643470520fd05f
+
+ accessToken = manual.get("web-services.token", "");
+ // todo lookup token (off-thread) and let users know if their token is valid
+ if (accessToken.length() > 0) {
+ gg.airplane.flare.FlareSetup.init(); // Airplane
+ }
+ }
+
}
@ -202,10 +205,10 @@ index 0000000000000000000000000000000000000000..f4976428bc721319d2926e97cbe0f64c
+}
diff --git a/src/main/java/gg/airplane/flare/FlareCommand.java b/src/main/java/gg/airplane/flare/FlareCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..81f5267d287138f6b47aa0a1f1d59d2d91a7e34a
index 0000000000000000000000000000000000000000..e3ef62ae97b8b92459e1c405525790ba2172df01
--- /dev/null
+++ b/src/main/java/gg/airplane/flare/FlareCommand.java
@@ -0,0 +1,158 @@
@@ -0,0 +1,159 @@
+package gg.airplane.flare;
+
+import com.google.common.collect.ImmutableList;
@ -230,6 +233,7 @@ index 0000000000000000000000000000000000000000..81f5267d287138f6b47aa0a1f1d59d2d
+
+public class FlareCommand extends Command {
+
+ private static final String BASE_URL = "https://blog.airplane.gg/flare-tutorial/#setting-the-access-token";
+ private static final ChatColor HEX = ChatColor.of("#6a7eda");
+ private static final BaseComponent[] PREFIX = new ComponentBuilder("Flare ✈ ")
+ .color(HEX)
@ -255,10 +259,10 @@ index 0000000000000000000000000000000000000000..81f5267d287138f6b47aa0a1f1d59d2d
+ public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+ if (!testPermission(sender)) return true;
+ if (AirplaneConfig.accessToken.length() == 0) {
+ BaseComponent clickable = new TextComponent("https://blog.airplane.gg/flare");
+ BaseComponent clickable = new TextComponent(BASE_URL);
+ clickable.setUnderlined(true);
+ clickable.setColor(HEX);
+ clickable.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://blog.airplane.gg/flare"));
+ clickable.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, BASE_URL));
+
+ sender.sendMessage(create(new ComponentBuilder("Flare currently requires an access token to use. To learn more, visit ")
+ .color(HEX)
@ -587,18 +591,6 @@ index 0000000000000000000000000000000000000000..86d6650d174a7794a7ebe793cad033b4
+ }
+
+}
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
index b8a45c80b6691214e513286262f31b7b5b1dd5eb..a85a844a4766cde16eea9e814abfec29d8935c0f 100644
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
@@ -187,6 +187,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config
gg.airplane.AirplaneConfig.load(); // Airplane - config
gg.airplane.commands.AirplaneCommands.init(); // Airplane - command
+ gg.airplane.flare.FlareSetup.init(); // Airplane
this.setPVP(dedicatedserverproperties.pvp);
this.setAllowFlight(dedicatedserverproperties.allowFlight);
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java b/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java
index 49dc0c441b9dd7e7745cf15ced67f383ebee1f99..b343d8ee7435312929558efdaf127334d8e2fff6 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/MinecraftInternalPlugin.java

View File

@ -37,11 +37,11 @@ index be408aebbccbda46e8aa82ef337574137cfa0096..b9bdce7c7ca8b7b107b0dca165d72232
protected final double maxFragFactor;
diff --git a/src/main/java/gg/airplane/AirplaneConfig.java b/src/main/java/gg/airplane/AirplaneConfig.java
index 3a5a65a2f282b00602643470520fd05fba5907fb..e183b6cae23935823fa9e0f767e499a8102b0ad1 100644
index 4f87df936d0092cbf8cb2a6db9b57f235c287beb..424325ada75b788ce390378d8df0116e5c50cf3d 100644
--- a/src/main/java/gg/airplane/AirplaneConfig.java
+++ b/src/main/java/gg/airplane/AirplaneConfig.java
@@ -87,4 +87,18 @@ public class AirplaneConfig {
// todo lookup token (off-thread) and let users know if their token is valid
@@ -90,4 +90,18 @@ public class AirplaneConfig {
}
}
+
@ -61,7 +61,7 @@ index 3a5a65a2f282b00602643470520fd05fba5907fb..e183b6cae23935823fa9e0f767e499a8
}
diff --git a/src/main/java/gg/airplane/structs/TrackQueue.java b/src/main/java/gg/airplane/structs/TrackQueue.java
new file mode 100644
index 0000000000000000000000000000000000000000..601694aa6d36ce230d84cc6b55231d2fc3af30e9
index 0000000000000000000000000000000000000000..e72229128285e1a48b9b461620620976ca0dc0a4
--- /dev/null
+++ b/src/main/java/gg/airplane/structs/TrackQueue.java
@@ -0,0 +1,84 @@
@ -82,7 +82,7 @@ index 0000000000000000000000000000000000000000..601694aa6d36ce230d84cc6b55231d2f
+public class TrackQueue {
+
+ private final IteratorSafeOrderedReferenceSet<Chunk> chunks;
+ private final ForkJoinPool pool = ForkJoinPool.commonPool();
+ private final ForkJoinPool pool = new ForkJoinPool(Math.max(4, Runtime.getRuntime().availableProcessors() >> 2));
+ private final AtomicInteger taskIndex = new AtomicInteger();
+
+ private final ConcurrentLinkedQueue<Runnable> mainThreadTasks;
@ -150,7 +150,7 @@ index 0000000000000000000000000000000000000000..601694aa6d36ce230d84cc6b55231d2f
+
+}
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 0924f6b484468f3cf3c2d405101c0158c12d69e6..1d65d884d1f31a73333e4cf6a9ce30d7863dab9f 100644
index 045b4af6721817b3dbfb05b9aec0bf382de9fcf5..6cde93d62c4c324a6544401cabe045cbb80f465e 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -65,6 +65,26 @@ public class Chunk implements IChunkAccess {
@ -181,7 +181,7 @@ index 0924f6b484468f3cf3c2d405101c0158c12d69e6..1d65d884d1f31a73333e4cf6a9ce30d7
this(world, chunkcoordintpair, biomestorage, ChunkConverter.a, TickListEmpty.b(), TickListEmpty.b(), 0L, (ChunkSection[]) null, (Consumer) null);
}
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 93bca6a52dd01d9ad524a03d90c7ec79d00d2c56..d6c6a389cf214f2f8cbb343fc8106ab7d0845950 100644
index e384a24d9b46587f66ee3e712a8206b1ca1f3877..8071e8ec7bb505e026ceead84377e61063864bc5 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -52,7 +52,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -287,10 +287,10 @@ index 2f758b3d3eaf5d5781a2072d0f3f7442b73cb9a8..63bcd1b61d0485b064d619ddfa0e2010
if (this.tracker instanceof EntityPlayer) {
((EntityPlayer) this.tracker).playerConnection.sendPacket(packet);
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78f0433a52 100644
index 3e0bf6df7c4608a5b19024612db52558fd722f4b..74bb2573aa4f52a30341b3763f60a895d7b7a068 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -722,6 +722,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -731,6 +731,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return (PlayerChunk) (this.hasPendingVisibleUpdate ? this.pendingVisibleChunks.get(i) : ((ProtectedVisibleChunksMap)this.visibleChunks).safeGet(i));
// Paper end
}
@ -302,7 +302,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
protected final IntSupplier getPrioritySupplier(long i) { return c(i); } // Paper - OBFHELPER
protected IntSupplier c(long i) {
@@ -2124,10 +2129,30 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -2134,10 +2139,30 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
entity.tracker = null; // Paper - We're no longer tracked
}
@ -333,7 +333,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<Chunk> iterator = this.world.getChunkProvider().entityTickingChunks.iterator();
try {
while (iterator.hasNext()) {
@@ -2389,7 +2414,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2403,7 +2428,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
public class EntityTracker {
final EntityTrackerEntry trackerEntry; // Paper - private -> package private
@ -342,7 +342,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
private final int trackingDistance;
private SectionPosition e;
// Paper start
@@ -2408,7 +2433,9 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2422,7 +2447,9 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
// Paper start - use distance map to optimise tracker
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> lastTrackerCandidates;
@ -353,7 +353,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<EntityPlayer> oldTrackerCandidates = this.lastTrackerCandidates;
this.lastTrackerCandidates = newTrackerCandidates;
@@ -2449,7 +2476,13 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2463,7 +2490,13 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
return this.tracker.getId();
}
@ -368,7 +368,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
Iterator iterator = this.trackedPlayers.iterator();
while (iterator.hasNext()) {
@@ -2461,6 +2494,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2475,6 +2508,12 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
}
public void broadcastIncludingSelf(Packet<?> packet) {
@ -381,7 +381,7 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
this.broadcast(packet);
if (this.tracker instanceof EntityPlayer) {
((EntityPlayer) this.tracker).playerConnection.sendPacket(packet);
@@ -2487,8 +2526,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2501,8 +2540,8 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
}
@ -392,12 +392,12 @@ index 285e976d4a655fb61e70883ae89f974812be7152..5c3e0cadb02fd6e4d55ae0faa4618d78
if (entityplayer != this.tracker) {
// Paper start - remove allocation of Vec3D here
//Vec3D vec3d = entityplayer.getPositionVector().d(this.tracker.getPositionVector()); // MC-155077, SPIGOT-5113
@@ -2504,7 +2543,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2518,7 +2557,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
if (!flag1) {
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(this.tracker.chunkX, this.tracker.chunkZ);
- PlayerChunk playerchunk = PlayerChunkMap.this.getVisibleChunk(chunkcoordintpair.pair());
+ PlayerChunk playerchunk = PlayerChunkMap.this.trackerGetVisibleChunk(chunkcoordintpair.pair()); // Airplane
if (playerchunk != null && playerchunk.getSendingChunk() != null) { // Paper - no-tick view distance
if (playerchunk != null && playerchunk.getSendingChunk() != null && PlayerChunkMap.this.playerChunkManager.isChunkSent(entityplayer, MathHelper.floor(this.tracker.locX()) >> 4, MathHelper.floor(this.tracker.locZ()) >> 4)) { // Paper - no-tick view distance // Tuinity - don't broadcast in chunks the player hasn't received
flag1 = PlayerChunkMap.b(chunkcoordintpair, entityplayer, false) <= PlayerChunkMap.this.viewDistance;

View File

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

View File

@ -0,0 +1,53 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paul Sauve <paul@technove.co>
Date: Sat, 13 Mar 2021 10:40:22 -0600
Subject: [PATCH] Reduce entity chunk ticking checks from 3 to 1
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 7660d098046100a4ab168149604ec196a4eea03d..4e7700443c4f0725c0d032b620f84fcfadbde7a1 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -988,11 +988,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit end */
gameprofilerfiller.enter("checkDespawn");
+ boolean entityTickingChunk = false; if (!entity.dead) entityTickingChunk = this.getChunkProvider().isInEntityTickingChunk(entity); // Airplane - check once, chunks won't unload ticking entities
if (!entity.dead) {
entity.checkDespawn();
// Tuinity start - optimise notify()
if (entity.inChunk && entity.valid) {
- if (this.getChunkProvider().isInEntityTickingChunk(entity)) {
+ if (entityTickingChunk) { // Airplane - reuse
this.updateNavigatorsInRegion(entity);
}
} else {
@@ -1022,7 +1023,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.entitiesById.remove(entity.getId()); // Tuinity
this.unregisterEntity(entity);
} else if (entity.inChunk && entity.valid) { // Tuinity start - optimise notify()
- if (this.getChunkProvider().isInEntityTickingChunk(entity)) {
+ if (entityTickingChunk) { // Airplane - reuse
this.updateNavigatorsInRegion(entity);
}
} else {
@@ -1349,7 +1350,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Tuinity end - log detailed entity tick information
- public void entityJoinedWorld(Entity entity) {
+ // Airplane start - reuse check for in entity ticking chunk
+ public void entityJoinedWorld(Entity entity) { entityJoinedWorld(entity, this.getChunkProvider().isInEntityTickingChunk(entity)); }
+ public void entityJoinedWorld(Entity entity, boolean entityTickingChunk) { // Airplane end
// Tuinity start - log detailed entity tick information
com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
try {
@@ -1357,7 +1360,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
currentlyTickingEntity.lazySet(entity);
}
// Tuinity end - log detailed entity tick information
- if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) {
+ if (!(entity instanceof EntityHuman) && !entityTickingChunk) { // Airplane - reuse
this.chunkCheck(entity);
} else {
++TimingHistory.entityTicks; // Paper - timings

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Disable the Snooper
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 17591457a33e6994cd26bb1487a7879a11411a9c..e9c0556af0a8ffd4d85e87bcccf2908444d967eb 100644
index be48e686272b81dab4f1f584d946e15285934e88..806c699ce25525bc8a382a52e95644479e8ad708 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1329,6 +1329,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=84=97=E3=84=A0=CB=8B=20=E3=84=91=E3=84=A7=CB=8A?=
<tsao-chi@the-lingo.org>
Date: Fri, 10 Apr 2020 15:47:15 +0800
Subject: [PATCH] Swaps the predicate order of collision
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 426bebc5cd67ffcc72ee56d437cc13f6846e109c..b8ae3f65ba8a923ad2b72e6d6b1db7a17fd08cb8 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1630,8 +1630,9 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
public void pickup(EntityHuman entityhuman) {}
public void collide(Entity entity) {
+ if (entity.noclip || this.noclip) return; // Akarin - Test this earlier
if (!this.isSameVehicle(entity)) {
- if (!entity.noclip && !this.noclip) {
+ if (true || !entity.noclip && !this.noclip) { // Akarin - Moved up
if (this.world.paperConfig.onlyPlayersCollide && !(entity instanceof EntityPlayer || this instanceof EntityPlayer)) return; // Paper
double d0 = entity.locX() - this.locX();
double d1 = entity.locZ() - this.locZ();

View File

@ -19,7 +19,7 @@ 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 44f52fb6e3aedeadec4be3979ad1c625643cf9fa..0856d7389f9fec20885ee38bac242fb91834c66c 100644
index bdb0e46d9196f4ac164ed09fd9d01db60aaab401..27b39f63fa9c340e0b9f2ed82448c870c40ac5c7 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -805,7 +805,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

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 0856d7389f9fec20885ee38bac242fb91834c66c..6007121ca9791bfc8e68b0354ad9005a7369d389 100644
index 27b39f63fa9c340e0b9f2ed82448c870c40ac5c7..e280afce30ddc0c2ec54945543ad65b4ebfa71f2 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 {

View File

@ -81,10 +81,10 @@ index 0000000000000000000000000000000000000000..0c8b3e5e4ba412624357ea5662a78862
+ }
+}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 2ea531eaef8c455fdd503f0c0258813fe9136085..53e10ef71fcd904d59c9c9825b2a736b6b35027c 100644
index a84ea92d02d34cd48174152e0391f1af6c6b5def..023ca23e8c91a6525cc31d483d873dfe14e97da3 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2076,4 +2076,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@@ -2116,4 +2116,25 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@Override
Spigot spigot();
// Spigot end

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Player invulnerabilities
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 53e10ef71fcd904d59c9c9825b2a736b6b35027c..a2a58dea8bdb5597fc0617e7b5b4fb8ab9d77641 100644
index 023ca23e8c91a6525cc31d483d873dfe14e97da3..3dd208c763a71f4211b89a32a936a2317555f265 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -2096,5 +2096,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@@ -2136,5 +2136,26 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Reset the idle timer back to 0
*/
void resetIdleTimer();

View File

@ -5,10 +5,10 @@ Subject: [PATCH] ItemStack convenience methods
diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java
index 7b77c7132723a01e8c38ddaa616b363be300b653..c6b1131b1700797e0515045f4e5c81f85aa3449f 100644
index 0a31a5321ac519568db936c94394f71b2e2fcec1..42a77a5f5b8968351a737cb1fd7cebf160b13245 100644
--- a/src/main/java/org/bukkit/Material.java
+++ b/src/main/java/org/bukkit/Material.java
@@ -8649,4 +8649,36 @@ public enum Material implements Keyed {
@@ -8660,4 +8660,36 @@ public enum Material implements Keyed {
// </editor-fold>
}
}

View File

@ -490,7 +490,7 @@ index 28a1fe3af1546daa779df46468e0ff8ad823f9ca..7a3be414ef9d54d7a852ba92d704011f
@NotNull
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index f486d7c819f6330223980793c9b086fded0af059..632e53338c4d902aea7e8589152b1c1b6e6dde6a 100644
index 7f90ef2fd1c87c5b8b69f2e9dba3ad8e6e9ce3ec..85f77a58bf6c21da815b6652c7b50d578951a14c 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -81,6 +81,8 @@ public interface UnsafeValues {
@ -950,10 +950,10 @@ index a6a7429ed2e1eefb2b12b7480ed74fcc3963a864..e8027e1d505dda6effbb1698550016e8
NORMAL(false),
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index a2a58dea8bdb5597fc0617e7b5b4fb8ab9d77641..2911b629b8ad1ad36090bdbf87a41f2eec888a0b 100644
index 3dd208c763a71f4211b89a32a936a2317555f265..2ed61f79fc7a625d00b86ee434d591232518ca3c 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -1898,6 +1898,8 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@@ -1938,6 +1938,8 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
void resetCooldown();
/**
@ -962,7 +962,7 @@ index a2a58dea8bdb5597fc0617e7b5b4fb8ab9d77641..2911b629b8ad1ad36090bdbf87a41f2e
* @return the client option value of the player
*/
@NotNull
@@ -1937,6 +1939,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
@@ -1977,6 +1979,9 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
// Paper end
// Spigot start

View File

@ -17,12 +17,12 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java
index 632e53338c4d902aea7e8589152b1c1b6e6dde6a..e64d28359c6f5180f1dfd3896a5ba99fd30a943c 100644
index 85f77a58bf6c21da815b6652c7b50d578951a14c..59a91250d80e6f67a32cb4c7a216f1389338ddbf 100644
--- a/src/main/java/org/bukkit/UnsafeValues.java
+++ b/src/main/java/org/bukkit/UnsafeValues.java
@@ -136,4 +136,28 @@ public interface UnsafeValues {
public int nextEntityId();
@@ -152,4 +152,28 @@ public interface UnsafeValues {
*/
public io.papermc.paper.inventory.ItemRarity getItemStackRarity(ItemStack itemStack);
// Paper end
+
+ // Purpur start

View File

@ -48,10 +48,10 @@ index 229c3b0f0c650b501f31147adaa17194af57fedd..f88cf526d272fe47b5a474c0b344b748
throwable = throwable1;
throw throwable1;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 7ac34a8959a797bf2af96f3f402fa65cffe3d666..80b7ef7c02c8f99b81a6c33d6d969690b933eb36 100644
index afc22e545df03a38c801362d308d135df90361e2..a76137268084e048696b7e8d35e00d26f6766df3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1520,7 +1520,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1524,7 +1524,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
public String getServerModName() {
@ -62,10 +62,10 @@ index 7ac34a8959a797bf2af96f3f402fa65cffe3d666..80b7ef7c02c8f99b81a6c33d6d969690
public CrashReport b(CrashReport crashreport) {
diff --git a/src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java b/src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221aaee80ce
index 0000000000000000000000000000000000000000..cabfcebf9f944f7a2a2a1cffc7401435803a8741
--- /dev/null
+++ b/src/main/java/net/pl3x/purpur/PurpurVersionFetcher.java
@@ -0,0 +1,115 @@
@@ -0,0 +1,119 @@
+package net.pl3x.purpur;
+
+import com.destroystokyo.paper.VersionHistoryManager;
@ -75,6 +75,10 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.TextComponent;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.format.TextDecoration;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
@ -95,15 +99,15 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+
+ @Nonnull
+ @Override
+ public String getVersionMessage(@Nonnull String serverVersion) {
+ public Component getVersionMessage(@Nonnull String serverVersion) {
+ String[] parts = serverVersion.substring("git-Purpur-".length()).split("[-\\s]");
+ String updateMessage = getUpdateStatusMessage("pl3xgaming/Purpur", GITHUB_BRANCH_NAME, parts[0]);
+ String history = getHistory();
+ final Component updateMessage = getUpdateStatusMessage("pl3xgaming/Purpur", GITHUB_BRANCH_NAME, parts[0]);
+ final Component history = getHistory();
+
+ return history != null ? history + "\n" + updateMessage : updateMessage;
+ return history != null ? TextComponent.ofChildren(updateMessage, Component.newline(), history) : updateMessage;
+ }
+
+ private static String getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) {
+ private static Component getUpdateStatusMessage(@Nonnull String repo, @Nonnull String branch, @Nonnull String versionInfo) {
+ int distance;
+ try {
+ int jenkinsBuild = Integer.parseInt(versionInfo);
@ -115,13 +119,13 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+
+ switch (distance) {
+ case -1:
+ return "Error obtaining version information";
+ return Component.text("Error obtaining version information", NamedTextColor.YELLOW);
+ case 0:
+ return "You are running the latest version";
+ return Component.text("You are running the latest version", NamedTextColor.GREEN);
+ case -2:
+ return "Unknown version";
+ return Component.text("Unknown version", NamedTextColor.YELLOW);
+ default:
+ return "You are " + distance + " version(s) behind";
+ return Component.text("You are " + distance + " version(s) behind", NamedTextColor.YELLOW);
+ }
+ }
+
@ -167,7 +171,7 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+ }
+
+ @Nullable
+ private String getHistory() {
+ private Component getHistory() {
+ final VersionHistoryManager.VersionData data = VersionHistoryManager.INSTANCE.getVersionData();
+ if (data == null) {
+ return null;
@ -178,7 +182,7 @@ index 0000000000000000000000000000000000000000..d8b408f061d96e2fa8e2e587462e2221
+ return null;
+ }
+
+ return "Previous version: " + oldVersion;
+ return Component.text("Previous version: " + oldVersion, NamedTextColor.GRAY, TextDecoration.ITALIC);
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@ -195,7 +199,7 @@ index f994e99ebc8fe22e6f6b45f6379ec410a598789f..eeae4862898f093ca4b9819d0d08fdaf
private final String bukkitVersion = Versioning.getBukkitVersion();
private final Logger logger = Logger.getLogger("Minecraft");
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 00e53d577b1dcaccb409e62d35165ee015de9330..7de7afae711800154735411947ff140c76d5171f 100644
index 57d56ff1b41582f0d249b24165d5b08b02b0f9fe..81cff601a5161c30df90de3cefc18d72cd7ee347 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -377,7 +377,7 @@ public final class CraftMagicNumbers implements UnsafeValues {

View File

@ -64,21 +64,8 @@ index 2644b190813cc934914aeab78fbd6515d1a37c4a..e3721b53db68171665ba05201155d088
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // load version history now
// Paper end
com.tuinity.tuinity.config.TuinityConfig.init((java.io.File) options.valueOf("tuinity-settings")); // Tuinity - Server Config
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index bf9732058c7e55e8f1ed38b3b5e8831e6b21706c..90154d2180ebb6a54536884bf89187ca17d11da5 100644
--- a/src/main/java/net/minecraft/server/EntityVillager.java
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
@@ -164,7 +164,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
protected void mobTick() { mobTick(false); }
protected void mobTick(boolean inactive) {
this.world.getMethodProfiler().enter("villagerBrain");
- if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+ if (!inactive) this.getBehaviorController().Wa((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
this.world.getMethodProfiler().exit();
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 970c1be5477a01ab9c6d79e84c519e22775564ff..ee1d5e2dc9fb21190a73e0f333e962a19264dd56 100644
index bf06ef09cfd4d7618365249d1332d264d8ff1377..ed2192ad7b27eb8fc34be5d7817e1ca4bee5c9d1 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 {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Timings stuff
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index 5dfa0658838c4801cdf260eae8b98163f729e5af..dae2e5d70756c5b61163d57099b65f7e415b288c 100644
index 35810f42d7a0cd50a4cbe90e8d698fe57914c889..5e672a0660d0aceffcdb26d185590ca18aa4f023 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -227,10 +227,14 @@ public class TimingsExport extends Thread {

View File

@ -25,7 +25,7 @@ index f034977f4666385d6e7c7288e453d058c270be01..390aae2733e397ac5c6c457c76bf75f9
super(EntityTypes.PLAYER, world);
this.bL = ItemStack.b;
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index f40c24b6e2f7bea21d1cb2b58ed3da45ffcfc866..9315a9f157de3a549c419f8193dc7896a098b472 100644
index c086579073c785b3b7cd556bbb629b91560bd449..e35fdbf915f627c2b9c9ca6314805006aa495e5f 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1940,8 +1940,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -193,7 +193,7 @@ index 9146b60cff0aa06e2f6b6003bfe9e2be9d2f0d56..bba8dc8fd10dc34179ca3c8cf471fbb3
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 9c77be805eb71c409a5d41c2730338583527e447..d8e39d29a792bf8a65884f18743befe29a86791e 100644
index a77fceac7c9e79a6bac05becc21bcb6bf2a1a7c7..be532af2a0de6927a268c631c25f062f370c72ba 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -887,7 +887,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -205,7 +205,7 @@ index 9c77be805eb71c409a5d41c2730338583527e447..d8e39d29a792bf8a65884f18743befe2
})) {
// CraftBukkit start
long l = this.worldData.getDayTime() + 24000L;
@@ -1224,7 +1224,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1231,7 +1231,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
while (iterator.hasNext()) {
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
@ -263,10 +263,10 @@ index 361f7857e461578e90cb71e15027dadaf794cb69..2578a4677d1ee060f687be531e696b7c
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index f965b071cd2f6a70a216679e4f19956115edee4f..8e69ad39102b8a91e664b31a7f07c5212822e961 100644
index b3636032fd36efe2e7e546dbebdfd5c1208f9951..abf2a6b9d18f04baa077ededa3562a30dbaa4fe4 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2427,4 +2427,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2482,4 +2482,21 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
return spigot;
}
// Spigot end

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Configurable server mod name
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 80b7ef7c02c8f99b81a6c33d6d969690b933eb36..5d64157b394b49d638e0295438f235c9492e1128 100644
index a76137268084e048696b7e8d35e00d26f6766df3..27013a6d3cd53778690ee0f45aa0a82994412fa2 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1520,7 +1520,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1524,7 +1524,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
public String getServerModName() {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Lagging threshold
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 5d64157b394b49d638e0295438f235c9492e1128..d9513addae86bd5d2f0c50173318cf4d23ef2128 100644
index 27013a6d3cd53778690ee0f45aa0a82994412fa2..830f3e52b7e5b8604e7c17227476c397912f93c3 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -167,6 +167,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Player invulnerabilities
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 9315a9f157de3a549c419f8193dc7896a098b472..abe8670ec7b0ef4a93418a5e9cf23a1a536cbc96 100644
index e35fdbf915f627c2b9c9ca6314805006aa495e5f..ee1bb58ce2fdaa4cc347476b8f040c346d029cf1 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -154,6 +154,8 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -79,7 +79,7 @@ index bba8dc8fd10dc34179ca3c8cf471fbb3739fa7b4..c586005b34c59710cf398e30924ff365
this.server.getPluginManager().callEvent(new PlayerResourcePackStatusEvent(getPlayer(), packStatus));
// Paper end
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index d03d0c13cca1762078617744253a9757b388958f..00db0f5fb098a4db4092f8ab75a4489cf466baac 100644
index a12e58668e74f2287ddff5bedc00daf2b0a416c1..7f784709ab8c560fd2dae551b6c8c234a2d134c6 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -914,6 +914,8 @@ public abstract class PlayerList {
@ -108,10 +108,10 @@ index 2578a4677d1ee060f687be531e696b7c7be89e84..c441fcea9b2b5a77b801c8a69541cf42
+ }
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 8e69ad39102b8a91e664b31a7f07c5212822e961..ca15efea5da7be1717a211b9b3556c755788561a 100644
index abf2a6b9d18f04baa077ededa3562a30dbaa4fe4..8bf29aca4b5aa0d51ed3cda25b37d30e6c986848 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -2443,5 +2443,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@@ -2498,5 +2498,20 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
public void resetIdleTimer() {
getHandle().resetIdleTimer();
}

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Configurable villager brain ticks
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
index 90154d2180ebb6a54536884bf89187ca17d11da5..1c87bc91515490e2f8579a5321058845c7d30a56 100644
index bf9732058c7e55e8f1ed38b3b5e8831e6b21706c..1c87bc91515490e2f8579a5321058845c7d30a56 100644
--- a/src/main/java/net/minecraft/server/EntityVillager.java
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
@@ -56,6 +56,7 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
@ -24,19 +24,17 @@ index 90154d2180ebb6a54536884bf89187ca17d11da5..1c87bc91515490e2f8579a5321058845
}
@Override
@@ -164,7 +166,11 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
@@ -164,6 +166,10 @@ public class EntityVillager extends EntityVillagerAbstract implements Reputation
protected void mobTick() { mobTick(false); }
protected void mobTick(boolean inactive) {
this.world.getMethodProfiler().enter("villagerBrain");
- if (!inactive) this.getBehaviorController().Wa((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
+ // Purpur start
+ boolean tick = (world.getTime() + brainTickOffset) % world.purpurConfig.villagerBrainTicks == 0;
+ if (((WorldServer) world).getMinecraftServer().lagging ? tick : world.purpurConfig.villagerUseBrainTicksOnlyWhenLagging || tick)
+ // Purpur end
+ if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
if (!inactive) this.getBehaviorController().a((WorldServer) this.world, this); // CraftBukkit - decompile error // Paper
this.world.getMethodProfiler().exit();
if (this.bF) {
this.bF = false;
diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java
index c441fcea9b2b5a77b801c8a69541cf42050927dc..c7fb5a737cab0083c39732247acb8f4e87562894 100644
--- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java

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 d8e39d29a792bf8a65884f18743befe29a86791e..428f43a37d5aa6e0bf363baeef02b0fa01951590 100644
index be532af2a0de6927a268c631c25f062f370c72ba..4f0159cd0b7a438084a3fc9cf681dbce6e41a125 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1101,12 +1101,18 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1104,12 +1104,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

@ -62,7 +62,7 @@ index 5e17868a76ea8e3f105c11d496d6da12afa0da41..5a0f8779672a9e34f6970045361630ab
}
diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java
index fce9967912628c232fe41ccc17fe2296f001ec61..44063d599e39e087b3eccfe204ef2fd79c3364e5 100644
index 245bdedd17b844dcd13aa0b60dffb1cac6a5bdb8..64e251fb63e67b9ebf11779580b1bff6def6d1c6 100644
--- a/src/main/java/net/minecraft/server/VillagePlace.java
+++ b/src/main/java/net/minecraft/server/VillagePlace.java
@@ -178,6 +178,7 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Ender dragon always drop full exp
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index 7289d6c706b6c845584bac616c9babea80f8e885..f777aea69dc9949aae3251e9a530b8cffb251bad 100644
index 50b93c93cfede2d64a996a22b811994b352149af..de025a48c7ca08d8ae71d2d9239121dc4a86a339 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -564,7 +564,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Signs allow color codes
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index abe8670ec7b0ef4a93418a5e9cf23a1a536cbc96..cdc559a8330d804a269f942f5bcba84ab9ea4289 100644
index ee1bb58ce2fdaa4cc347476b8f040c346d029cf1..4cd9937d97343e33a4c417b4a7af9ee2601b18b0 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1449,6 +1449,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -106,7 +106,7 @@ index be859a1b41254b299a507d03e453dc8efee6f3dd..4de2877f30a9b231a5c8bbd173941699
this.move(EnumMoveType.SELF, this.getMot());
if (!this.onGround) {
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index cdc559a8330d804a269f942f5bcba84ab9ea4289..320719bcc43b69a4dcca53d431a1eb4af0034c71 100644
index 4cd9937d97343e33a4c417b4a7af9ee2601b18b0..f200faf78ab887d1b58677e20039765cb67ac6b8 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1002,6 +1002,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Players should not cram to death
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 320719bcc43b69a4dcca53d431a1eb4af0034c71..572a2546acb6decc9fabfc77a2073bab3e0f5abf 100644
index f200faf78ab887d1b58677e20039765cb67ac6b8..ce48b823db35ca2d7557cfc840801349b19cbd54 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1426,7 +1426,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Add permission for F3+N debug
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 00db0f5fb098a4db4092f8ab75a4489cf466baac..86f534c871a3c9b9ca71b20daa7780dfdab9e76d 100644
index 7f784709ab8c560fd2dae551b6c8c234a2d134c6..f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -1073,6 +1073,7 @@ public abstract class PlayerList {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Configurable TPS Catchup
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index d9513addae86bd5d2f0c50173318cf4d23ef2128..50f1841e3d5e92d6186db49ac4962c0bac943a8c 100644
index 830f3e52b7e5b8604e7c17227476c397912f93c3..d1d5216f14fd2fb9b3bebcdb3864bbaed1f3d5c2 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1010,7 +1010,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Add 5 second tps average in /tps
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 50f1841e3d5e92d6186db49ac4962c0bac943a8c..a3ddf2839738e089a02d841f5b6fd759c3047305 100644
index d1d5216f14fd2fb9b3bebcdb3864bbaed1f3d5c2..1fa06582ff843e62a8a4701d98b3f5cad8770a73 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -166,7 +166,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -221,10 +221,10 @@ index 4e3f01bc79b6ed2a322155f29f1d0dcf298c8b82..ac1ea2f0c15bccf94f203194a5a7b10e
}
}
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index a77b1d61b9dcb0a2a27d7e50357eaf44c99a661e..ae17950438132c5084210252bd345517131d5a99 100644
index 53fd0549c965b2252ad80648d61ff1f7cd2b837a..ad520cb36afd0f011b6337f3e42efb01f740a950 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 {
@@ -394,6 +394,7 @@ public final class SpawnerCreature {
return new BlockPosition(i, l, j);
}
@ -233,7 +233,7 @@ index a77b1d61b9dcb0a2a27d7e50357eaf44c99a661e..ae17950438132c5084210252bd345517
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 ee1d5e2dc9fb21190a73e0f333e962a19264dd56..8246bdf5e686c2089397e8669cf37968ef3de80d 100644
index ed2192ad7b27eb8fc34be5d7817e1ca4bee5c9d1..905ec2bee2f47d9126b77a5bc1abfc4941b42815 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1597,6 +1597,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

View File

@ -49,7 +49,7 @@ index 223361a1a8b41ebe91e0db39f40cf12a4968b1b4..07f23572bdf15c57a53e32646f2fc64f
return true;
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 8246bdf5e686c2089397e8669cf37968ef3de80d..d3b3b771640a46ce9a898f645cf50007e25ae7c2 100644
index 905ec2bee2f47d9126b77a5bc1abfc4941b42815..d86a23c6febc638080c0d26857839918db22ce93 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1672,4 +1672,14 @@ public abstract class World implements GeneratorAccess, AutoCloseable {

View File

@ -17,7 +17,7 @@ index 8bc0fb58ef18ce7828451857a97460bbde567c6b..a8cd7f0abf58e69d276e469bd7d5ef6a
}
}
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 572a2546acb6decc9fabfc77a2073bab3e0f5abf..6052643bbe1ee12bcf98126e36fc09bd2593dfa6 100644
index ce48b823db35ca2d7557cfc840801349b19cbd54..2aef37c4602d9c3ec12a2b5deade36801c171be0 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -2425,4 +2425,26 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Populator seed controls
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index dae2e5d70756c5b61163d57099b65f7e415b288c..55b67f1057224101272f9d6023a93872c4423405 100644
index 5e672a0660d0aceffcdb26d185590ca18aa4f023..4b171a2a60e24947e884f8988920f335bd99a471 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -293,7 +293,7 @@ public class TimingsExport extends Thread {
@ -18,7 +18,7 @@ index dae2e5d70756c5b61163d57099b65f7e415b288c..55b67f1057224101272f9d6023a93872
}
final Object val = config.get(key);
diff --git a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java
index 0959aa6855a150b121b9b75885216c46b151179e..b181b22cdd78f9ddeea38f315a5dc856134d1c58 100644
index eb53f0a9012884ce2ab6b6d8cfeefaffa3a48ead..8f95c3c22a4f3f90f001e34ded081708ede59454 100644
--- a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java
+++ b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java
@@ -1,5 +1,6 @@
@ -28,7 +28,7 @@ index 0959aa6855a150b121b9b75885216c46b151179e..b181b22cdd78f9ddeea38f315a5dc856
import com.destroystokyo.paper.util.SneakyThrow;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.TicketType;
@@ -382,6 +383,19 @@ public final class TuinityConfig {
@@ -401,6 +402,19 @@ public final class TuinityConfig {
this.spawnLimitAmbient = this.getInt(path + ".ambient", -1);
}
@ -50,10 +50,10 @@ index 0959aa6855a150b121b9b75885216c46b151179e..b181b22cdd78f9ddeea38f315a5dc856
}
\ No newline at end of file
diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java
index 0854ac9ef586b378420d9899f3afd2755e6f9f33..df6874c1cf5fc5764dc575866aab87883b6cf035 100644
index 3fc101552e3c229076c91a1cfa45206b4cc7a04c..60d5c08706dc8b2f895ff7083d3a611a73ac19d2 100644
--- a/src/main/java/net/minecraft/server/BiomeBase.java
+++ b/src/main/java/net/minecraft/server/BiomeBase.java
@@ -189,6 +189,10 @@ public final class BiomeBase {
@@ -227,6 +227,10 @@ public final class BiomeBase {
return this.k;
}
@ -64,7 +64,7 @@ index 0854ac9ef586b378420d9899f3afd2755e6f9f33..df6874c1cf5fc5764dc575866aab8788
public void a(StructureManager structuremanager, ChunkGenerator chunkgenerator, RegionLimitedWorldAccess regionlimitedworldaccess, long i, SeededRandom seededrandom, BlockPosition blockposition) {
List<List<Supplier<WorldGenFeatureConfigured<?, ?>>>> list = this.k.c();
int j = WorldGenStage.Decoration.values().length;
@@ -225,12 +229,24 @@ public final class BiomeBase {
@@ -263,12 +267,24 @@ public final class BiomeBase {
}
}

View File

@ -22,7 +22,7 @@ index 829d4a7508e1656dbdc912096b7eafcf30cbb5b2..6aea156d7c7a9ca8a357aad6a6781d72
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 428f43a37d5aa6e0bf363baeef02b0fa01951590..59301aad8c257758cb0fe9709901847925d60be4 100644
index 4f0159cd0b7a438084a3fc9cf681dbce6e41a125..af7c9562cb7eac9d1e985d5337c8d127d875bcfb 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -418,14 +418,14 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -1175,7 +1175,7 @@ index 1a102816921fa3b40f6d364bb826db4459f68eb2..125eab60f2b4657e52a71eddf7586c57
@Override
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index f777aea69dc9949aae3251e9a530b8cffb251bad..497d05996ab84f599aa0a02f853149f074e4d3cb 100644
index de025a48c7ca08d8ae71d2d9239121dc4a86a339..81e63fe1b8252e2b5abcbf9051190cd0214b534c 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -46,6 +46,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
@ -3194,7 +3194,7 @@ index a3a428da99574c485fcf2b8c7944e0d8354146ee..cf7de0127166f6175a6246062c8664e6
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget<>(this, EntityHuman.class, true));
this.targetSelector.a(3, new PathfinderGoalNearestAttackableTarget<>(this, EntityVillagerAbstract.class, false));
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 6052643bbe1ee12bcf98126e36fc09bd2593dfa6..dbc7ca05503dd3de6d4ffe50433d9f2284016191 100644
index 2aef37c4602d9c3ec12a2b5deade36801c171be0..04879594b5157d2e0ed7c464bcea52fa937fa68f 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -512,6 +512,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
@ -4469,7 +4469,7 @@ index ca3c5150bcfe2a92b49ad5a27c23dd37a7054fbb..323d79a99402b0f6952b4fb873170069
this.targetSelector.a(2, this.br);
this.targetSelector.a(3, this.bs);
diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java
index b1159f0258eca2bee52ec0939ba86792d24a1f99..6fc097d2ae11ec5d1c12ce070c8d69d2249cf3c7 100644
index 3230c5454ccc39a2e3c89fdf8ca015cf7a15f380..e7c558e268f77cc6451b3a8fe502465dfc017cec 100644
--- a/src/main/java/net/minecraft/server/EntityWither.java
+++ b/src/main/java/net/minecraft/server/EntityWither.java
@@ -32,6 +32,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {
@ -4889,7 +4889,7 @@ index dc9f2a1a132b3a7925bd62aa1da0512afd90b8b1..b7e540dfeeabb13227596ecfc6eddabf
Entity entity1 = this.getShooter();
// Paper start - Cancel hit for vanished players
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index a3ddf2839738e089a02d841f5b6fd759c3047305..85c14df768ec844b710bf2b32eb7f85c9e6b47ea 100644
index 1fa06582ff843e62a8a4701d98b3f5cad8770a73..16a03a92b786da366ecf84b3cc79499654d0a899 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1418,6 +1418,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -4972,10 +4972,10 @@ index b2c64b31440389db5abe2322f7e31b328f590f6c..515ba50aec81497d27297e4b6c642e86
Vec3D vec3d = entity.getMot();
World world = entity.world;
diff --git a/src/main/java/net/minecraft/server/Vec3D.java b/src/main/java/net/minecraft/server/Vec3D.java
index 5af554870bcf36e47aef43b966b141b9eda6c4d5..c59305ef7dd7847e204d4c4ed79758bf9d66e91e 100644
index 7190316a38e6b4edf5501bfedbb12be79e990797..4469fdc932d725b8e6fa4f8e3ec15c22a88ca5e7 100644
--- a/src/main/java/net/minecraft/server/Vec3D.java
+++ b/src/main/java/net/minecraft/server/Vec3D.java
@@ -39,6 +39,7 @@ public class Vec3D implements IPosition {
@@ -45,6 +45,7 @@ public class Vec3D implements IPosition {
return new Vec3D(vec3d.x - this.x, vec3d.y - this.y, vec3d.z - this.z);
}
@ -4983,7 +4983,7 @@ index 5af554870bcf36e47aef43b966b141b9eda6c4d5..c59305ef7dd7847e204d4c4ed79758bf
public Vec3D d() {
double d0 = (double) MathHelper.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
@@ -98,6 +99,7 @@ public class Vec3D implements IPosition {
@@ -104,6 +105,7 @@ public class Vec3D implements IPosition {
return d3 * d3 + d4 * d4 + d5 * d5;
}
@ -4991,7 +4991,7 @@ index 5af554870bcf36e47aef43b966b141b9eda6c4d5..c59305ef7dd7847e204d4c4ed79758bf
public Vec3D a(double d0) {
return this.d(d0, d0, d0);
}
@@ -106,6 +108,7 @@ public class Vec3D implements IPosition {
@@ -112,6 +114,7 @@ public class Vec3D implements IPosition {
return this.d(vec3d.x, vec3d.y, vec3d.z);
}
@ -5000,7 +5000,7 @@ 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 d3b3b771640a46ce9a898f645cf50007e25ae7c2..34e5f8b3bf1b0045856ec0d06ec6d62d0b976862 100644
index d86a23c6febc638080c0d26857839918db22ce93..af46e9ccfcc24e8222fdd49d66c3ba2057633021 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1681,5 +1681,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -5015,7 +5015,7 @@ index d3b3b771640a46ce9a898f645cf50007e25ae7c2..34e5f8b3bf1b0045856ec0d06ec6d62d
// Purpur end
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 59301aad8c257758cb0fe9709901847925d60be4..33b41dc393e302c114f2ea69e789505b7ec77935 100644
index af7c9562cb7eac9d1e985d5337c8d127d875bcfb..ee74d3a9bb6938c83509fa09840a1c243d03c389 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] Customizable wither health and healing
Adds the ability to customize the health of the wither, as well as the amount that it heals, and how often.
diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java
index 6fc097d2ae11ec5d1c12ce070c8d69d2249cf3c7..c9037d847b12a705194a0bd70f11c5dae8f50bfa 100644
index e7c558e268f77cc6451b3a8fe502465dfc017cec..9b9eeb14776c09415823e0d5e313e44e51deb43a 100644
--- a/src/main/java/net/minecraft/server/EntityWither.java
+++ b/src/main/java/net/minecraft/server/EntityWither.java
@@ -150,6 +150,11 @@ public class EntityWither extends EntityMonster implements IRangedEntity {

View File

@ -29,7 +29,7 @@ index 341af7474690b929cfa3e35cd464bbbbacb6685e..ad00ff2bd525768e4f06631d16b912c6
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 34e5f8b3bf1b0045856ec0d06ec6d62d0b976862..d72580deaa50617b5b6a991777f4b36c138308a6 100644
index af46e9ccfcc24e8222fdd49d66c3ba2057633021..452dbbf572ad38716c81ae90873884076c1abc6f 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -187,7 +187,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
@ -42,7 +42,7 @@ index 34e5f8b3bf1b0045856ec0d06ec6d62d0b976862..d72580deaa50617b5b6a991777f4b36c
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 33b41dc393e302c114f2ea69e789505b7ec77935..adc6420b63730929de491cb0a57d898ef02bb7e8 100644
index ee74d3a9bb6938c83509fa09840a1c243d03c389..baeca1fcb81c9f83e488a23be3cf66de3af65ba1 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -436,7 +436,24 @@ public class WorldServer extends World implements GeneratorAccessSeed {

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 adc6420b63730929de491cb0a57d898ef02bb7e8..2c73ddae3df32eea175fb1779104441b49796939 100644
index baeca1fcb81c9f83e488a23be3cf66de3af65ba1..877ba68edec7b8b444ea7cd849fdcb337cfbc60d 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 {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Add tablist suffix option for afk
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index dbc7ca05503dd3de6d4ffe50433d9f2284016191..6071e5f141c04813d0f8af07d82d80bec7f0c194 100644
index 04879594b5157d2e0ed7c464bcea52fa937fa68f..78abdcdc9e6eee80ee88454e5020ad26d7abe3fd 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1991,7 +1991,11 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -33,7 +33,7 @@ index b290218e506d5e4ddd1af17f91de19a588bbcfbd..cf9be4be18e913e49e9150358c66138b
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 d72580deaa50617b5b6a991777f4b36c138308a6..87766db4e3c2e522b738fa304a861dc0985d878a 100644
index 452dbbf572ad38716c81ae90873884076c1abc6f..abd415f02d8b4c28602b6c4aefc0914b5a83165b 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 {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Set name visible when using a Name Tag on an Armor Stand
diff --git a/src/main/java/net/minecraft/server/ItemNameTag.java b/src/main/java/net/minecraft/server/ItemNameTag.java
index a34772e329df62d9176b0aa392197e2771c69da4..b6f2270aae3422f5ee5bae0f955f5807f5cadf59 100644
index a34772e329df62d9176b0aa392197e2771c69da4..facaca3622e028e315b822a61ed40ba518de2720 100644
--- a/src/main/java/net/minecraft/server/ItemNameTag.java
+++ b/src/main/java/net/minecraft/server/ItemNameTag.java
@@ -20,6 +20,11 @@ public class ItemNameTag extends Item {
@ -13,8 +13,8 @@ index a34772e329df62d9176b0aa392197e2771c69da4..b6f2270aae3422f5ee5bae0f955f5807
EntityLiving newEntityLiving = ((org.bukkit.craftbukkit.entity.CraftLivingEntity) event.getEntity()).getHandle();
newEntityLiving.setCustomName(event.getName() != null ? PaperAdventure.asVanilla(event.getName()) : null);
+ // Purpur start
+ if (entityhuman.world.purpurConfig.armorstandFixNametags && newEntityLiving instanceof EntityArmorStand) {
+ newEntityLiving.setCustomNameVisible(true);
+ if (entityhuman.world.purpurConfig.armorstandFixNametags && entityliving instanceof EntityArmorStand) {
+ entityliving.setCustomNameVisible(true);
+ }
+ // Purpur end
if (event.isPersistent() && newEntityLiving instanceof EntityInsentient) {

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Origami - Fix ProtocolLib issues on Java 15
diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java
index 65de374d485f31f8cd6f4e03941173565074ea0e..ea86843fa0313da15b905cbd712c15e7b217daa4 100644
index d93634391501da01cb1afe70fedd5247c654e8fc..53b5063b43e42f09c2ef335251c91d2051676972 100644
--- a/src/main/java/net/minecraft/server/NetworkManager.java
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
@@ -394,9 +394,9 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
@@ -416,9 +416,9 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
// note: since the type is not dynamic here, we need to actually copy the old executor code
// into two branches. On conflict, just re-copy - no changes were made inside the executor code.
if (flush) {
@ -20,7 +20,7 @@ index 65de374d485f31f8cd6f4e03941173565074ea0e..ea86843fa0313da15b905cbd712c15e7
}
// Paper start
@@ -406,7 +406,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
@@ -428,7 +428,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
}
try {
// Paper end
@ -29,7 +29,7 @@ index 65de374d485f31f8cd6f4e03941173565074ea0e..ea86843fa0313da15b905cbd712c15e7
if (genericfuturelistener != null) {
@@ -426,12 +426,12 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
@@ -448,12 +448,12 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
packet.onPacketDispatchFinish(player, null);
}
// Paper end
@ -45,7 +45,7 @@ index 65de374d485f31f8cd6f4e03941173565074ea0e..ea86843fa0313da15b905cbd712c15e7
}
// Paper start
@@ -441,7 +441,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
@@ -463,7 +463,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
}
try {
// Paper end
@ -54,7 +54,7 @@ index 65de374d485f31f8cd6f4e03941173565074ea0e..ea86843fa0313da15b905cbd712c15e7
if (genericfuturelistener != null) {
@@ -461,7 +461,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
@@ -483,7 +483,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
packet.onPacketDispatchFinish(player, null);
}
// Paper end

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Add boat fall damage config
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 6071e5f141c04813d0f8af07d82d80bec7f0c194..44a10c656c9b131c8889da81b7999dc492077e58 100644
index 78abdcdc9e6eee80ee88454e5020ad26d7abe3fd..100472ab38414f6d393f86a790837e448c7db381 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1011,7 +1011,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -76,7 +76,7 @@ index 15e052cb844df310c62d8a5695e8da6c633d94b6..a04123b5897a150439846abe5b25a3a1
long i = this.bC + 12000L;
long j = this.world.getTime();
diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index b92ca4a6de01f3f86367fb8dfe3591b08a3e9218..1208464fba96daf276c9cc0c1c9b18db75b03abc 100644
index 6aec5098d346c1b7498fd8b800154cd31ce08a97..cba6f414d1a673e735f80662620a8bec78cd09ab 100644
--- a/src/main/java/net/minecraft/server/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java
@@ -101,6 +101,7 @@ public abstract class NavigationAbstract {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Spread out and optimise player list ticks
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 86f534c871a3c9b9ca71b20daa7780dfdab9e76d..d454b6c61c1a7d0ae9d6c2979cb865531acf405f 100644
index f9043744ad0a622c6aa5e5bd3986fb9f60cab4c3..4415d081983d46bcece9b80bad6f3b5cdc624a4e 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -68,7 +68,7 @@ public abstract class PlayerList {
@ -56,7 +56,7 @@ index 86f534c871a3c9b9ca71b20daa7780dfdab9e76d..d454b6c61c1a7d0ae9d6c2979cb86553
public void sendAll(Packet<?> packet) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index ca15efea5da7be1717a211b9b3556c755788561a..400e26c96f00e9f8895a45e70f22552ec17f2436 100644
index 8bf29aca4b5aa0d51ed3cda25b37d30e6c986848..7b5ffe92430121eebe2866ac33b37a840eed90f1 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1435,7 +1435,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player {

View File

@ -188,7 +188,7 @@ index 638efc67d66001ee085957d4698f51a7daac77fc..a766910663e47b05d1e38908b5db7471
@Override
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index 497d05996ab84f599aa0a02f853149f074e4d3cb..29c8e1b67396df160cdb7ecf4e1a563fc1acd5ac 100644
index 81e63fe1b8252e2b5abcbf9051190cd0214b534c..75e834caaf7bb64a3d51d793e86aa702f6ccb0ae 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -97,6 +97,11 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {

View File

@ -17,7 +17,7 @@ index b5cc099746e9f05ea69bc438bda22a5ac3ebc3c5..bbd17231a4f7ad0ddde6eb5e589a6c40
if (commanddispatcher_servertype.d) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 85c14df768ec844b710bf2b32eb7f85c9e6b47ea..17591457a33e6994cd26bb1487a7879a11411a9c 100644
index 16a03a92b786da366ecf84b3cc79499654d0a899..be48e686272b81dab4f1f584d946e15285934e88 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -472,6 +472,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -37,7 +37,7 @@ index 85c14df768ec844b710bf2b32eb7f85c9e6b47ea..17591457a33e6994cd26bb1487a7879a
this.isRestarting = isRestarting;
this.hasLoggedStop = true; // Paper
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index d454b6c61c1a7d0ae9d6c2979cb865531acf405f..f80371ce1665d0760ad0553a2a057a955c56669c 100644
index 4415d081983d46bcece9b80bad6f3b5cdc624a4e..3a4165efa33cce86457092c29d2cf2aced42f43d 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -513,6 +513,8 @@ public abstract class PlayerList {

View File

@ -58,7 +58,7 @@ index 0f147dc938cef428452bd3137c68b52a78f9fbde..276aac9afd5d987cf388a87718453c47
return true;
// Purpur end
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index 29c8e1b67396df160cdb7ecf4e1a563fc1acd5ac..fd019a7d8940150ba776e211fe5f7ecb4ffbc89c 100644
index 75e834caaf7bb64a3d51d793e86aa702f6ccb0ae..e2377c6e8a98be431953533bf0b2060028caad45 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -489,7 +489,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
@ -246,7 +246,7 @@ index 1dd13dfea91a05b1e83b065328092a17d41a605f..eb6344a5671408ae9fdd6013774baa13
}
diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java
index c9037d847b12a705194a0bd70f11c5dae8f50bfa..8679f9f5210632349915558016c3273f5ef0527d 100644
index 9b9eeb14776c09415823e0d5e313e44e51deb43a..7d5183cd2121092f7342a282ba98f659f10f19f8 100644
--- a/src/main/java/net/minecraft/server/EntityWither.java
+++ b/src/main/java/net/minecraft/server/EntityWither.java
@@ -323,7 +323,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {

View File

@ -123,7 +123,7 @@ index 5471422d23d261a06c67f9374cae933430ec03a0..4c592f6d4d6cbeb4c3225e7794f4b1d6
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 400e26c96f00e9f8895a45e70f22552ec17f2436..ec450146f82b656616c8b60cc05d727437eaa0b6 100644
index 7b5ffe92430121eebe2866ac33b37a840eed90f1..98f4407848347dfc46b70d1c1fe466dce10f54b7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -117,6 +117,7 @@ import org.bukkit.entity.EntityType;

View File

@ -25,7 +25,7 @@ index 85ffb2e72dbf08604c004732f17aee9ec7e1ff9d..49a1447bae91294a23ccab27c2809bea
this.inPortal = true;
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 44a10c656c9b131c8889da81b7999dc492077e58..ac9238e1de65efe9fea7d9e623478c61066e8d68 100644
index 100472ab38414f6d393f86a790837e448c7db381..eb62597449081656a05073e5bbf878f893166b53 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1161,6 +1161,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -46,7 +46,7 @@ index 4c592f6d4d6cbeb4c3225e7794f4b1d6c8d62394..b441dac8f31b679aa7e36d23848d34e2
// Purpur end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 7de7afae711800154735411947ff140c76d5171f..b14e9a2cd6e849fe91a2512f379036a284323420 100644
index 81cff601a5161c30df90de3cefc18d72cd7ee347..980696490709d04741c1617f528357100696d0e5 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -390,9 +390,14 @@ public final class CraftMagicNumbers implements UnsafeValues {

View File

@ -18,7 +18,7 @@ index 49a1447bae91294a23ccab27c2809bea0c4c90a3..94af972e115491d0f4394dd290ec2d9d
}
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index fd019a7d8940150ba776e211fe5f7ecb4ffbc89c..9e27d3ccfd6a5ee00cac72c3137189b1be1f81fb 100644
index e2377c6e8a98be431953533bf0b2060028caad45..a495c14b9f168884a0bba6b95d28c9ecfa9dfdab 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -1023,6 +1023,7 @@ public class EntityEnderDragon extends EntityInsentient implements IMonster {
@ -30,7 +30,7 @@ index fd019a7d8940150ba776e211fe5f7ecb4ffbc89c..9e27d3ccfd6a5ee00cac72c3137189b1
}
diff --git a/src/main/java/net/minecraft/server/EntityWither.java b/src/main/java/net/minecraft/server/EntityWither.java
index 8679f9f5210632349915558016c3273f5ef0527d..e238352bd41069936da2860b707f071c9aef0062 100644
index 7d5183cd2121092f7342a282ba98f659f10f19f8..2c81a5d1381afa37b966625d3a6ec6cf603f466d 100644
--- a/src/main/java/net/minecraft/server/EntityWither.java
+++ b/src/main/java/net/minecraft/server/EntityWither.java
@@ -673,6 +673,7 @@ public class EntityWither extends EntityMonster implements IRangedEntity {

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Config to ignore nearby mobs when sleeping
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index ac9238e1de65efe9fea7d9e623478c61066e8d68..93bca6a52dd01d9ad524a03d90c7ec79d00d2c56 100644
index eb62597449081656a05073e5bbf878f893166b53..e384a24d9b46587f66ee3e712a8206b1ca1f3877 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -1311,7 +1311,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {

View File

@ -1,13 +1,165 @@
Copyright 2018-2020 Robert Norman
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -0,0 +1,112 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 29 Jan 2021 16:26:05 -0800
Subject: [PATCH] Per player viewdistances
Add per player no-tick, tick, and send view distances.
Also add send view distance to World.
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index 064497506e6a5ab89ca43b99968ca79d51d67c46..5848c8c03a1520b95c9f494e0820e075f1757fc6 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -3508,6 +3508,26 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad
* @param viewDistance view distance in [2, 32]
*/
void setNoTickViewDistance(int viewDistance);
+
+ // Tuinity start - add view distances
+ /**
+ * Gets the sending view distance for this world.
+ * <p>
+ * Sending view distance is the view distance where chunks will load in for players in this world.
+ * </p>
+ * @return The sending view distance for this world.
+ */
+ public int getSendViewDistance();
+
+ /**
+ * Sets the sending view distance for this world.
+ * <p>
+ * Sending view distance is the view distance where chunks will load in for players in this world.
+ * </p>
+ * @param viewDistance view distance in [2, 32] or -1
+ */
+ public void setSendViewDistance(int viewDistance);
+ // Tuinity end - add view distances
// Paper end - view distance api
// Spigot start
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 2ea531eaef8c455fdd503f0c0258813fe9136085..a84ea92d02d34cd48174152e0391f1af6c6b5def 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -1768,23 +1768,63 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
* Gets the view distance for this player
*
* @return the player's view distance
- * @deprecated This is unimplemented and <i>will</i> throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work.
+ * // Tuinity - implemented
* @see org.bukkit.World#getViewDistance()
* @see org.bukkit.World#getNoTickViewDistance()
*/
- @Deprecated
+ //@Deprecated // Tuinity - implemented
public int getViewDistance();
/**
* Sets the view distance for this player
*
* @param viewDistance the player's view distance
- * @deprecated This is unimplemented and <i>will</i> throw an exception at runtime. The {@link org.bukkit.World World}-based methods still work.
+ * // Tuinity - implemented
* @see org.bukkit.World#setViewDistance(int)
* @see org.bukkit.World#setNoTickViewDistance(int)
*/
- @Deprecated
+ //@Deprecated // Tuinity - implemented
public void setViewDistance(int viewDistance);
+
+ // Tuinity start - add view distances api
+ /**
+ * Gets the no-ticking view distance for this player.
+ * <p>
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
+ * be set to tick.
+ * </p>
+ * @return The no-tick view distance for this player.
+ */
+ public int getNoTickViewDistance();
+
+ /**
+ * Sets the no-ticking view distance for this player.
+ * <p>
+ * No-tick view distance is the view distance where chunks will load, however the chunks and their entities will not
+ * be set to tick.
+ * </p>
+ * @param viewDistance view distance in [2, 32] or -1
+ */
+ public void setNoTickViewDistance(int viewDistance);
+
+ /**
+ * Gets the sending view distance for this player.
+ * <p>
+ * Sending view distance is the view distance where chunks will load in for players.
+ * </p>
+ * @return The sending view distance for this player.
+ */
+ public int getSendViewDistance();
+
+ /**
+ * Sets the sending view distance for this player.
+ * <p>
+ * Sending view distance is the view distance where chunks will load in for players.
+ * </p>
+ * @param viewDistance view distance in [2, 32] or -1
+ */
+ public void setSendViewDistance(int viewDistance);
+ // Tuinity end - add view distances api
// Paper end
/**

View File

@ -78,3 +78,679 @@ index 22bde395939f97086e411cef190bb2b1e7ede79a..ac32e19afe7255fedecc2cadbc47d2a3
//System.err.println("*** Server will start in 20 seconds ***");
//Thread.sleep(TimeUnit.SECONDS.toMillis(20));
// Paper End
diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png
index a7d785f60c884ee4ee487cc364402d66c3dc2ecc..1e6ee83b1a207eca59d82b25c06895ce894e8173 100644
GIT binary patch
literal 23418
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
literal 14310
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%0ABLt+m?son?j
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
WX&3$!%>|s_1IbA#OV)^+1pg1OmmZn`

View File

@ -6,14 +6,12 @@ Subject: [PATCH] Util patch
diff --git a/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881be124e46c
index 0000000000000000000000000000000000000000..6985b1df450a3b2b9e9c4696fef60652cb84fa2c
--- /dev/null
+++ b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
@@ -0,0 +1,488 @@
@@ -0,0 +1,477 @@
+package com.tuinity.tuinity.chunk;
+
+import co.aikar.timings.MinecraftTimings;
+import co.aikar.timings.Timing;
+import com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
@ -23,44 +21,40 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+import net.minecraft.server.WorldServer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public final class SingleThreadChunkRegionManager<T extends Enum<T> & SingleThreadChunkRegionManager.RegionDataCreator<T>> {
+public final class SingleThreadChunkRegionManager {
+
+ static final int REGION_SECTION_MERGE_RADIUS = 1;
+ // if this becomes > 8, then the RegionSection needs to be properly modified (see bitset)
+ public static final int REGION_CHUNK_SIZE = 32;
+ public static final int REGION_CHUNK_SIZE_SHIFT = 5; // log2(REGION_CHUNK_SIZE)
+ protected final int regionSectionMergeRadius;
+ protected final int regionSectionChunkSize;
+ public final int regionChunkShift; // log2(REGION_CHUNK_SIZE)
+
+ public final WorldServer world;
+ public final Class<T> dataClass;
+ public final String name;
+
+ public final Timing addChunkTimings;
+ public final Timing removeChunkTimings;
+ public final Timing regionRecalculateTimings;
+
+ protected final Long2ObjectOpenHashMap<RegionSection<T>> regionsBySection = new Long2ObjectOpenHashMap<>();
+ protected final ReferenceLinkedOpenHashSet<Region<T>> needsRecalculation = new ReferenceLinkedOpenHashSet<>();
+ protected final Long2ObjectOpenHashMap<RegionSection> regionsBySection = new Long2ObjectOpenHashMap<>();
+ protected final ReferenceLinkedOpenHashSet<Region> needsRecalculation = new ReferenceLinkedOpenHashSet<>();
+ protected final int minSectionRecalcCount;
+ protected final double maxDeadRegionPercent;
+ protected final Supplier<RegionData> regionDataSupplier;
+ protected final Supplier<RegionSectionData> regionSectionDataSupplier;
+
+ public SingleThreadChunkRegionManager(final WorldServer world, final Class<T> enumClass,
+ final int minSectionRecalcCount, final double maxDeadRegionPercent,
+ final String name) {
+ public SingleThreadChunkRegionManager(final WorldServer world, final int minSectionRecalcCount,
+ final double maxDeadRegionPercent, final int sectionMergeRadius,
+ final int regionSectionChunkShift,
+ final String name, final Supplier<RegionData> regionDataSupplier,
+ final Supplier<RegionSectionData> regionSectionDataSupplier) {
+ this.regionSectionMergeRadius = sectionMergeRadius;
+ this.regionSectionChunkSize = 1 << regionSectionChunkShift;
+ this.regionChunkShift = regionSectionChunkShift;
+ this.world = world;
+ this.dataClass = enumClass;
+ this.name = name;
+ this.minSectionRecalcCount = Math.max(2, minSectionRecalcCount);
+ this.maxDeadRegionPercent = maxDeadRegionPercent;
+
+ String prefix = world.getWorld().getName() + " - Region Manager - " + name + " - ";
+ this.addChunkTimings = MinecraftTimings.getInternalTaskName(prefix.concat("add"));
+ this.removeChunkTimings = MinecraftTimings.getInternalTaskName(prefix.concat("remove"));
+ this.regionRecalculateTimings = MinecraftTimings.getInternalTaskName(prefix.concat("recalculate"));
+ this.regionDataSupplier = regionDataSupplier;
+ this.regionSectionDataSupplier = regionSectionDataSupplier;
+ }
+
+ // tested via https://gist.github.com/Spottedleaf/aa7ade3451c37b4cac061fc77074db2f
@ -80,51 +74,51 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ */
+
+ protected void addToRecalcQueue(final Region<T> region) {
+ protected void addToRecalcQueue(final Region region) {
+ this.needsRecalculation.add(region);
+ }
+
+ protected void removeFromRecalcQueue(final Region<T> region) {
+ protected void removeFromRecalcQueue(final Region region) {
+ this.needsRecalculation.remove(region);
+ }
+
+ public RegionSection<T> getRegionSection(final int chunkX, final int chunkZ) {
+ return this.regionsBySection.get(MCUtil.getCoordinateKey(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT));
+ public RegionSection getRegionSection(final int chunkX, final int chunkZ) {
+ return this.regionsBySection.get(MCUtil.getCoordinateKey(chunkX >> this.regionChunkShift, chunkZ >> this.regionChunkShift));
+ }
+
+ public Region<T> getRegion(final int chunkX, final int chunkZ) {
+ final RegionSection<T> section = this.regionsBySection.get(MCUtil.getCoordinateKey(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT));
+ public Region getRegion(final int chunkX, final int chunkZ) {
+ final RegionSection section = this.regionsBySection.get(MCUtil.getCoordinateKey(chunkX >> regionChunkShift, chunkZ >> regionChunkShift));
+ return section != null ? section.region : null;
+ }
+
+ private final List<Region<T>> toMerge = new ArrayList<>((2 * REGION_SECTION_MERGE_RADIUS + 1) * (2 * REGION_SECTION_MERGE_RADIUS + 1));
+ private final List<Region> toMerge = new ArrayList<>();
+
+ protected RegionSection<T> getOrCreateAndMergeSection(final int sectionX, final int sectionZ, final RegionSection<T> force) {
+ protected RegionSection getOrCreateAndMergeSection(final int sectionX, final int sectionZ, final RegionSection force) {
+ final long sectionKey = MCUtil.getCoordinateKey(sectionX, sectionZ);
+
+ if (force == null) {
+ RegionSection<T> region = this.regionsBySection.get(sectionKey);
+ RegionSection region = this.regionsBySection.get(sectionKey);
+ if (region != null) {
+ return region;
+ }
+ }
+
+ int mergeCandidateSectionSize = -1;
+ Region<T> mergeIntoCandidate = null;
+ Region mergeIntoCandidate = null;
+
+ // find optimal candidate to merge into
+
+ final int minX = sectionX - REGION_SECTION_MERGE_RADIUS;
+ final int maxX = sectionX + REGION_SECTION_MERGE_RADIUS;
+ final int minZ = sectionZ - REGION_SECTION_MERGE_RADIUS;
+ final int maxZ = sectionZ + REGION_SECTION_MERGE_RADIUS;
+ final int minX = sectionX - this.regionSectionMergeRadius;
+ final int maxX = sectionX + this.regionSectionMergeRadius;
+ final int minZ = sectionZ - this.regionSectionMergeRadius;
+ final int maxZ = sectionZ + this.regionSectionMergeRadius;
+ for (int currX = minX; currX <= maxX; ++currX) {
+ for (int currZ = minZ; currZ <= maxZ; ++currZ) {
+ final RegionSection<T> section = this.regionsBySection.get(MCUtil.getCoordinateKey(currX, currZ));
+ final RegionSection section = this.regionsBySection.get(MCUtil.getCoordinateKey(currX, currZ));
+ if (section == null) {
+ continue;
+ }
+ final Region<T> region = section.region;
+ final Region region = section.region;
+ if (region.dead) {
+ throw new IllegalStateException("Dead region should not be in live region manager state: " + region);
+ }
@ -141,7 +135,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ // merge
+ if (mergeIntoCandidate != null) {
+ for (int i = 0; i < this.toMerge.size(); ++i) {
+ final Region<T> region = this.toMerge.get(i);
+ final Region region = this.toMerge.get(i);
+ if (region.dead || mergeIntoCandidate == region) {
+ continue;
+ }
@ -149,14 +143,14 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ this.toMerge.clear();
+ } else {
+ mergeIntoCandidate = new Region<>(this);
+ mergeIntoCandidate = new Region(this);
+ }
+
+ final RegionSection<T> section;
+ final RegionSection section;
+ if (force == null) {
+ this.regionsBySection.put(sectionKey, section = new RegionSection<>(sectionKey, this));
+ this.regionsBySection.put(sectionKey, section = new RegionSection(sectionKey, this));
+ } else {
+ final RegionSection<T> existing = this.regionsBySection.putIfAbsent(sectionKey, force);
+ final RegionSection existing = this.regionsBySection.putIfAbsent(sectionKey, force);
+ if (existing != null) {
+ throw new IllegalStateException("Attempting to override section '" + existing.toStringWithRegion() +
+ ", with " + force.toStringWithRegion());
@ -165,8 +159,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ section = force;
+ }
+
+ section.region = mergeIntoCandidate;
+ mergeIntoCandidate.sections.add(section);
+ mergeIntoCandidate.addRegionSection(section);
+ //mergeIntoCandidate.check();
+ //this.check();
+
@ -174,110 +167,97 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+
+ public void addChunk(final int chunkX, final int chunkZ) {
+ this.addChunkTimings.startTiming();
+ try {
+ this.getOrCreateAndMergeSection(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT, null).addChunk(chunkX, chunkZ);
+ } finally {
+ this.addChunkTimings.stopTiming();
+ }
+ this.getOrCreateAndMergeSection(chunkX >> this.regionChunkShift, chunkZ >> this.regionChunkShift, null).addChunk(chunkX, chunkZ);
+ }
+
+ public void removeChunk(final int chunkX, final int chunkZ) {
+ this.removeChunkTimings.startTiming();
+ try {
+ final RegionSection<T> section = this.regionsBySection.get(
+ MCUtil.getCoordinateKey(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT)
+ );
+ if (section != null) {
+ section.removeChunk(chunkX, chunkZ);
+ } else {
+ throw new IllegalStateException("Cannot remove chunk at (" + chunkX + "," + chunkZ + ") from region state, section does not exist");
+ }
+ } finally {
+ this.removeChunkTimings.stopTiming();
+ final RegionSection section = this.regionsBySection.get(
+ MCUtil.getCoordinateKey(chunkX >> this.regionChunkShift, chunkZ >> this.regionChunkShift)
+ );
+ if (section != null) {
+ section.removeChunk(chunkX, chunkZ);
+ } else {
+ throw new IllegalStateException("Cannot remove chunk at (" + chunkX + "," + chunkZ + ") from region state, section does not exist");
+ }
+ }
+
+ public void recalculateRegions() {
+ for (int i = 0, len = this.needsRecalculation.size(); i < len; ++i) {
+ final Region<T> region = this.needsRecalculation.removeFirst();
+ final Region region = this.needsRecalculation.removeFirst();
+
+ this.recalculateRegion(region);
+ //this.check();
+ }
+ }
+
+ protected void recalculateRegion(final Region<T> region) {
+ this.regionRecalculateTimings.startTiming();
+ try {
+ region.markedForRecalc = false;
+ protected void recalculateRegion(final Region region) {
+ region.markedForRecalc = false;
+ //region.check();
+ // clear unused regions
+ for (final Iterator<RegionSection> iterator = region.deadSections.iterator(); iterator.hasNext();) {
+ final RegionSection deadSection = iterator.next();
+
+ if (deadSection.hasChunks()) {
+ throw new IllegalStateException("Dead section '" + deadSection.toStringWithRegion() + "' is marked dead but has chunks!");
+ }
+ if (!region.removeRegionSection(deadSection)) {
+ throw new IllegalStateException("Region " + region + " has inconsistent state, it should contain section " + deadSection);
+ }
+ if (!this.regionsBySection.remove(deadSection.regionCoordinate, deadSection)) {
+ throw new IllegalStateException("Cannot remove dead section '" +
+ deadSection.toStringWithRegion() + "' from section state! State at section coordinate: " +
+ this.regionsBySection.get(deadSection.regionCoordinate));
+ }
+ }
+ region.deadSections.clear();
+
+ // implicitly cover cases where size == 0
+ if (region.sections.size() < this.minSectionRecalcCount) {
+ //region.check();
+ // clear unused regions
+ for (final Iterator<RegionSection<T>> iterator = region.deadSections.iterator(); iterator.hasNext();) {
+ final RegionSection<T> deadSection = iterator.next();
+ return;
+ }
+
+ if (deadSection.hasChunks()) {
+ throw new IllegalStateException("Dead section '" + deadSection.toStringWithRegion() + "' is marked dead but has chunks!");
+ }
+ if (!region.sections.remove(deadSection)) {
+ throw new IllegalStateException("Region " + region + " has inconsistent state, it should contain section " + deadSection);
+ }
+ if (!this.regionsBySection.remove(deadSection.regionCoordinate, deadSection)) {
+ throw new IllegalStateException("Cannot remove dead section '" +
+ deadSection.toStringWithRegion() + "' from section state! State at section coordinate: " +
+ this.regionsBySection.get(deadSection.regionCoordinate));
+ }
+ // run a test to see if we actually need to recalculate
+ // TODO
+
+ // destroy and rebuild the region
+ region.dead = true;
+
+ // destroy region state
+ for (final Iterator<RegionSection> iterator = region.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection aliveSection = iterator.next();
+ if (!aliveSection.hasChunks()) {
+ throw new IllegalStateException("Alive section '" + aliveSection.toStringWithRegion() + "' has no chunks!");
+ }
+ region.deadSections.clear();
+
+ // implicitly cover cases where size == 0
+ if (region.sections.size() < this.minSectionRecalcCount) {
+ //region.check();
+ return;
+ if (!this.regionsBySection.remove(aliveSection.regionCoordinate, aliveSection)) {
+ throw new IllegalStateException("Cannot remove alive section '" +
+ aliveSection.toStringWithRegion() + "' from section state! State at section coordinate: " +
+ this.regionsBySection.get(aliveSection.regionCoordinate));
+ }
+ }
+
+ // run a test to see if we actually need to recalculate
+ // TODO
+
+ // destroy and rebuild the region
+ region.dead = true;
+
+ // destroy region state
+ for (final Iterator<RegionSection<T>> iterator = region.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection<T> aliveSection = iterator.next();
+ if (!aliveSection.hasChunks()) {
+ throw new IllegalStateException("Alive section '" + aliveSection.toStringWithRegion() + "' has no chunks!");
+ }
+ if (!this.regionsBySection.remove(aliveSection.regionCoordinate, aliveSection)) {
+ throw new IllegalStateException("Cannot remove alive section '" +
+ aliveSection.toStringWithRegion() + "' from section state! State at section coordinate: " +
+ this.regionsBySection.get(aliveSection.regionCoordinate));
+ }
+ }
+
+ // rebuild regions
+ for (final Iterator<RegionSection<T>> iterator = region.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection<T> aliveSection = iterator.next();
+ this.getOrCreateAndMergeSection(aliveSection.getSectionX(), aliveSection.getSectionZ(), aliveSection);
+ }
+ } finally {
+ this.regionRecalculateTimings.stopTiming();
+ // rebuild regions
+ for (final Iterator<RegionSection> iterator = region.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection aliveSection = iterator.next();
+ this.getOrCreateAndMergeSection(aliveSection.getSectionX(), aliveSection.getSectionZ(), aliveSection);
+ }
+ }
+
+ public static final class Region<T extends Enum<T> & SingleThreadChunkRegionManager.RegionDataCreator<T>> {
+ protected final IteratorSafeOrderedReferenceSet<RegionSection<T>> sections = new IteratorSafeOrderedReferenceSet<>(true);
+ protected final ReferenceOpenHashSet<RegionSection<T>> deadSections = new ReferenceOpenHashSet<>(16, 0.7f);
+ public static final class Region {
+ protected final IteratorSafeOrderedReferenceSet<RegionSection> sections = new IteratorSafeOrderedReferenceSet<>();
+ protected final ReferenceOpenHashSet<RegionSection> deadSections = new ReferenceOpenHashSet<>(16, 0.7f);
+ protected boolean dead;
+ protected boolean markedForRecalc;
+
+ public final SingleThreadChunkRegionManager<T> regionManager;
+ public final SingleThreadChunkRegionManager regionManager;
+ public final RegionData regionData;
+
+ protected Region(final SingleThreadChunkRegionManager<T> regionManager) {
+ protected Region(final SingleThreadChunkRegionManager regionManager) {
+ this.regionManager = regionManager;
+ this.regionData = regionManager.regionDataSupplier.get();
+ }
+
+ public IteratorSafeOrderedReferenceSet.Iterator<RegionSection<T>> getSections() {
+ public IteratorSafeOrderedReferenceSet.Iterator<RegionSection> getSections() {
+ return this.sections.iterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS);
+ }
+
@ -302,7 +282,30 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ */
+
+ protected void mergeInto(final Region<T> mergeTarget) {
+ // note: it is not true that the region at this point is not in any region. use the region field on the section
+ // to see if it is currently in another region.
+ protected final boolean addRegionSection(final RegionSection section) {
+ if (!this.sections.add(section)) {
+ return false;
+ }
+
+ section.sectionData.addToRegion(section, section.region, this);
+
+ section.region = this;
+ return true;
+ }
+
+ protected final boolean removeRegionSection(final RegionSection section) {
+ if (!this.sections.remove(section)) {
+ return false;
+ }
+
+ section.sectionData.removeFromRegion(section, this);
+
+ return true;
+ }
+
+ protected void mergeInto(final Region mergeTarget) {
+ if (this == mergeTarget) {
+ throw new IllegalStateException("Cannot merge a region onto itself");
+ }
@ -316,17 +319,15 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ this.regionManager.removeFromRecalcQueue(this);
+ }
+
+ for (final Iterator<RegionSection<T>> iterator = this.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection<T> section = iterator.next();
+ for (final Iterator<RegionSection> iterator = this.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection section = iterator.next();
+
+ if (!mergeTarget.sections.add(section)) {
+ if (!mergeTarget.addRegionSection(section)) {
+ throw new IllegalStateException("Target cannot contain source's sections! Source " + this + ", target " + mergeTarget);
+ }
+
+ section.region = mergeTarget;
+ }
+
+ for (final RegionSection<T> deadSection : this.deadSections) {
+ for (final RegionSection deadSection : this.deadSections) {
+ if (!this.sections.contains(deadSection)) {
+ throw new IllegalStateException("Source region does not even contain its own dead sections! Missing " + deadSection + " from region " + this);
+ }
@ -335,7 +336,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ //mergeTarget.check();
+ }
+
+ protected void markSectionAlive(final RegionSection<T> section) {
+ protected void markSectionAlive(final RegionSection section) {
+ this.deadSections.remove(section);
+ if (this.markedForRecalc && (this.sections.size() < this.regionManager.minSectionRecalcCount || this.getDeadSectionPercent() < this.regionManager.maxDeadRegionPercent)) {
+ this.regionManager.removeFromRecalcQueue(this);
@ -343,7 +344,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ }
+
+ protected void markSectionDead(final RegionSection<T> section) {
+ protected void markSectionDead(final RegionSection section) {
+ this.deadSections.add(section);
+ if (!this.markedForRecalc && (this.sections.size() >= this.regionManager.minSectionRecalcCount || this.sections.size() == this.deadSections.size()) && this.getDeadSectionPercent() >= this.regionManager.maxDeadRegionPercent) {
+ this.regionManager.addToRecalcQueue(this);
@ -361,8 +362,8 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+
+ ret.append("sectionCount=").append(this.sections.size()).append(',');
+ ret.append("sections=[");
+ for (final Iterator<RegionSection<T>> iterator = this.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection<T> section = iterator.next();
+ for (final Iterator<RegionSection> iterator = this.sections.unsafeIterator(IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ final RegionSection section = iterator.next();
+ ret.append(section);
+ if (iterator.hasNext()) {
+ ret.append(',');
@ -375,23 +376,20 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ }
+
+ public static final class RegionSection<T extends Enum<T> & SingleThreadChunkRegionManager.RegionDataCreator<T>> {
+ public static final class RegionSection {
+ protected final long regionCoordinate;
+ protected final long[] chunksBitset = new long[Math.max(1, REGION_CHUNK_SIZE * REGION_CHUNK_SIZE / Long.SIZE)];
+ protected final long[] chunksBitset;
+ protected int chunkCount;
+ protected Region<T> region;
+ protected final EnumMap<T, Object> data;
+ protected final Function<? super T, Object> createIfAbsentFunction;
+ protected Region region;
+
+ public final SingleThreadChunkRegionManager<T> regionManager;
+ public final SingleThreadChunkRegionManager regionManager;
+ public final RegionSectionData sectionData;
+
+ protected RegionSection(final long regionCoordinate, final SingleThreadChunkRegionManager<T> regionManager) {
+ protected RegionSection(final long regionCoordinate, final SingleThreadChunkRegionManager regionManager) {
+ this.regionCoordinate = regionCoordinate;
+ this.data = new EnumMap<>(regionManager.dataClass);
+ this.regionManager = regionManager;
+ this.createIfAbsentFunction = (final T keyInMap) -> {
+ return keyInMap.createData(RegionSection.this, regionManager);
+ };
+ this.chunksBitset = new long[Math.max(1, regionManager.regionSectionChunkSize * regionManager.regionSectionChunkSize / Long.SIZE)];
+ this.sectionData = regionManager.regionSectionDataSupplier.get();
+ }
+
+ public int getSectionX() {
@ -402,28 +400,12 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ return MCUtil.getCoordinateZ(this.regionCoordinate);
+ }
+
+ public Region<T> getRegion() {
+ public Region getRegion() {
+ return this.region;
+ }
+
+ public Object getData(final T key) {
+ return this.data.get(key);
+ }
+
+ public Object getOrCreateData(final T key) {
+ return this.data.computeIfAbsent(key, this.createIfAbsentFunction);
+ }
+
+ public Object removeData(final T key) {
+ return this.data.remove(key);
+ }
+
+ public void setData(final T key, final Object data) {
+ this.data.put(key, data);
+ }
+
+ private static int getChunkIndex(final int chunkX, final int chunkZ) {
+ return (chunkX & (REGION_CHUNK_SIZE - 1)) | ((chunkZ & (REGION_CHUNK_SIZE - 1)) << REGION_CHUNK_SIZE_SHIFT);
+ private int getChunkIndex(final int chunkX, final int chunkZ) {
+ return (chunkX & (this.regionManager.regionSectionChunkSize - 1)) | ((chunkZ & (this.regionManager.regionSectionChunkSize - 1)) << this.regionManager.regionChunkShift);
+ }
+
+ protected boolean hasChunks() {
@ -431,7 +413,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+
+ protected void addChunk(final int chunkX, final int chunkZ) {
+ final int index = getChunkIndex(chunkX, chunkZ);
+ final int index = this.getChunkIndex(chunkX, chunkZ);
+ final long bitset = this.chunksBitset[index >>> 6]; // index / Long.SIZE
+ final long after = this.chunksBitset[index >>> 6] = bitset | (1L << (index & (Long.SIZE - 1)));
+ if (after == bitset) {
@ -444,7 +426,7 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+
+ protected void removeChunk(final int chunkX, final int chunkZ) {
+ final int index = getChunkIndex(chunkX, chunkZ);
+ final int index = this.getChunkIndex(chunkX, chunkZ);
+ final long before = this.chunksBitset[index >>> 6]; // index / Long.SIZE
+ final long bitset = this.chunksBitset[index >>> 6] = before & ~(1L << (index & (Long.SIZE - 1)));
+ if (before == bitset) {
@ -477,12 +459,12 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+
+ private static String toString(final long[] array) {
+ StringBuilder ret = new StringBuilder();
+ for (long value : array) {
+ final StringBuilder ret = new StringBuilder();
+ for (final long value : array) {
+ // zero pad the hex string
+ char[] zeros = new char[Long.SIZE / 4];
+ final char[] zeros = new char[Long.SIZE / 4];
+ Arrays.fill(zeros, '0');
+ String string = Long.toHexString(value);
+ final String string = Long.toHexString(value);
+ System.arraycopy(string.toCharArray(), 0, zeros, zeros.length - string.length(), string.length());
+
+ ret.append(zeros);
@ -492,10 +474,17 @@ index 0000000000000000000000000000000000000000..20150ad0750a648d349701a09b31881b
+ }
+ }
+
+ public static interface RegionDataCreator<E extends Enum<E> & RegionDataCreator<E>> {
+ public static interface RegionData {
+
+ }
+
+ public static interface RegionSectionData {
+
+ public void removeFromRegion(final RegionSection section, final Region from);
+
+ // removal from the old region is handled via removeFromRegion
+ public void addToRegion(final RegionSection section, final Region oldRegion, final Region newRegion);
+
+ Object createData(final RegionSection<E> section,
+ final SingleThreadChunkRegionManager<E> regionManager);
+ }
+}
\ No newline at end of file
@ -2321,7 +2310,7 @@ index ff74be14512a947e81b62d53e616131ca7d7f609..2371557d083446b17ffebdae576b1cc3
public static <T> void mergeSortedSets(final java.util.function.Consumer<T> consumer, final java.util.Comparator<? super T> comparator, final java.util.SortedSet<T>...sets) {
final ObjectRBTreeSet<T> all = new ObjectRBTreeSet<>(comparator);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 2131f7322640879496692b73fd2a8c52b059ae24..74f89ea456e23937d0fec14831508365f3014ab0 100644
index 2131f7322640879496692b73fd2a8c52b059ae24..91545586909d37b4bfaa4444a35953873ca819e8 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -155,6 +155,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -2340,11 +2329,15 @@ index 2131f7322640879496692b73fd2a8c52b059ae24..74f89ea456e23937d0fec14831508365
if ( ++MinecraftServer.currentTick % SAMPLE_INTERVAL == 0 )
{
final long diff = curTime - tickSection;
@@ -1362,6 +1364,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1362,6 +1364,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
midTickLoadChunks(); // Paper
worldserver.timings.doTick.startTiming(); // Spigot
worldserver.doTick(booleansupplier);
+ worldserver.getChunkProvider().playerChunkMap.dataRegionManager.recalculateRegions(); // Tuinity
+ // Tuinity start
+ for (final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkProvider().playerChunkMap.regionManagers) {
+ regionManager.recalculateRegions();
+ }
+ // Tuinity end
worldserver.timings.doTick.stopTiming(); // Spigot
midTickLoadChunks(); // Paper
} catch (Throwable throwable) {
@ -2408,50 +2401,70 @@ index 904c6a7d0a36b57bb4f693fc4fd0dd5b17adcbac..b03865a932d341ae2fdad6c9447979fa
// Paper start - raise IO/load priority if priority changes, use our preferred priority
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..2b2920a5602e23dd766ddbbf10b4fed90a1a21bc 100644
index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..a470e8fb8df29f611c13039b7a4f58a114564705 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -278,6 +278,21 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -278,6 +278,36 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Paper end
+ // Tuinity start
+ public static enum RegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionDataCreator<RegionData> {
+ protected final List<com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager> regionManagers = new java.util.ArrayList<>();
+ public final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager dataRegionManager;
+
+ public static final class DataRegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionData {
+
+
+ ;
+
+ @Override
+ public Object createData(com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<RegionData> section,
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<RegionData> regionManager) {
+ throw new AbstractMethodError();
+ }
+ }
+
+ public final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<RegionData> dataRegionManager;
+ public static final class DataRegionSectionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSectionData {
+
+ @Override
+ public void removeFromRegion(final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section,
+ final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region from) {
+ final DataRegionSectionData sectionData = (DataRegionSectionData)section.sectionData;
+ final DataRegionData fromData = (DataRegionData)from.regionData;
+ }
+
+ @Override
+ public void addToRegion(final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section,
+ final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region oldRegion,
+ final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region newRegion) {
+ final DataRegionSectionData sectionData = (DataRegionSectionData)section.sectionData;
+ final DataRegionData oldRegionData = oldRegion == null ? null : (DataRegionData)oldRegion.regionData;
+ final DataRegionData newRegionData = (DataRegionData)newRegion.regionData;
+ }
+ }
+ // Tuiniy end
+
private final java.util.concurrent.ExecutorService lightThread;
public PlayerChunkMap(WorldServer worldserver, Convertable.ConversionSession convertable_conversionsession, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, IAsyncTaskHandler<Runnable> iasynctaskhandler, ILightAccess ilightaccess, ChunkGenerator chunkgenerator, WorldLoadListener worldloadlistener, Supplier<WorldPersistentData> supplier, int i, boolean flag) {
super(new File(convertable_conversionsession.a(worldserver.getDimensionKey()), "region"), datafixer, flag);
@@ -445,6 +460,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -445,6 +475,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
PlayerChunkMap.this.sendChunk(player, new ChunkCoordIntPair(rangeX, rangeZ), null, true, false); // unloaded, loaded
});
// Paper end - no-tick view distance
+ // Tuinity start
+ this.dataRegionManager = new com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<>(this.world, RegionData.class, 2, (1.0 / 3.0), "Data");
+ this.dataRegionManager = new com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager(this.world, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
+ this.regionManagers.add(this.dataRegionManager);
+ // Tuinity end
}
// Paper start - Chunk Prioritization
public void queueHolderUpdate(PlayerChunk playerchunk) {
@@ -779,6 +797,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -779,6 +813,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
playerchunk.a(j);
} else {
playerchunk = new PlayerChunk(new ChunkCoordIntPair(i), j, this.lightEngine, this.p, this);
+ this.dataRegionManager.addChunk(playerchunk.location.x, playerchunk.location.z); // Tuinity
+ // Tuinity start
+ for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
+ this.regionManagers.get(index).addChunk(playerchunk.location.x, playerchunk.location.z);
+ }
+ // Tuinity end
}
this.updatingChunks.put(i, playerchunk);
@@ -1021,7 +1040,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1021,7 +1060,14 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
if (completablefuture1 != completablefuture) {
this.a(i, playerchunk);
} else {
@ -2459,22 +2472,30 @@ index 00d0a5fd7c5d2db19756f3c6cfb2381868af51fd..2b2920a5602e23dd766ddbbf10b4fed9
+ // Tuinity start
+ boolean removed;
+ if ((removed = this.pendingUnload.remove(i, playerchunk)) && ichunkaccess != null) { // Tuinity end
+ this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z); // Tuinity
+ // Tuinity start
+ for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
+ this.regionManagers.get(index).removeChunk(playerchunk.location.x, playerchunk.location.z);
+ }
+ // Tuinity end
if (ichunkaccess instanceof Chunk) {
((Chunk) ichunkaccess).setLoaded(false);
}
@@ -1044,7 +1066,9 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1044,7 +1090,13 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.lightEngine.a(ichunkaccess.getPos());
this.lightEngine.queueUpdate();
this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null);
- }
+ } else if (removed) { // Tuinity start
+ this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z);
+ // Tuinity start
+ for (int index = 0, len = this.regionManagers.size(); index < len; ++index) {
+ this.regionManagers.get(index).removeChunk(playerchunk.location.x, playerchunk.location.z);
+ }
+ // Tuinity end
+ } // Tuinity end
}
};
@@ -1711,6 +1735,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1711,6 +1763,11 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
return chunkHolder == null ? null : chunkHolder.getAvailableChunkNow();
}
// Paper end

View File

@ -274,7 +274,7 @@ index d4793a1d476d8d6687ec8782501c31265f284daa..617ba6fb85c55967360ca270ee8feeff
this.setPVP(dedicatedserverproperties.pvp);
this.setAllowFlight(dedicatedserverproperties.allowFlight);
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 74f89ea456e23937d0fec14831508365f3014ab0..dc8e4a86ddae9ea4dfd62e591523fdc8a6599151 100644
index 91545586909d37b4bfaa4444a35953873ca819e8..f2fd2c2df4b99910d1838035a5f1ed11731c98ca 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -960,6 +960,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -81,34 +81,6 @@ index e7624948ea4aa1a07d84ed3d295cfe2dd354fd14..a263cd7a0680e0cc3517f84308118eb3
// good thing this is only used in debug reports // TODO check on update
int ret = 0;
diff --git a/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
index 20150ad0750a648d349701a09b31881be124e46c..cae06962d80cdd00962236891472ba815b0ab8cd 100644
--- a/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
+++ b/src/main/java/com/tuinity/tuinity/chunk/SingleThreadChunkRegionManager.java
@@ -162,6 +162,7 @@ public final class SingleThreadChunkRegionManager<T extends Enum<T> & SingleThre
}
public void addChunk(final int chunkX, final int chunkZ) {
+ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region manager add chunk"); // Tuinity
this.addChunkTimings.startTiming();
try {
this.getOrCreateAndMergeSection(chunkX >> REGION_CHUNK_SIZE_SHIFT, chunkZ >> REGION_CHUNK_SIZE_SHIFT, null).addChunk(chunkX, chunkZ);
@@ -171,6 +172,7 @@ public final class SingleThreadChunkRegionManager<T extends Enum<T> & SingleThre
}
public void removeChunk(final int chunkX, final int chunkZ) {
+ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region manager remove chunk"); // Tuinity
this.removeChunkTimings.startTiming();
try {
final RegionSection<T> section = this.regionsBySection.get(
@@ -187,6 +189,7 @@ public final class SingleThreadChunkRegionManager<T extends Enum<T> & SingleThre
}
public void recalculateRegions() {
+ com.tuinity.tuinity.util.TickThread.ensureTickThread("async region recalculation"); // Tuinity
for (int i = 0, len = this.needsRecalculation.size(); i < len; ++i) {
final Region<T> region = this.needsRecalculation.removeFirst();
diff --git a/src/main/java/com/tuinity/tuinity/util/TickThread.java b/src/main/java/com/tuinity/tuinity/util/TickThread.java
index 033548a58d27f64d3954206d267783c0437d4019..08ed243259f052165c6f75aed1d1d65a14219715 100644
--- a/src/main/java/com/tuinity/tuinity/util/TickThread.java
@ -224,7 +196,7 @@ index f2a9396c2ec64c79391782249db7507f12a69a9e..798ebfdcd8e06ffb576964da006e77bd
if (!list.equals(this.p)) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 2b2920a5602e23dd766ddbbf10b4fed90a1a21bc..bf1a1e7e6fd01b2e600c758f900e5fdb08e74930 100644
index a470e8fb8df29f611c13039b7a4f58a114564705..4abd156556b40aa82e6ed5093b279c0f780b9c9c 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -201,6 +201,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -251,7 +223,7 @@ index 2b2920a5602e23dd766ddbbf10b4fed90a1a21bc..bf1a1e7e6fd01b2e600c758f900e5fdb
int chunkX = MCUtil.getChunkCoordinate(player.locX());
int chunkZ = MCUtil.getChunkCoordinate(player.locZ());
// Note: players need to be explicitly added to distance maps before they can be updated
@@ -775,6 +778,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -791,6 +794,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@Nullable
private PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k) {
@ -259,7 +231,7 @@ index 2b2920a5602e23dd766ddbbf10b4fed90a1a21bc..bf1a1e7e6fd01b2e600c758f900e5fdb
if (k > PlayerChunkMap.GOLDEN_TICKET && j > PlayerChunkMap.GOLDEN_TICKET) {
return playerchunk;
} else {
@@ -1084,6 +1088,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1112,6 +1116,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
protected boolean b() {
@ -267,7 +239,7 @@ index 2b2920a5602e23dd766ddbbf10b4fed90a1a21bc..bf1a1e7e6fd01b2e600c758f900e5fdb
if (!this.updatingChunksModified) {
return false;
} else {
@@ -1523,6 +1528,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1551,6 +1556,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
public void setViewDistance(int i) { // Paper - public
@ -275,7 +247,7 @@ index 2b2920a5602e23dd766ddbbf10b4fed90a1a21bc..bf1a1e7e6fd01b2e600c758f900e5fdb
int j = MathHelper.clamp(i + 1, 3, 33); // Paper - diff on change, these make the lower view distance limit 2 and the upper 32
if (j != this.viewDistance) {
@@ -1536,6 +1542,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1564,6 +1570,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Paper start - no-tick view distance
public final void setNoTickViewDistance(int viewDistance) {

View File

@ -5,6 +5,8 @@ Subject: [PATCH] Update version fetcher repo
Sets the target github repo to Tuinity in the version checker. Also disables the jenkins build lookups.
This patch is licensed under the MIT license. See /licenses/MIT.md.
diff --git a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java
index dc0ea65ab87255fad0d54dfb509300098a0b4864..7063f1da3654b382e26b0093ad5d0ff04a2b38c2 100644
--- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java

View File

@ -3,6 +3,7 @@ From: Chase Whipple <chasewhip20@gmail.com>
Date: Thu, 26 Mar 2020 21:45:54 -0600
Subject: [PATCH] Per World Spawn Limits
This patch is licensed under the MIT license. See /licenses/MIT.md.
diff --git a/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java b/src/main/java/com/tuinity/tuinity/config/TuinityConfig.java
index 994c735958dc0ee0dfd8c28820fcd4f50057aad0..a302cda14aa2dd6550cca03b07be21cdcb993061 100644

View File

@ -159,7 +159,7 @@ index 8c7080777b370f97e1291dfedde5b419290f39cc..8112b01f15c33f50fe5ec9aebf75d809
});
throw CancelledPacketHandleException.INSTANCE;
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index e285038154d83cbf0d7c0b6b8a247c11b9e20119..97a9a201a055520a7ab92b3ecc8987eb560bf263 100644
index e285038154d83cbf0d7c0b6b8a247c11b9e20119..949ed1cbb19317844424975c9e976148cfa2614d 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 {
@ -167,14 +167,12 @@ index e285038154d83cbf0d7c0b6b8a247c11b9e20119..97a9a201a055520a7ab92b3ecc8987eb
}
+ // Tuinity start - log detailed entity tick information
+ static final java.util.concurrent.ConcurrentLinkedDeque<Entity> currentlyTickingEntities = new java.util.concurrent.ConcurrentLinkedDeque<>();
+ // TODO replace with varhandle
+ static final java.util.concurrent.atomic.AtomicReference<Entity> currentlyTickingEntity = new java.util.concurrent.atomic.AtomicReference<>();
+
+ public static List<Entity> getCurrentlyTickingEntities() {
+ List<Entity> ret = Lists.newArrayListWithCapacity(4);
+
+ for (Entity entity : currentlyTickingEntities) {
+ ret.add(entity);
+ }
+ Entity ticking = currentlyTickingEntity.get();
+ List<Entity> ret = java.util.Arrays.asList(ticking == null ? new Entity[0] : new Entity[] { ticking });
+
+ return ret;
+ }
@ -184,18 +182,22 @@ index e285038154d83cbf0d7c0b6b8a247c11b9e20119..97a9a201a055520a7ab92b3ecc8987eb
+ // Tuinity start - log detailed entity tick information
+ com.tuinity.tuinity.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
+ try {
+ currentlyTickingEntities.push(entity);
+ if (currentlyTickingEntity.get() == null) {
+ currentlyTickingEntity.lazySet(entity);
+ }
+ // Tuinity end - log detailed entity tick information
if (!(entity instanceof EntityHuman) && !this.getChunkProvider().a(entity)) {
this.chunkCheck(entity);
} else {
@@ -954,6 +973,11 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -954,6 +973,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
//} finally { timer.stopTiming(); } // Paper - timings - move up
}
+ // Tuinity start - log detailed entity tick information
+ } finally {
+ currentlyTickingEntities.pop();
+ if (currentlyTickingEntity.get() == entity) {
+ currentlyTickingEntity.lazySet(null);
+ }
+ }
+ // Tuinity end - log detailed entity tick information
}

View File

@ -101,7 +101,7 @@ index 4082c4f366bce1784759bda773d3d35472403ade..7bb23731b548d5344013429a7d7df136
@Override
protected boolean executeNext() {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index dc8e4a86ddae9ea4dfd62e591523fdc8a6599151..b96ffaab1253a8f1bd36f542865feeaebeadbff5 100644
index f2fd2c2df4b99910d1838035a5f1ed11731c98ca..a50b311876ce6aa3a571b3d290235775aa02d925 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -993,7 +993,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -260,7 +260,7 @@ index dc8e4a86ddae9ea4dfd62e591523fdc8a6599151..b96ffaab1253a8f1bd36f542865feeae
MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
// Send time updates to everyone, it will get the right time from the world the player is in.
// Paper start - optimize time updates
@@ -1362,12 +1418,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@@ -1362,7 +1418,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
this.methodProfiler.enter("tick");
try {
@ -268,7 +268,10 @@ index dc8e4a86ddae9ea4dfd62e591523fdc8a6599151..b96ffaab1253a8f1bd36f542865feeae
+ // Tuinity - replace logic
worldserver.timings.doTick.startTiming(); // Spigot
worldserver.doTick(booleansupplier);
worldserver.getChunkProvider().playerChunkMap.dataRegionManager.recalculateRegions(); // Tuinity
// Tuinity start
@@ -1371,7 +1427,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
}
// Tuinity end
worldserver.timings.doTick.stopTiming(); // Spigot
- midTickLoadChunks(); // Paper
+ // Tuinity - replace logic
@ -288,7 +291,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 97a9a201a055520a7ab92b3ecc8987eb560bf263..f2e630598320f7f09ecdee5a9a548b20cc1b7877 100644
index 949ed1cbb19317844424975c9e976148cfa2614d..a1e0761f255b5bda9834738fbcea57a129ada4e3 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

@ -7,10 +7,10 @@ Should limit build up of I/O tasks, or at least properly
indicate to server owners that I/O is falling behind
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index bf1a1e7e6fd01b2e600c758f900e5fdb08e74930..8b9e3418cdb90227eee149e25c4e208979aaf8fb 100644
index 4abd156556b40aa82e6ed5093b279c0f780b9c9c..bef3ff1e4527e4eb98fcb29910d8f2e39689a240 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -994,7 +994,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1014,7 +1014,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(this.world, chunkPos.x, chunkPos.z,
@ -19,7 +19,7 @@ index bf1a1e7e6fd01b2e600c758f900e5fdb08e74930..8b9e3418cdb90227eee149e25c4e2089
if (!chunk.isNeedsSaving()) {
return;
@@ -1028,7 +1028,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1048,7 +1048,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
asyncSaveData = ChunkRegionLoader.getAsyncSaveData(this.world, chunk);
}
@ -28,7 +28,7 @@ index bf1a1e7e6fd01b2e600c758f900e5fdb08e74930..8b9e3418cdb90227eee149e25c4e2089
asyncSaveData, chunk);
chunk.setLastSaved(this.world.getTime());
@@ -1658,7 +1658,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1686,7 +1686,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
if (Thread.currentThread() != com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE) {
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.scheduleSave(
this.world, chunkcoordintpair.x, chunkcoordintpair.z, null, nbttagcompound,

View File

@ -35,7 +35,7 @@ index c8c4d4f3d5a0ca6255473f3f256eeb32f18a9984..e1a17abda657c7eb7aee7cd0763bcb48
} catch (Throwable thr) {
if (thr instanceof ThreadDeath) {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 8b9e3418cdb90227eee149e25c4e208979aaf8fb..b05683f65a51363672779b5aebdce166743218c8 100644
index bef3ff1e4527e4eb98fcb29910d8f2e39689a240..b36568601dd2956518cc5dfe1b10cca8d65b6fb6 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -122,31 +122,28 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {

View File

@ -936,7 +936,7 @@ index 2371557d083446b17ffebdae576b1cc39e939eb1..e79e773f2219f9a9ae076fcbc8108b79
0, 2, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(),
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b96ffaab1253a8f1bd36f542865feeaebeadbff5..29e7b4aa6e94566d446221cd28c2f60fdb3fccab 100644
index a50b311876ce6aa3a571b3d290235775aa02d925..e64c57fd46f3d5e7989f01f063887e81be0590df 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1329,6 +1329,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
@ -1457,7 +1457,7 @@ index 6e82c1d1b272a95144bfc78d34b630c24466fa3e..6b4c007550c3e2e405314d8931630557
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 f2e630598320f7f09ecdee5a9a548b20cc1b7877..74cd5d412b285469f6f77bef73e65b139179992e 100644
index a1e0761f255b5bda9834738fbcea57a129ada4e3..d1d54c9c8657cdebf320ea03547417876a7af092 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

@ -7,10 +7,10 @@ Should bring us back in-line with tracker performance
before the loaded entity list reversion.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index b05683f65a51363672779b5aebdce166743218c8..ef7b76d891b28a2769c910933da91df1d3e9d152 100644
index b36568601dd2956518cc5dfe1b10cca8d65b6fb6..1a25a8ebd88d49ac16b58abc6d366367671e1ee7 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -2071,22 +2071,25 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -2099,22 +2099,25 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
private final void processTrackQueue() {
this.world.timings.tracker1.startTiming();
try {

View File

@ -74,10 +74,10 @@ index b03865a932d341ae2fdad6c9447979fa9e95fc14..9a321c8a0a357ca1fd47d0c7fe4fe7af
if (chunk != null) {
playerchunkmap.callbackExecutor.execute(() -> {
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index ef7b76d891b28a2769c910933da91df1d3e9d152..d829feb9f17c5412e63b2481af968391f38298d2 100644
index 1a25a8ebd88d49ac16b58abc6d366367671e1ee7..bd1abaa47109abaeafb728cbb9185804927ecbf2 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1273,7 +1273,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1301,7 +1301,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Paper end
this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable));

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 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc127f3871 100644
index d1d54c9c8657cdebf320ea03547417876a7af092..3e46e49aebee3c47447419eb784fcf2150f422f2 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 {
@ -63,7 +63,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
this.tickingEntities = false;
// Paper start
for (java.lang.Runnable run : this.afterEntityTickingTasks) {
@@ -1662,7 +1662,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1664,7 +1664,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
Entity entity = (Entity) iterator.next();
if (!(entity instanceof EntityPlayer)) {
@ -72,7 +72,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!")));
}
@@ -1690,6 +1690,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1692,6 +1692,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
public void unregisterEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
@ -80,7 +80,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
// Paper start - fix entity registration issues
if (entity instanceof EntityComplexPart) {
// Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways
@@ -1756,12 +1757,16 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1758,12 +1759,16 @@ public class WorldServer extends World implements GeneratorAccessSeed {
this.getScoreboard().a(entity);
// CraftBukkit start - SPIGOT-5278
if (entity instanceof EntityDrowned) {
@ -100,7 +100,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
}
new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
entity.valid = false; // CraftBukkit
@@ -1777,7 +1782,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1779,7 +1784,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
return;
}
// Paper end
@ -109,7 +109,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
if (!entity.isQueuedForRegister) { // Paper
this.entitiesToAdd.add(entity);
entity.isQueuedForRegister = true; // Paper
@@ -1785,6 +1790,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1787,6 +1792,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} else {
entity.isQueuedForRegister = false; // Paper
this.entitiesById.put(entity.getId(), entity);
@ -117,7 +117,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
if (entity instanceof EntityEnderDragon) {
EntityComplexPart[] aentitycomplexpart = ((EntityEnderDragon) entity).eJ();
int i = aentitycomplexpart.length;
@@ -1793,6 +1799,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1795,6 +1801,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
EntityComplexPart entitycomplexpart = aentitycomplexpart[j];
this.entitiesById.put(entitycomplexpart.getId(), entitycomplexpart);
@ -125,7 +125,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
}
}
@@ -1817,12 +1824,16 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1819,12 +1826,16 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// this.getChunkProvider().addEntity(entity); // Paper - moved down below valid=true
// CraftBukkit start - SPIGOT-5278
if (entity instanceof EntityDrowned) {
@ -145,7 +145,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
}
entity.valid = true; // CraftBukkit
this.getChunkProvider().addEntity(entity); // Paper - from above to be below valid=true
@@ -1838,7 +1849,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1840,7 +1851,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
public void removeEntity(Entity entity) {
@ -154,7 +154,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
throw (IllegalStateException) SystemUtils.c((Throwable) (new IllegalStateException("Removing entity while ticking!")));
} else {
this.removeEntityFromChunk(entity);
@@ -1942,7 +1953,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1944,7 +1955,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) {
boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper
@ -165,7 +165,7 @@ index 74cd5d412b285469f6f77bef73e65b139179992e..1f7cb91cc4f8d77b2ed0ffbf3a6063fc
while (iterator.hasNext()) {
// CraftBukkit start - fix SPIGOT-6362
@@ -1962,6 +1975,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1964,6 +1977,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
navigationabstract.b(blockposition);
}
}

View File

@ -20,10 +20,10 @@ index 0e5e7a321dc7066444d92387968a7c41cb3a8470..ce0bb4d228a73d8353d67828529879e1
boolean flag = this.chunkMapDistance.a(this.playerChunkMap);
boolean flag1 = this.playerChunkMap.b();
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index d829feb9f17c5412e63b2481af968391f38298d2..94da0b4cb9a790f866bcd3b11a61ae0c0faa1dc5 100644
index bd1abaa47109abaeafb728cbb9185804927ecbf2..8578cac6a19d9d1b5ac5f12fa369cc54a2436d4e 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -776,6 +776,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -792,6 +792,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@Nullable
private PlayerChunk a(long i, int j, @Nullable PlayerChunk playerchunk, int k) {
com.tuinity.tuinity.util.TickThread.softEnsureTickThread("Chunk holder update"); // Tuinity
@ -31,7 +31,7 @@ index d829feb9f17c5412e63b2481af968391f38298d2..94da0b4cb9a790f866bcd3b11a61ae0c
if (k > PlayerChunkMap.GOLDEN_TICKET && j > PlayerChunkMap.GOLDEN_TICKET) {
return playerchunk;
} else {
@@ -1033,6 +1034,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1053,6 +1054,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Paper end
@ -40,7 +40,7 @@ index d829feb9f17c5412e63b2481af968391f38298d2..94da0b4cb9a790f866bcd3b11a61ae0c
private void a(long i, PlayerChunk playerchunk) {
CompletableFuture<IChunkAccess> completablefuture = playerchunk.getChunkSave();
Consumer<IChunkAccess> consumer = (ichunkaccess) -> { // CraftBukkit - decompile error
@@ -1041,6 +1044,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1061,6 +1064,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
if (completablefuture1 != completablefuture) {
this.a(i, playerchunk);
} else {
@ -53,9 +53,9 @@ index d829feb9f17c5412e63b2481af968391f38298d2..94da0b4cb9a790f866bcd3b11a61ae0c
// Tuinity start
boolean removed;
if ((removed = this.pendingUnload.remove(i, playerchunk)) && ichunkaccess != null) { // Tuinity end
@@ -1070,6 +1079,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
} else if (removed) { // Tuinity start
this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z);
@@ -1098,6 +1107,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Tuinity end
} // Tuinity end
+ } finally { this.unloadingPlayerChunk = unloadingBefore; } // Tuinity - do not allow ticket level changes while unloading chunks

View File

@ -185,7 +185,7 @@ index 48976b1f07aeb0d588d0856f18b6fd07b2d18e05..a22021766b3bffa4f96d1d4ee546b12e
// 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 94da0b4cb9a790f866bcd3b11a61ae0c0faa1dc5..2d15a4ea2958c4597269ba50bcd82282ee8e3bf0 100644
index 8578cac6a19d9d1b5ac5f12fa369cc54a2436d4e..d04be5ae54ac543de144eb4ae87a255c467bc637 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -196,6 +196,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@ -231,9 +231,9 @@ index 94da0b4cb9a790f866bcd3b11a61ae0c0faa1dc5..2d15a4ea2958c4597269ba50bcd82282
}
// Paper end
@@ -463,6 +478,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");
@@ -479,6 +494,23 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.dataRegionManager = new com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager(this.world, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
this.regionManagers.add(this.dataRegionManager);
// Tuinity end
+ // Tuinity start - optimise checkDespawn
+ this.playerGeneralAreaMap = new com.destroystokyo.paper.util.misc.PlayerAreaMap(this.pooledLinkedPlayerHashSets,
@ -348,7 +348,7 @@ index 1d87e7461d28d8a639fafcfdfa5496014e9180f6..970c1be5477a01ab9c6d79e84c519e22
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
index 3e46e49aebee3c47447419eb784fcf2150f422f2..ac4b2d34824c00b655f9e5dbcc431b0ed8e4d765 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 {

View File

@ -3,13 +3,6 @@ From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Thu, 27 Aug 2020 20:51:40 -0700
Subject: [PATCH] Remove streams for villager AI
POI searching:
Turns out chaining a lot of streams together has inane amounts of
overheard. Use the good ol iterator method to remove that overhead.
The rest is just standard stream removal.
Also remove streams for poi searching in some zombie pathfinding.
diff --git a/src/main/java/net/minecraft/server/Behavior.java b/src/main/java/net/minecraft/server/Behavior.java
index 65af976527133ee5c2f52e411e19c4f7f06df3ef..0b9d469a92decfb0632805791868ef7faa88c535 100644
@ -25,247 +18,10 @@ index 65af976527133ee5c2f52e411e19c4f7f06df3ef..0b9d469a92decfb0632805791868ef7f
private final int d;
private final int e;
diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
index 63a761ebef80d4af09cdc2682e496d78492c4a3a..8d445e9c0875db6cf45e4d8bcfce7cd3d5094d94 100644
index 63a761ebef80d4af09cdc2682e496d78492c4a3a..275d4cad8ff0dd64b74ef8f8056cdef093523f97 100644
--- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java
+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
@@ -55,6 +55,227 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
}
}
+ // Tuinity - remove streams entirely for poi search
+ // the only intentional vanilla diff is that this function will NOT load in poi data, anything else is a bug!
+ protected static Set<BlockPosition> findNearestPoi(VillagePlace poiStorage,
+ Predicate<VillagePlaceType> villagePlaceType,
+ Predicate<BlockPosition> positionPredicate,
+ BlockPosition sourcePosition,
+ int range, // distance on x y z axis
+ VillagePlace.Occupancy occupancy,
+ int max) {
+ java.util.TreeSet<BlockPosition> ret = new java.util.TreeSet<>((blockpos1, blockpos2) -> {
+ // important to keep distanceSquared order: the param is the source
+ return Double.compare(blockpos1.distanceSquared(sourcePosition), blockpos2.distanceSquared(sourcePosition));
+ });
+ findNearestPoi(poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, occupancy, max, ret);
+ return new java.util.HashSet<>(ret);
+ }
+ protected static void findNearestPoi(VillagePlace poiStorage,
+ Predicate<VillagePlaceType> villagePlaceType,
+ Predicate<BlockPosition> positionPredicate,
+ BlockPosition sourcePosition,
+ int range, // distance on x y z axis
+ VillagePlace.Occupancy occupancy,
+ int max,
+ java.util.SortedSet<BlockPosition> ret) {
+ // the biggest issue with the original mojang implementation is that they chain so many streams together
+ // the amount of streams chained just rolls performance, even if nothing is iterated over
+ Predicate<? super VillagePlaceRecord> occupancyFilter = occupancy.getPredicate();
+ double rangeSquared = range * range;
+
+ // First up, we need to iterate the chunks
+ // all the values here are in chunk sections
+ int lowerX = MathHelper.floor(sourcePosition.getX() - range) >> 4;
+ int lowerY = Math.max(0, MathHelper.floor(sourcePosition.getY() - range) >> 4);
+ int lowerZ = MathHelper.floor(sourcePosition.getZ() - range) >> 4;
+ int upperX = MathHelper.floor(sourcePosition.getX() + range) >> 4;
+ int upperY = Math.min(15, MathHelper.floor(sourcePosition.getY() + range) >> 4);
+ int upperZ = MathHelper.floor(sourcePosition.getZ() + range) >> 4;
+
+ // Vanilla iterates by x until max is reached then increases z
+ // vanilla also searches by increasing Y section value
+ for (int currZ = lowerZ; currZ <= upperZ; ++currZ) {
+ for (int currX = lowerX; currX <= upperX; ++currX) {
+ for (int currY = lowerY; currY <= upperY; ++currY) { // vanilla searches the entire chunk because they're actually stupid. just search the sections we need
+ Optional<VillagePlaceSection> poiSectionOptional = poiStorage.getIfLoaded(SectionPosition.asLong(currX, currY, currZ));
+ VillagePlaceSection poiSection = poiSectionOptional == null ? null : poiSectionOptional.orElse(null);
+ if (poiSection == null) {
+ continue;
+ }
+
+ java.util.Map<VillagePlaceType, Set<VillagePlaceRecord>> sectionData = poiSection.getData();
+ if (sectionData.isEmpty()) {
+ continue;
+ }
+
+ // now we search the section data
+ for (java.util.Iterator<java.util.Map.Entry<VillagePlaceType, Set<VillagePlaceRecord>>> iterator = sectionData.entrySet().iterator();
+ iterator.hasNext();) {
+ java.util.Map.Entry<VillagePlaceType, Set<VillagePlaceRecord>> entry = iterator.next();
+ if (!villagePlaceType.test(entry.getKey())) {
+ // filter out by poi type
+ continue;
+ }
+
+ // now we can look at the poi data
+ for (VillagePlaceRecord poiData : entry.getValue()) {
+ if (!occupancyFilter.test(poiData)) {
+ // filter by occupancy
+ continue;
+ }
+
+ // vanilla code is pretty dumb about filtering by distance: first they filter out
+ // so that only values in the square radius of range are returned but then they
+ // filter out so that the distance is in range
+ // but there's a catch! distanceSquared, by default, will ADD 0.5 to ONLY ONE OF the
+ // block position parameters (itself, in this case the poi position)! So if we want to
+ // maintain exact vanilla behaviour, well shit we need to play dumb as well.
+
+ BlockPosition poiPosition = poiData.getPosition();
+
+ if (Math.abs(poiPosition.getX() - sourcePosition.getX()) > range
+ || Math.abs(poiPosition.getZ() - sourcePosition.getZ()) > range) {
+ // out of range for square radius
+ continue;
+ }
+
+ if (poiPosition.distanceSquared(sourcePosition) > rangeSquared) {
+ // out of range for distance check
+ continue;
+ }
+
+ if (!positionPredicate.test(poiPosition)) {
+ // filter by position
+ continue;
+ }
+
+ // found one!
+ ret.add(poiPosition);
+ if (ret.size() > max) {
+ ret.remove(ret.last());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected static BlockPosition findAnyFirstPoi(VillagePlace poiStorage,
+ Predicate<VillagePlaceType> villagePlaceType,
+ Predicate<BlockPosition> positionPredicate,
+ BlockPosition sourcePosition,
+ int range, // distance on x y z axis
+ VillagePlace.Occupancy occupancy) {
+ Set<BlockPosition> ret = new java.util.HashSet<>();
+ findPoi(poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, occupancy, 1, ret);
+ return ret.isEmpty() ? null : ret.iterator().next();
+ }
+
+ protected static Set<BlockPosition> findPoi(VillagePlace poiStorage,
+ Predicate<VillagePlaceType> villagePlaceType,
+ Predicate<BlockPosition> positionPredicate,
+ BlockPosition sourcePosition,
+ int range, // distance on x y z axis
+ VillagePlace.Occupancy occupancy,
+ int max) {
+ Set<BlockPosition> ret = new java.util.HashSet<>();
+ findPoi(poiStorage, villagePlaceType, positionPredicate, sourcePosition, range, occupancy, max, ret);
+ return ret;
+ }
+ protected static void findPoi(VillagePlace poiStorage,
+ Predicate<VillagePlaceType> villagePlaceType,
+ Predicate<BlockPosition> positionPredicate,
+ BlockPosition sourcePosition,
+ int range, // distance on x y z axis
+ VillagePlace.Occupancy occupancy,
+ int max,
+ Set<BlockPosition> ret) {
+ // the biggest issue with the original mojang implementation is that they chain so many streams together
+ // the amount of streams chained just rolls performance, even if nothing is iterated over
+ Predicate<? super VillagePlaceRecord> occupancyFilter = occupancy.getPredicate();
+ double rangeSquared = range * range;
+
+ // First up, we need to iterate the chunks
+ // all the values here are in chunk sections
+ int lowerX = MathHelper.floor(sourcePosition.getX() - range) >> 4;
+ int lowerY = Math.max(0, MathHelper.floor(sourcePosition.getY() - range) >> 4);
+ int lowerZ = MathHelper.floor(sourcePosition.getZ() - range) >> 4;
+ int upperX = MathHelper.floor(sourcePosition.getX() + range) >> 4;
+ int upperY = Math.min(15, MathHelper.floor(sourcePosition.getY() + range) >> 4);
+ int upperZ = MathHelper.floor(sourcePosition.getZ() + range) >> 4;
+
+ // Vanilla iterates by x until max is reached then increases z
+ // vanilla also searches by increasing Y section value
+ for (int currZ = lowerZ; currZ <= upperZ; ++currZ) {
+ for (int currX = lowerX; currX <= upperX; ++currX) {
+ for (int currY = lowerY; currY <= upperY; ++currY) { // vanilla searches the entire chunk because they're actually stupid. just search the sections we need
+ Optional<VillagePlaceSection> poiSectionOptional = poiStorage.getIfLoaded(SectionPosition.asLong(currX, currY, currZ));
+ VillagePlaceSection poiSection = poiSectionOptional == null ? null : poiSectionOptional.orElse(null);
+ if (poiSection == null) {
+ continue;
+ }
+
+ java.util.Map<VillagePlaceType, Set<VillagePlaceRecord>> sectionData = poiSection.getData();
+ if (sectionData.isEmpty()) {
+ continue;
+ }
+
+ // now we search the section data
+ for (java.util.Iterator<java.util.Map.Entry<VillagePlaceType, Set<VillagePlaceRecord>>> iterator = sectionData.entrySet().iterator();
+ iterator.hasNext();) {
+ java.util.Map.Entry<VillagePlaceType, Set<VillagePlaceRecord>> entry = iterator.next();
+ if (!villagePlaceType.test(entry.getKey())) {
+ // filter out by poi type
+ continue;
+ }
+
+ // now we can look at the poi data
+ for (VillagePlaceRecord poiData : entry.getValue()) {
+ if (!occupancyFilter.test(poiData)) {
+ // filter by occupancy
+ continue;
+ }
+
+ // vanilla code is pretty dumb about filtering by distance: first they filter out
+ // so that only values in the square radius of range are returned but then they
+ // filter out so that the distance is in range
+ // but there's a catch! distanceSquared, by default, will ADD 0.5 to ONLY ONE OF the
+ // block position parameters (itself, in this case the poi position)! So if we want to
+ // maintain exact vanilla behaviour, well shit we need to play dumb as well.
+
+ BlockPosition poiPosition = poiData.getPosition();
+
+ if (Math.abs(poiPosition.getX() - sourcePosition.getX()) > range
+ || Math.abs(poiPosition.getZ() - sourcePosition.getZ()) > range) {
+ // out of range for square radius
+ continue;
+ }
+
+ if (poiPosition.distanceSquared(sourcePosition) > rangeSquared) {
+ // out of range for distance check
+ continue;
+ }
+
+ if (!positionPredicate.test(poiPosition)) {
+ // filter by position
+ continue;
+ }
+
+ // found one!
+ ret.add(poiPosition);
+ if (ret.size() >= max) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Tuinity - remove streams entirely for poi search
+
protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) {
this.f = i + 20L + (long) worldserver.getRandom().nextInt(20);
VillagePlace villageplace = worldserver.y();
@@ -74,7 +295,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
return true;
}
};
- Set<BlockPosition> set = (Set) villageplace.b(this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE).limit(5L).collect(Collectors.toSet());
+ Set<BlockPosition> set = findNearestPoi(villageplace, this.b.c(), predicate, entitycreature.getChunkCoordinates(), 48, VillagePlace.Occupancy.HAS_SPACE, 5); // Tuinity - remove streams entirely for poi search
PathEntity pathentity = entitycreature.getNavigation().a(set, this.b.d());
if (pathentity != null && pathentity.j()) {
@@ -84,7 +305,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
@@ -84,7 +84,7 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
villageplace.a(this.b.c(), (blockposition1) -> {
return blockposition1.equals(blockposition);
}, blockposition, 1);
@ -473,41 +229,6 @@ index 99b01cb35e2af2d61688b0b10ad1c655b9f2e4c3..1b56d83bdac536e8189901f03ad58e82
public double h(Entity entity) {
return this.e(entity.getPositionVector());
}
diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index 1558c5f8256f50be6850f1d7f70eee3e8ec76496..55fa3911703f96cf1f97c82b19d8e2d0d220016b 100644
--- a/src/main/java/net/minecraft/server/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java
@@ -85,7 +85,7 @@ public abstract class NavigationAbstract {
@Nullable
public PathEntity a(Stream<BlockPosition> stream, int i) {
- return this.a((Set) stream.collect(Collectors.toSet()), 8, false, i);
+ return this.a((Set) stream.collect(Collectors.toSet()), 8, false, i); // Tuinity - diff on change, inlined into SensorNearestBed
}
@Nullable
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalMoveThroughVillage.java b/src/main/java/net/minecraft/server/PathfinderGoalMoveThroughVillage.java
index 475c0764b97b056f17720f37b1ca3eb1a2375334..9f48d476c05dbeabbfe3c650ce4ad33ec691a56a 100644
--- a/src/main/java/net/minecraft/server/PathfinderGoalMoveThroughVillage.java
+++ b/src/main/java/net/minecraft/server/PathfinderGoalMoveThroughVillage.java
@@ -50,7 +50,7 @@ public class PathfinderGoalMoveThroughVillage extends PathfinderGoal {
if (!worldserver.a_(blockposition1)) {
return Double.NEGATIVE_INFINITY;
} else {
- Optional<BlockPosition> optional = worldserver.y().c(VillagePlaceType.b, this::a, blockposition1, 10, VillagePlace.Occupancy.IS_OCCUPIED);
+ Optional<BlockPosition> optional = Optional.ofNullable(BehaviorFindPosition.findAnyFirstPoi(worldserver.y(), VillagePlaceType.b, this::a, blockposition1, 10, VillagePlace.Occupancy.IS_OCCUPIED)); // Tuinity - remove streams here
return !optional.isPresent() ? Double.NEGATIVE_INFINITY : -((BlockPosition) optional.get()).j(blockposition);
}
@@ -59,7 +59,7 @@ public class PathfinderGoalMoveThroughVillage extends PathfinderGoal {
if (vec3d == null) {
return false;
} else {
- Optional<BlockPosition> optional = worldserver.y().c(VillagePlaceType.b, this::a, new BlockPosition(vec3d), 10, VillagePlace.Occupancy.IS_OCCUPIED);
+ Optional<BlockPosition> optional = Optional.ofNullable(BehaviorFindPosition.findAnyFirstPoi(worldserver.y(), VillagePlaceType.b, this::a, new BlockPosition(vec3d), 10, VillagePlace.Occupancy.IS_OCCUPIED)); // Tuinity - remove streams here
if (!optional.isPresent()) {
return false;
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
index 04256a95108b8182e8f808e856e0d2b62165e242..d9362b74fda2ea937281f897fbc2cb501775a275 100644
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
@ -524,20 +245,10 @@ index 04256a95108b8182e8f808e856e0d2b62165e242..d9362b74fda2ea937281f897fbc2cb50
}
diff --git a/src/main/java/net/minecraft/server/SensorNearestBed.java b/src/main/java/net/minecraft/server/SensorNearestBed.java
index ad3609f2b884f64f1a1a449036cece49a46e933e..d3d28f97f9d2f969a182aec5e0947b6969d2939c 100644
index ad3609f2b884f64f1a1a449036cece49a46e933e..83025d69e8a0732f16581fcfeaef5c1a45d70b63 100644
--- a/src/main/java/net/minecraft/server/SensorNearestBed.java
+++ b/src/main/java/net/minecraft/server/SensorNearestBed.java
@@ -40,15 +40,15 @@ public class SensorNearestBed extends Sensor<EntityInsentient> {
return true;
}
};
- Stream<BlockPosition> stream = villageplace.a(VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY);
- PathEntity pathentity = entityinsentient.getNavigation().a(stream, VillagePlaceType.r.d());
+ Set<BlockPosition> set = BehaviorFindPosition.findPoi(villageplace, VillagePlaceType.r.c(), predicate, entityinsentient.getChunkCoordinates(), 48, VillagePlace.Occupancy.ANY, Integer.MAX_VALUE); // Tuinity - remove streams
+ PathEntity pathentity = entityinsentient.getNavigation().a(set, 8, false, VillagePlaceType.r.d()); // this.a((Set) stream.collect(Collectors.toSet()), 8, false, i) // Tuinity - remove streams
if (pathentity != null && pathentity.j()) {
BlockPosition blockposition = pathentity.m();
@@ -48,7 +48,7 @@ public class SensorNearestBed extends Sensor<EntityInsentient> {
Optional<VillagePlaceType> optional = villageplace.c(blockposition);
if (optional.isPresent()) {

View File

@ -3,6 +3,7 @@ From: Andrew Steinborn <git@steinborn.me>
Date: Wed, 23 Sep 2020 01:46:46 -0400
Subject: [PATCH] Add Velocity natives for encryption and compression
This patch is licensed under the MIT license. See /licenses/MIT.md.
diff --git a/pom.xml b/pom.xml
index 650c6b91440d4ce1c5f82517a00056673750e74e..ddb06df414408461e2ad270e4849514cc7d3ec78 100644

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 2d15a4ea2958c4597269ba50bcd82282ee8e3bf0..8c4a350d59b20efb3f3c6c19e0ae0b676465de70 100644
index d04be5ae54ac543de144eb4ae87a255c467bc637..c7897e1a3655301d848313c26b244c325766253e 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -341,9 +341,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -356,9 +356,10 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.worldLoadListener = worldloadlistener;
// Paper start - use light thread

View File

@ -24,7 +24,7 @@ index 617ba6fb85c55967360ca270ee8feeff5acbf8e0..2644b190813cc934914aeab78fbd6515
if (this.remoteControlListener != null) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 29e7b4aa6e94566d446221cd28c2f60fdb3fccab..7ac34a8959a797bf2af96f3f402fa65cffe3d666 100644
index e64c57fd46f3d5e7989f01f063887e81be0590df..afc22e545df03a38c801362d308d135df90361e2 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -756,10 +756,11 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas

View File

@ -19,7 +19,7 @@ index ce0bb4d228a73d8353d67828529879e1c99682f9..18270d44185b0ec41b9b6e1d2135e7aa
}
} 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
index ac4b2d34824c00b655f9e5dbcc431b0ed8e4d765..d1832cd24667f62026f6f0b8d9d1cec8139aa057 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 {

View File

@ -37,23 +37,23 @@ by 2x. According to cpu time, the light engine itself spent 10x less time
lighting chunks for generation.
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
index dcbee6ebfac34f793c18f21e07187ae7dcb37695..c891f7c247c81a865720237f316f352b2289c724 100644
index 2f2701b9f0aa1a26a3e3eb7a14eac370f509ce1e..9d2ef2639f7a04aaf960be70384df24d8b4daf09 100644
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
@@ -186,6 +186,44 @@ public class PaperCommand extends Command {
@@ -219,6 +219,44 @@ public class PaperCommand extends Command {
}
}
+ private void starlightFixLight(EntityPlayer sender, WorldServer world, LightEngineThreaded lightengine, int radius) {
+ long start = System.nanoTime();
+ LinkedHashSet<ChunkCoordIntPair> chunks = new LinkedHashSet<>(MCUtil.getSpiralOutChunks(sender.getChunkCoordinates(), radius)); // getChunkCoordinates is actually just bad mappings, this function rets position as blockpos
+ java.util.LinkedHashSet<ChunkCoordIntPair> chunks = new java.util.LinkedHashSet<>(MCUtil.getSpiralOutChunks(sender.getChunkCoordinates(), radius)); // getChunkCoordinates is actually just bad mappings, this function rets position as blockpos
+
+ int[] pending = new int[1];
+ for (java.util.Iterator<ChunkCoordIntPair> iterator = chunks.iterator(); iterator.hasNext();) {
+ final ChunkCoordIntPair chunkPos = iterator.next();
+
+ final IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(chunkPos.x, chunkPos.z);
+ if (chunk == null || !chunk.isLit() || !chunk.getChunkStatus().isAtLeastStatus(ChunkStatus.LIGHT)) {
+ final net.minecraft.server.IChunkAccess chunk = world.getChunkProvider().getChunkAtImmediately(chunkPos.x, chunkPos.z);
+ if (chunk == null || !chunk.isLit() || !chunk.getChunkStatus().isAtLeastStatus(net.minecraft.server.ChunkStatus.LIGHT)) {
+ // cannot relight this chunk
+ iterator.remove();
+ continue;
@ -85,7 +85,7 @@ index dcbee6ebfac34f793c18f21e07187ae7dcb37695..c891f7c247c81a865720237f316f352b
private void doFixLight(CommandSender sender, String[] args) {
if (!(sender instanceof Player)) {
sender.sendMessage("Only players can use this command");
@@ -194,7 +232,7 @@ public class PaperCommand extends Command {
@@ -227,7 +265,7 @@ public class PaperCommand extends Command {
int radius = 2;
if (args.length > 1) {
try {
@ -94,7 +94,7 @@ index dcbee6ebfac34f793c18f21e07187ae7dcb37695..c891f7c247c81a865720237f316f352b
} catch (Exception e) {
sender.sendMessage("Not a number");
return;
@@ -207,6 +245,13 @@ public class PaperCommand extends Command {
@@ -240,6 +278,13 @@ public class PaperCommand extends Command {
net.minecraft.server.WorldServer world = (WorldServer) handle.world;
LightEngineThreaded lightengine = world.getChunkProvider().getLightEngine();
@ -5297,10 +5297,10 @@ index a22021766b3bffa4f96d1d4ee546b12e96b5ca58..3127fc9dd87e82243e167862cae83ac8
}
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 8c4a350d59b20efb3f3c6c19e0ae0b676465de70..44c04a0a0c744402edb5f6054919a3c181818c27 100644
index c7897e1a3655301d848313c26b244c325766253e..ff91f069e5f4a16c069c8a68d8cb55e9ad3627c8 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1322,6 +1322,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1350,6 +1350,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
// Tuinity end - force competion on the main thread
}
@ -5479,7 +5479,7 @@ 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 2814846acb8b855050a865770dcc12e00fb780d1..fda23d89da29e6a6065fc4bb57a4809f8bdb8b46 100644
index d1832cd24667f62026f6f0b8d9d1cec8139aa057..ff9cbb830779b54af3fd3964d559b0d88376681d 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -402,6 +402,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {

View File

@ -8,9 +8,18 @@ Instead, only iterate over navigators in the current region that are
eligible for repathing.
diff --git a/src/main/java/net/minecraft/server/NavigationAbstract.java b/src/main/java/net/minecraft/server/NavigationAbstract.java
index 55fa3911703f96cf1f97c82b19d8e2d0d220016b..b92ca4a6de01f3f86367fb8dfe3591b08a3e9218 100644
index 1558c5f8256f50be6850f1d7f70eee3e8ec76496..6aec5098d346c1b7498fd8b800154cd31ce08a97 100644
--- a/src/main/java/net/minecraft/server/NavigationAbstract.java
+++ b/src/main/java/net/minecraft/server/NavigationAbstract.java
@@ -8,7 +8,7 @@ import javax.annotation.Nullable;
public abstract class NavigationAbstract {
- protected final EntityInsentient a; public Entity getEntity() { return a; } // Paper - OBFHELPER
+ protected final EntityInsentient a; public final EntityInsentient getEntity() { return a; } // Paper - OBFHELPER // Tuinity - match types
protected final World b;
@Nullable
protected PathEntity c; protected final PathEntity getCurrentPath() { return this.c; } // Paper - OBFHELPER
@@ -21,7 +21,7 @@ public abstract class NavigationAbstract {
protected long j;
protected double k;
@ -44,28 +53,110 @@ 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 44c04a0a0c744402edb5f6054919a3c181818c27..3ef3c05be2241c43bbef096b00c4b68141af3924 100644
index ff91f069e5f4a16c069c8a68d8cb55e9ad3627c8..58089180c730ce0bc423cdb20e86f11858543c25 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -295,7 +295,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -299,17 +299,82 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
public static final class DataRegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionData {
// Tuinity start
public static enum RegionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionDataCreator<RegionData> {
-
+ // Tuinity start - optimise notify()
+ PATHING_NAVIGATORS() {
+ @Override
+ public Object createData(com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<RegionData> section,
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager<RegionData> regionManager) {
+ return new com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<>(true);
+ private com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<EntityInsentient> navigators;
+ public com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<EntityInsentient> getNavigators() {
+ return this.navigators;
+ }
+
+ public boolean addToNavigators(final EntityInsentient navigator) {
+ if (this.navigators == null) {
+ this.navigators = new com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<>();
+ }
+ return this.navigators.add(navigator);
+ }
+
+ public boolean removeFromNavigators(final EntityInsentient navigator) {
+ if (this.navigators == null) {
+ return false;
+ }
+ return this.navigators.remove(navigator);
+ }
+ // Tuinity end - optimise notify()
;
}
public static final class DataRegionSectionData implements com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSectionData {
+ // Tuinity start - optimise notify()
+ private com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<EntityInsentient> navigators;
+
+ public com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<EntityInsentient> getNavigators() {
+ return this.navigators;
+ }
+
+ public boolean addToNavigators(final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section, final EntityInsentient navigator) {
+ if (this.navigators == null) {
+ this.navigators = new com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<>();
+ }
+ final boolean ret = this.navigators.add(navigator);
+ if (ret) {
+ final DataRegionData data = (DataRegionData)section.getRegion().regionData;
+ if (!data.addToNavigators(navigator)) {
+ throw new IllegalStateException();
+ }
+ }
+ return ret;
+ }
+
+ public boolean removeFromNavigators(final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section, final EntityInsentient navigator) {
+ if (this.navigators == null) {
+ return false;
+ }
+ final boolean ret = this.navigators.remove(navigator);
+ if (ret) {
+ final DataRegionData data = (DataRegionData)section.getRegion().regionData;
+ if (!data.removeFromNavigators(navigator)) {
+ throw new IllegalStateException();
+ }
+ }
+ return ret;
+ }
+ // Tuinity end - optimise notify()
+
@Override
public void removeFromRegion(final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section,
final com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region from) {
final DataRegionSectionData sectionData = (DataRegionSectionData)section.sectionData;
final DataRegionData fromData = (DataRegionData)from.regionData;
+ // Tuinity start - optimise notify()
+ if (sectionData.navigators != null) {
+ for (final Iterator<EntityInsentient> iterator = sectionData.navigators.unsafeIterator(com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ if (!fromData.removeFromNavigators(iterator.next())) {
+ throw new IllegalStateException();
+ }
+ }
+ }
+ // Tuinity end - optimise notify()
}
@Override
@@ -319,6 +384,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
final DataRegionSectionData sectionData = (DataRegionSectionData)section.sectionData;
final DataRegionData oldRegionData = oldRegion == null ? null : (DataRegionData)oldRegion.regionData;
final DataRegionData newRegionData = (DataRegionData)newRegion.regionData;
+ // Tuinity start - optimise notify()
+ if (sectionData.navigators != null) {
+ for (final Iterator<EntityInsentient> iterator = sectionData.navigators.unsafeIterator(com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.ITERATOR_FLAG_SEE_ADDITIONS); iterator.hasNext();) {
+ if (!newRegionData.addToNavigators(iterator.next())) {
+ throw new IllegalStateException();
+ }
+ }
+ }
+ // Tuinity end - optimise notify()
}
}
// Tuiniy end
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cbca2017e4 100644
index ff9cbb830779b54af3fd3964d559b0d88376681d..c6d2ab318d711072507ce3667d07a9cdeb0d0fbe 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -970,6 +970,15 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@ -99,20 +190,20 @@ index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cb
gameprofilerfiller.exit();
}
@@ -1401,6 +1417,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1403,6 +1419,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);
+ // Tuinity start
+ int oldRegionX = entity.chunkX >> com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.REGION_CHUNK_SIZE_SHIFT;
+ int oldRegionZ = entity.chunkZ >> com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.REGION_CHUNK_SIZE_SHIFT;
+ int newRegionX = i >> com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.REGION_CHUNK_SIZE_SHIFT;
+ int newRegionZ = k >> com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.REGION_CHUNK_SIZE_SHIFT;
+ int oldRegionX = entity.chunkX >> this.getChunkProvider().playerChunkMap.dataRegionManager.regionChunkShift;
+ int oldRegionZ = entity.chunkZ >> this.getChunkProvider().playerChunkMap.dataRegionManager.regionChunkShift;
+ int newRegionX = i >> this.getChunkProvider().playerChunkMap.dataRegionManager.regionChunkShift;
+ int newRegionZ = k >> this.getChunkProvider().playerChunkMap.dataRegionManager.regionChunkShift;
+ // Tuinity end
if (!entity.inChunk || entity.chunkX != i || entity.chunkY != j || entity.chunkZ != k) {
// Paper start - remove entity if its in a chunk more correctly.
@@ -1410,6 +1432,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1412,6 +1434,12 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
// Paper end
@ -125,7 +216,7 @@ index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cb
if (entity.inChunk && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) {
this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.chunkY);
}
@@ -1423,6 +1451,11 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1425,6 +1453,11 @@ public class WorldServer extends World implements GeneratorAccessSeed {
} else {
this.getChunkAt(i, k).a(entity);
}
@ -137,7 +228,7 @@ index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cb
}
this.getMethodProfiler().exit();
@@ -1885,9 +1918,96 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1887,9 +1920,64 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// Tuinity end
}
new com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
@ -147,84 +238,52 @@ index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cb
+ // Tuinity start - optimise notify()
+ void removeNavigatorsIfNotPathingFromRegion(Entity entity) {
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData> section =
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section =
+ this.getChunkProvider().playerChunkMap.dataRegionManager.getRegionSection(entity.chunkX, entity.chunkZ);
+ if (section != null) {
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<NavigationAbstract> navigators = (com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet)section.getOrCreateData(PlayerChunkMap.RegionData.PATHING_NAVIGATORS);
+ // Copied from above
+ if (entity instanceof EntityDrowned) {
+ if (!((EntityDrowned)entity).navigationWater.isViableForPathRecalculationChecking()) {
+ navigators.remove(((EntityDrowned)entity).navigationWater);
+ }
+ if (!((EntityDrowned)entity).navigationLand.isViableForPathRecalculationChecking()) {
+ navigators.remove(((EntityDrowned)entity).navigationLand);
+ }
+ } else if (entity instanceof EntityInsentient) {
+ PlayerChunkMap.DataRegionSectionData sectionData = (PlayerChunkMap.DataRegionSectionData)section.sectionData;
+ if (entity instanceof EntityInsentient) {
+ if (!((EntityInsentient)entity).getNavigation().isViableForPathRecalculationChecking()) {
+ navigators.remove(((EntityInsentient)entity).getNavigation());
+ sectionData.removeFromNavigators(section, (EntityInsentient)entity);
+ }
+ }
+ }
+ }
+
+ void removeNavigatorsFromData(Entity entity) {
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData> section =
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section =
+ this.getChunkProvider().playerChunkMap.dataRegionManager.getRegionSection(entity.chunkX, entity.chunkZ);
+ if (section != null) {
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<NavigationAbstract> navigators = (com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet)section.getOrCreateData(PlayerChunkMap.RegionData.PATHING_NAVIGATORS);
+ // Copied from above
+ if (entity instanceof EntityDrowned) {
+ navigators.remove(((EntityDrowned)entity).navigationWater);
+ navigators.remove(((EntityDrowned)entity).navigationLand);
+ } else if (entity instanceof EntityInsentient) {
+ navigators.remove(((EntityInsentient)entity).getNavigation());
+ PlayerChunkMap.DataRegionSectionData sectionData = (PlayerChunkMap.DataRegionSectionData)section.sectionData;
+ if (entity instanceof EntityInsentient) {
+ sectionData.removeFromNavigators(section, ((EntityInsentient)entity));
+ }
+ }
+ }
+
+ void addNavigatorsIfPathingToRegion(Entity entity) {
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData> section =
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section =
+ this.getChunkProvider().playerChunkMap.dataRegionManager.getRegionSection(entity.chunkX, entity.chunkZ);
+ if (section != null) {
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<NavigationAbstract> navigators = (com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet)section.getOrCreateData(PlayerChunkMap.RegionData.PATHING_NAVIGATORS);
+ // Copied from above
+ if (entity instanceof EntityDrowned) {
+ if (((EntityDrowned)entity).navigationWater.isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityDrowned)entity).navigationWater);
+ }
+ if (((EntityDrowned)entity).navigationLand.isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityDrowned)entity).navigationLand);
+ }
+ } else if (entity instanceof EntityInsentient) {
+ PlayerChunkMap.DataRegionSectionData sectionData = (PlayerChunkMap.DataRegionSectionData)section.sectionData;
+ if (entity instanceof EntityInsentient) {
+ if (((EntityInsentient)entity).getNavigation().isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityInsentient)entity).getNavigation());
+ sectionData.addToNavigators(section, ((EntityInsentient)entity));
+ }
+ }
+ }
+ }
+
+ void updateNavigatorsInRegion(Entity entity) {
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData> section =
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection section =
+ this.getChunkProvider().playerChunkMap.dataRegionManager.getRegionSection(entity.chunkX, entity.chunkZ);
+ if (section != null) {
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<NavigationAbstract> navigators = (com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet)section.getOrCreateData(PlayerChunkMap.RegionData.PATHING_NAVIGATORS);
+ // Copied from above
+ if (entity instanceof EntityDrowned) {
+ if (((EntityDrowned)entity).navigationWater.isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityDrowned)entity).navigationWater);
+ } else {
+ navigators.remove(((EntityDrowned)entity).navigationWater);
+ }
+ if (((EntityDrowned)entity).navigationLand.isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityDrowned)entity).navigationLand);
+ } else {
+ navigators.remove(((EntityDrowned)entity).navigationLand);
+ }
+ } else if (entity instanceof EntityInsentient) {
+ PlayerChunkMap.DataRegionSectionData sectionData = (PlayerChunkMap.DataRegionSectionData)section.sectionData;
+ if (entity instanceof EntityInsentient) {
+ if (((EntityInsentient)entity).getNavigation().isViableForPathRecalculationChecking()) {
+ navigators.add(((EntityInsentient)entity).getNavigation());
+ sectionData.addToNavigators(section, ((EntityInsentient)entity));
+ } else {
+ navigators.remove(((EntityInsentient)entity).getNavigation());
+ sectionData.removeFromNavigators(section, ((EntityInsentient)entity));
+ }
+ }
+ }
@ -234,52 +293,32 @@ index fda23d89da29e6a6065fc4bb57a4809f8bdb8b46..d2b50cdc43c737d9fdfdcd7838de24cb
private void registerEntity(Entity entity) {
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
// Paper start - don't double enqueue entity registration
@@ -2068,9 +2188,25 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -2070,16 +2158,26 @@ public class WorldServer extends World implements GeneratorAccessSeed {
VoxelShape voxelshape1 = iblockdata1.getCollisionShape(this, blockposition);
if (VoxelShapes.c(voxelshape, voxelshape1, OperatorBoolean.NOT_SAME)) {
+ // Tuinity start - optimise notify()
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region<PlayerChunkMap.RegionData> region = this.getChunkProvider().playerChunkMap.dataRegionManager.getRegion(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.Region region = this.getChunkProvider().playerChunkMap.dataRegionManager.getRegion(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ if (region == null) {
+ return;
+ }
+ // Tuinity end - optimise notify()
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<EntityInsentient> navigatorsFromRegion = ((PlayerChunkMap.DataRegionData)region.regionData).getNavigators();
+ if (navigatorsFromRegion == null) {
+ return;
+ }
boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper
// Tuinity start
- com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator iterator = this.navigatorsForIteration.iterator();
+ // Tuinity start - optimise notify()
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData>> sectionIterator = null;
+ try {
+ for (sectionIterator = region.getSections(); sectionIterator.hasNext();) {
+ com.tuinity.tuinity.chunk.SingleThreadChunkRegionManager.RegionSection<PlayerChunkMap.RegionData> section = sectionIterator.next();
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet<NavigationAbstract> navigators = (com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet)section.getData(PlayerChunkMap.RegionData.PATHING_NAVIGATORS);
+ if (navigators == null) {
+ continue;
+ }
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator iterator = navigators.iterator();
+ com.tuinity.tuinity.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<EntityInsentient> iterator = navigatorsFromRegion.iterator();
+ // Tuinity end - optimise notify()
try { // Tuinity end
while (iterator.hasNext()) {
@@ -2090,10 +2226,21 @@ public class WorldServer extends World implements GeneratorAccessSeed {
if (!navigationabstract.i()) {
navigationabstract.b(blockposition);
}
+ // Tuinity start - optimise notify()
+ if (!navigationabstract.isViableForPathRecalculationChecking()) {
+ navigators.remove(navigationabstract);
+ }
+ // Tuinity end - optimise notify()
}
} finally { // Tuinity start
iterator.finishedIterating();
} // Tuinity end
+ } // Tuinity start - optimise notify()
+ } finally {
+ if (sectionIterator != null) {
+ sectionIterator.finishedIterating();
+ }
+ } // Tuinity end - optimise notify()
this.tickingEntities = wasTicking; // Paper
}
// CraftBukkit start - fix SPIGOT-6362
NavigationAbstract navigationabstract;
try {
- navigationabstract = (NavigationAbstract) iterator.next();
+ navigationabstract = (NavigationAbstract) iterator.next().getNavigation(); // Tuinity - optimise notify
} catch (java.util.ConcurrentModificationException ex) {
// This can happen because the pathfinder update below may trigger a chunk load, which in turn may cause more navigators to register
// In this case we just run the update again across all the iterators as the chunk will then be loaded

View File

@ -25,18 +25,18 @@ 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 3ef3c05be2241c43bbef096b00c4b68141af3924..36418fb2ede9e98c021c5e62150c46d91e5e3e01 100644
index 58089180c730ce0bc423cdb20e86f11858543c25..6ac16c7252f5f9e7259eed2bae74a14d57a9bd37 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -842,6 +842,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
@@ -928,6 +928,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
// Tuinity end
}
+ this.getVillagePlace().dequeueUnload(playerchunk.location.pair()); // Tuinity - unload POI data
this.updatingChunks.put(i, playerchunk);
this.updatingChunksModified = true;
@@ -967,7 +968,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1053,7 +1054,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
}
@ -45,23 +45,23 @@ index 3ef3c05be2241c43bbef096b00c4b68141af3924..36418fb2ede9e98c021c5e62150c46d9
protected void unloadChunks(BooleanSupplier booleansupplier) {
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
@@ -1095,6 +1096,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
boolean removed;
if ((removed = this.pendingUnload.remove(i, playerchunk)) && ichunkaccess != null) { // Tuinity end
this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z); // Tuinity
@@ -1185,6 +1186,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.regionManagers.get(index).removeChunk(playerchunk.location.x, playerchunk.location.z);
}
// Tuinity end
+ this.getVillagePlace().queueUnload(playerchunk.location.pair(), MinecraftServer.currentTickLong + 1); // Tuinity - unload POI data
if (ichunkaccess instanceof Chunk) {
((Chunk) ichunkaccess).setLoaded(false);
}
@@ -1119,6 +1121,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.worldLoadListener.a(ichunkaccess.getPos(), (ChunkStatus) null);
} else if (removed) { // Tuinity start
this.dataRegionManager.removeChunk(playerchunk.location.x, playerchunk.location.z);
@@ -1213,6 +1215,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
this.regionManagers.get(index).removeChunk(playerchunk.location.x, playerchunk.location.z);
}
// Tuinity end
+ this.getVillagePlace().queueUnload(playerchunk.location.pair(), MinecraftServer.currentTickLong + 1); // Tuinity - unload POI data
} // Tuinity end
} finally { this.unloadingPlayerChunk = unloadingBefore; } // Tuinity - do not allow ticket level changes while unloading chunks
@@ -1212,6 +1215,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1306,6 +1309,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 36418fb2ede9e98c021c5e62150c46d91e5e3e01..391b1db2d457daeed0c3276d2e408a86f1f2e866 100644
index 6ac16c7252f5f9e7259eed2bae74a14d57a9bd37..74408c70f896bffba3d021f601db2aa58f93b506 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -1501,9 +1501,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
@@ -1595,9 +1595,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
chunk.B();
return chunk;
});

View File

@ -36,10 +36,10 @@ index 50c61b633faaa47a86172315b53899d3747c8e27..2ec48858be8eb2c522c9685b43bd36b3
// Paper end - optimise entity tracking
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 391b1db2d457daeed0c3276d2e408a86f1f2e866..285e976d4a655fb61e70883ae89f974812be7152 100644
index 74408c70f896bffba3d021f601db2aa58f93b506..9129a720e4d85ffbeaa4c76473de6786ffd816fd 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -2546,7 +2546,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
@@ -2640,7 +2640,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
int j = entity.getEntityType().getChunkRange() * 16;
j = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, j); // Paper

View File

@ -48,10 +48,10 @@ index cf14b83ec3c2b9a2812f50f3bca991e029bf7c67..f40c24b6e2f7bea21d1cb2b58ed3da45
public void broadcastCarriedItem() {
if (!this.e) {
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index d2b50cdc43c737d9fdfdcd7838de24cbca2017e4..9c77be805eb71c409a5d41c2730338583527e447 100644
index c6d2ab318d711072507ce3667d07a9cdeb0d0fbe..658d74b8ab1698fa2832facc6d8e9678af958c85 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1792,9 +1792,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@@ -1794,9 +1794,13 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// Spigot Start
for (TileEntity tileentity : chunk.getTileEntities().values()) {
if (tileentity instanceof IInventory) {

View File

@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 19 Feb 2021 18:45:25 -0800
Subject: [PATCH] Remove chunk lookup & lambda allocation from counting mobs
The chunk lookup doesn't look cheap.
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index e26389d8d9ee4fedb32767fce3aed071af412304..cce750fd5725a232db16cd8ec4603d5cf09da3df 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -991,9 +991,9 @@ public class ChunkProviderServer extends IChunkProvider {
for (EntityPlayer player : this.world.players) {
Arrays.fill(player.mobCounts, 0);
}
- spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true);
+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, true, this); // Tuinity
} else {
- spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false);
+ spawnercreature_d = SpawnerCreature.countMobs(l, this.world.A(), this::a, false, this); // Tuinity
}
// Paper end
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
index a77b1d61b9dcb0a2a27d7e50357eaf44c99a661e..53fd0549c965b2252ad80648d61ff1f7cd2b837a 100644
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
@@ -30,9 +30,9 @@ public final class SpawnerCreature {
public static SpawnerCreature.d a(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b) {
// Paper start - add countMobs parameter
- return countMobs(i, iterable, spawnercreature_b, false);
+ return countMobs(i, iterable, spawnercreature_b, false, null); // Tuinity - it'll still be broken no matter what
}
- public static SpawnerCreature.d countMobs(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs) {
+ public static SpawnerCreature.d countMobs(int i, Iterable<Entity> iterable, SpawnerCreature.b spawnercreature_b, boolean countMobs, ChunkProviderServer chunkProvider) { // Tuinity - add CPS param
// Paper end - add countMobs parameter
SpawnerCreatureProbabilities spawnercreatureprobabilities = new SpawnerCreatureProbabilities();
Object2IntOpenHashMap<EnumCreatureType> object2intopenhashmap = new Object2IntOpenHashMap();
@@ -63,7 +63,16 @@ public final class SpawnerCreature {
BlockPosition blockposition = entity.getChunkCoordinates();
long j = ChunkCoordIntPair.pair(blockposition.getX() >> 4, blockposition.getZ() >> 4);
- spawnercreature_b.query(j, (chunk) -> {
+ // Tuinity start - remove chunk lookup and lambda
+ Chunk chunk = entity.getCurrentChunk();
+ if (chunk == null || j != chunk.coordinateKey) { // no chunk or coordinate doesn't match
+ chunk = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ if (chunk == null) {
+ // unloaded chunk! no longer FULL.
+ continue;
+ }
+ }
+ // Tuinity end - remove chunk lookup and lambda
BiomeSettingsMobs.b biomesettingsmobs_b = b(blockposition, chunk).b().a(entity.getEntityType());
if (biomesettingsmobs_b != null) {
@@ -73,10 +82,10 @@ public final class SpawnerCreature {
object2intopenhashmap.addTo(enumcreaturetype, 1);
// Paper start
if (countMobs) {
- ((WorldServer)chunk.world).getChunkProvider().playerChunkMap.updatePlayerMobTypeMap(entity);
+ chunkProvider.playerChunkMap.updatePlayerMobTypeMap(entity); // Tuinity - directly use chunk provider
}
// Paper end
- });
+ // Tuinity - remove chunk lookup and lambda
}
}

View File

@ -0,0 +1,139 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 19 Feb 2021 19:27:34 -0800
Subject: [PATCH] Optimise snow & ice in chunk ticking
Avoid the biome lookups most of the time by
hiding them behind the snow/air checks. The biome
checks take up the most here, followed by the block gets.
Soften some of the block gets by passing the chunk to
the biome methods, removing the need to invoke a chunk
lookup.
diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java
index 0854ac9ef586b378420d9899f3afd2755e6f9f33..3fc101552e3c229076c91a1cfa45206b4cc7a04c 100644
--- a/src/main/java/net/minecraft/server/BiomeBase.java
+++ b/src/main/java/net/minecraft/server/BiomeBase.java
@@ -145,14 +145,33 @@ public final class BiomeBase {
}
public boolean a(IWorldReader iworldreader, BlockPosition blockposition, boolean flag) {
- if (this.getAdjustedTemperature(blockposition) >= 0.15F) {
+ // Tuinity start - add chunk parameter and lazily get biome
+ return canTurnWaterIntoIce(iworldreader, blockposition, flag, null, new BiomeBase[] { this });
+ }
+ public static boolean canTurnWaterIntoIce(IWorldReader iworldreader, BlockPosition blockposition, boolean flag, IChunkAccess chunk, BiomeBase[] biomeAbove) {
+ // Tuinity end - add chunk parameter and lazily get biome
+ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive
return false;
} else {
if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) {
- IBlockData iblockdata = iworldreader.getType(blockposition);
- Fluid fluid = iworldreader.getFluid(blockposition);
+ // Tuinity start - add chunk parameter
+ if (chunk == null) {
+ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ }
+ // Tuinity end - add chunk parameter
+ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk
+ Fluid fluid = iblockdata.getFluid(); // Tuinity - skip another block lookup, we have the blockdata
if (fluid.getType() == FluidTypes.WATER && iblockdata.getBlock() instanceof BlockFluids) {
+ // Tuinity start - moved down from top, only run when we actually encounter water
+ if (biomeAbove[0] == null) {
+ // lazily-get biome
+ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc
+ }
+ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) {
+ return false;
+ }
+ // Tuinity end - moved down from top, only run when we actually encounter water
if (!flag) {
return true;
}
@@ -170,13 +189,32 @@ public final class BiomeBase {
}
public boolean b(IWorldReader iworldreader, BlockPosition blockposition) {
- if (this.getAdjustedTemperature(blockposition) >= 0.15F) {
+ // Tuinity start - add chunk parameter and lazily get biome
+ return canTurnAirIntoSnow(iworldreader, blockposition, null, new BiomeBase[]{ this });
+ }
+ public static boolean canTurnAirIntoSnow(IWorldReader iworldreader, BlockPosition blockposition, IChunkAccess chunk, BiomeBase[] biomeAbove) {
+ // Tuinity end - add chunk parameter and lazily get biome
+ if (false && biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) { // Tuinity - move this down, this check is expensive
return false;
} else {
if (blockposition.getY() >= 0 && blockposition.getY() < 256 && iworldreader.getBrightness(EnumSkyBlock.BLOCK, blockposition) < 10) {
- IBlockData iblockdata = iworldreader.getType(blockposition);
+ // Tuinity start - add chunk parameter
+ if (chunk == null) {
+ chunk = iworldreader.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4);
+ }
+ // Tuinity end - add chunk parameter
+ IBlockData iblockdata = chunk.getType(blockposition); // Tuinity - skip chunk lookup, we got the chunk
if (iblockdata.isAir() && Blocks.SNOW.getBlockData().canPlace(iworldreader, blockposition)) {
+ // Tuinity start - moved down from top, only run when we actually encounter water
+ if (biomeAbove[0] == null) {
+ // lazily-get biome
+ biomeAbove[0] = iworldreader.getBiome(blockposition.up()); // TODO - avoid blockpos alloc
+ }
+ if (biomeAbove[0].getAdjustedTemperature(blockposition) >= 0.15F) {
+ return false;
+ }
+ // Tuinity end - moved down from top, only run when we actually encounter water
return true;
}
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 658d74b8ab1698fa2832facc6d8e9678af958c85..a77fceac7c9e79a6bac05becc21bcb6bf2a1a7c7 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -1083,6 +1083,9 @@ public class WorldServer extends World implements GeneratorAccessSeed {
private final BlockPosition.MutableBlockPosition chunkTickMutablePosition = new BlockPosition.MutableBlockPosition();
private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom();
// Paper end
+ // Tuinity start - optimise chunk ice snow ticking
+ private final BiomeBase[] biomeBaseCache = new BiomeBase[1];
+ // Tuinity end - optimise chunk ice snow ticking
public void a(Chunk chunk, int i) { final int randomTickSpeed = i; // Paper
ChunkCoordIntPair chunkcoordintpair = chunk.getPos();
@@ -1120,28 +1123,32 @@ public class WorldServer extends World implements GeneratorAccessSeed {
gameprofilerfiller.exitEnter("iceandsnow");
if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
// Paper start - optimise chunk ticking
+ // Tuinity start - optimise chunk ice snow ticking
+ BiomeBase[] biomeCache = this.biomeBaseCache;
+ biomeCache[0] = null;
+ // Tuinity start - optimise chunk ice snow ticking
this.getRandomBlockPosition(j, 0, k, 15, blockposition);
int normalY = chunk.getHighestBlockY(HeightMap.Type.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15);
int downY = normalY - 1;
blockposition.setY(normalY);
// Paper end
- BiomeBase biomebase = this.getBiome(blockposition);
+ //BiomeBase biomebase = this.getBiome(blockposition); // Tuinity - lazily-get biome
// Paper start - optimise chunk ticking
blockposition.setY(downY);
- if (biomebase.a(this, blockposition)) {
+ if (BiomeBase.canTurnWaterIntoIce(this, blockposition, true, chunk, biomeCache)) { // Tuinity - add chunk parameter, avoid biome lookup
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.getBlockData(), null); // CraftBukkit
// Paper end
}
blockposition.setY(normalY); // Paper
- if (flag && biomebase.b(this, blockposition)) {
+ if (flag && BiomeBase.canTurnAirIntoSnow(this, blockposition, chunk, biomeCache)) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.getBlockData(), null); // CraftBukkit
}
// Paper start - optimise chunk ticking
blockposition.setY(downY);
- if (flag && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) {
+ if (flag && chunk.getType(blockposition).getBlock() instanceof BlockCauldron && this.getBiome(blockposition).c() == BiomeBase.Precipitation.RAIN) { // Tuinity - only cauldron uses that method, and it's not likely to hit. So, avoid the expensive biome lookup and replace it with a block lookup TODO check on update for overrides
chunk.getType(blockposition).getBlock().c((World) this, blockposition);
// Paper end
}

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Fri, 19 Feb 2021 22:51:52 -0800
Subject: [PATCH] Oprimise map impl for tracked players
Reference2BooleanOpenHashMap is going to have
better lookups than HashMap.
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 9129a720e4d85ffbeaa4c76473de6786ffd816fd..fd7d403b7aac37f5b97a8c73bc6f0c4c587ac546 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -49,6 +49,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet; // Paper
+import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap; // Tuinity
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -2489,7 +2490,7 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
// Paper start
// Replace trackedPlayers Set with a Map. The value is true until the player receives
// their first update (which is forced to have absolute coordinates), false afterward.
- public java.util.Map<EntityPlayer, Boolean> trackedPlayerMap = new java.util.HashMap<>();
+ public java.util.Map<EntityPlayer, Boolean> trackedPlayerMap = new Reference2BooleanOpenHashMap<>(); // Tuinity - optimise map impl
public Set<EntityPlayer> trackedPlayers = trackedPlayerMap.keySet();
public EntityTracker(Entity entity, int i, int j, boolean flag) {

View File

@ -0,0 +1,348 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 11 Mar 2021 20:05:44 -0800
Subject: [PATCH] Custom table implementation for blockstate state lookups
Testing some redstone intensive machines showed to bring about a 10%
improvement.
diff --git a/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java b/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..298d09634effcb06cd2237a1f7f903e9e46ec78d
--- /dev/null
+++ b/src/main/java/com/tuinity/tuinity/util/table/ZeroCollidingReferenceStateTable.java
@@ -0,0 +1,160 @@
+package com.tuinity.tuinity.util.table;
+
+import com.google.common.collect.Table;
+import net.minecraft.server.IBlockDataHolder;
+import net.minecraft.server.IBlockState;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public final class ZeroCollidingReferenceStateTable {
+
+ // upper 32 bits: starting index
+ // lower 32 bits: bitset for contained ids
+ protected final long[] this_index_table;
+ protected final Comparable<?>[] this_table;
+ protected final IBlockDataHolder<?, ?> this_state;
+
+ protected long[] index_table;
+ protected IBlockDataHolder<?, ?>[][] value_table;
+
+ public ZeroCollidingReferenceStateTable(final IBlockDataHolder<?, ?> state, final Map<IBlockState<?>, Comparable<?>> this_map) {
+ this.this_state = state;
+ this.this_index_table = this.create_table(this_map.keySet());
+
+ int max_id = -1;
+ for (final IBlockState<?> property : this_map.keySet()) {
+ final int id = lookup_vindex(property, this.this_index_table);
+ if (id > max_id) {
+ max_id = id;
+ }
+ }
+
+ this.this_table = new Comparable[max_id + 1];
+ for (final Map.Entry<IBlockState<?>, Comparable<?>> entry : this_map.entrySet()) {
+ this.this_table[lookup_vindex(entry.getKey(), this.this_index_table)] = entry.getValue();
+ }
+ }
+
+ public void loadInTable(final Table<IBlockState<?>, Comparable<?>, IBlockDataHolder<?, ?>> table,
+ final Map<IBlockState<?>, Comparable<?>> this_map) {
+ final Set<IBlockState<?>> combined = new HashSet<>(table.rowKeySet());
+ combined.addAll(this_map.keySet());
+
+ this.index_table = this.create_table(combined);
+
+ int max_id = -1;
+ for (final IBlockState<?> property : combined) {
+ final int id = lookup_vindex(property, this.index_table);
+ if (id > max_id) {
+ max_id = id;
+ }
+ }
+
+ this.value_table = new IBlockDataHolder[max_id + 1][];
+
+ final Map<IBlockState<?>, Map<Comparable<?>, IBlockDataHolder<?, ?>>> map = table.rowMap();
+ for (final IBlockState<?> property : map.keySet()) {
+ final Map<Comparable<?>, IBlockDataHolder<?, ?>> propertyMap = map.get(property);
+
+ final int id = lookup_vindex(property, this.index_table);
+ final IBlockDataHolder<?, ?>[] states = this.value_table[id] = new IBlockDataHolder[property.getValues().size()];
+
+ for (final Map.Entry<Comparable<?>, IBlockDataHolder<?, ?>> entry : propertyMap.entrySet()) {
+ if (entry.getValue() == null) {
+ // TODO what
+ continue;
+ }
+
+ states[((IBlockState)property).getIdFor(entry.getKey())] = entry.getValue();
+ }
+ }
+
+
+ for (final Map.Entry<IBlockState<?>, Comparable<?>> entry : this_map.entrySet()) {
+ final IBlockState<?> property = entry.getKey();
+ final int index = lookup_vindex(property, this.index_table);
+
+ if (this.value_table[index] == null) {
+ this.value_table[index] = new IBlockDataHolder[property.getValues().size()];
+ }
+
+ this.value_table[index][((IBlockState)property).getIdFor(entry.getValue())] = this.this_state;
+ }
+ }
+
+
+ protected long[] create_table(final Collection<IBlockState<?>> collection) {
+ int max_id = -1;
+ for (final IBlockState<?> property : collection) {
+ final int id = property.getId();
+ if (id > max_id) {
+ max_id = id;
+ }
+ }
+
+ final long[] ret = new long[((max_id + 1) + 31) >>> 5]; // ceil((max_id + 1) / 32)
+
+ for (final IBlockState<?> property : collection) {
+ final int id = property.getId();
+
+ ret[id >>> 5] |= (1L << (id & 31));
+ }
+
+ int total = 0;
+ for (int i = 1, len = ret.length; i < len; ++i) {
+ ret[i] |= (long)(total += Long.bitCount(ret[i - 1] & 0xFFFFFFFFL)) << 32;
+ }
+
+ return ret;
+ }
+
+ public Comparable<?> get(final IBlockState<?> state) {
+ final Comparable<?>[] table = this.this_table;
+ final int index = lookup_vindex(state, this.this_index_table);
+
+ if (index < 0 || index >= table.length) {
+ return null;
+ }
+ return table[index];
+ }
+
+ public IBlockDataHolder<?, ?> get(final IBlockState<?> property, final Comparable<?> with) {
+ final int withId = ((IBlockState)property).getIdFor(with);
+ if (withId < 0) {
+ return null;
+ }
+
+ final int index = lookup_vindex(property, this.index_table);
+ final IBlockDataHolder<?, ?>[][] table = this.value_table;
+ if (index < 0 || index >= table.length) {
+ return null;
+ }
+
+ final IBlockDataHolder<?, ?>[] values = table[index];
+
+ if (withId >= values.length) {
+ return null;
+ }
+
+ return values[withId];
+ }
+
+ protected static int lookup_vindex(final IBlockState<?> property, final long[] index_table) {
+ final int id = property.getId();
+ final long bitset_mask = (1L << (id & 31));
+ final long lower_mask = bitset_mask - 1;
+ final int index = id >>> 5;
+ if (index >= index_table.length) {
+ return -1;
+ }
+ final long index_value = index_table[index];
+ final long contains_check = ((index_value & bitset_mask) - 1) >> (Long.SIZE - 1); // -1L if doesn't contain
+
+ // index = total bits set in lower table values (upper 32 bits of index_value) plus total bits set in lower indices below id
+ // contains_check is 0 if the bitset had id set, else it's -1: so index is unaffected if contains_check == 0,
+ // otherwise it comes out as -1.
+ return (int)(((index_value >>> 32) + Long.bitCount(index_value & lower_mask)) | contains_check);
+ }
+}
diff --git a/src/main/java/net/minecraft/server/BlockStateBoolean.java b/src/main/java/net/minecraft/server/BlockStateBoolean.java
index 4ca8db630434915de4eaeac6c4ecd60714d7f5d9..d6c8ae638b3993ce55be91087de09a300405e075 100644
--- a/src/main/java/net/minecraft/server/BlockStateBoolean.java
+++ b/src/main/java/net/minecraft/server/BlockStateBoolean.java
@@ -12,6 +12,13 @@ public class BlockStateBoolean extends IBlockState<Boolean> {
super(s, Boolean.class);
}
+ // Tuinity start - optimise iblockdata state lookup
+ @Override
+ public final int getIdFor(final Boolean value) {
+ return value.booleanValue() ? 1 : 0;
+ }
+ // Tuinity end - optimise iblockdata state lookup
+
@Override
public Collection<Boolean> getValues() {
return this.a;
diff --git a/src/main/java/net/minecraft/server/BlockStateEnum.java b/src/main/java/net/minecraft/server/BlockStateEnum.java
index 8dc620b22bb904aa6a82e2127aa9da861986525c..e6663281481a48fe1b838339160565fbf4c6a65a 100644
--- a/src/main/java/net/minecraft/server/BlockStateEnum.java
+++ b/src/main/java/net/minecraft/server/BlockStateEnum.java
@@ -17,6 +17,15 @@ public class BlockStateEnum<T extends Enum<T> & INamable> extends IBlockState<T>
private final ImmutableSet<T> a;
private final Map<String, T> b = Maps.newHashMap();
+ // Tuinity start - optimise iblockdata state lookup
+ private int[] idLookupTable;
+
+ @Override
+ public final int getIdFor(final T value) {
+ return this.idLookupTable[value.ordinal()];
+ }
+ // Tuinity end - optimise iblockdata state lookup
+
protected BlockStateEnum(String s, Class<T> oclass, Collection<T> collection) {
super(s, oclass);
this.a = ImmutableSet.copyOf(collection);
@@ -32,6 +41,14 @@ public class BlockStateEnum<T extends Enum<T> & INamable> extends IBlockState<T>
this.b.put(s1, t0);
}
+ // Tuinity start - optimise iblockdata state lookup
+ int id = 0;
+ this.idLookupTable = new int[oclass.getEnumConstants().length];
+ java.util.Arrays.fill(this.idLookupTable, -1);
+ for (final T value : this.getValues()) {
+ this.idLookupTable[value.ordinal()] = id++;
+ }
+ // Tuinity end - optimise iblockdata state lookup
}
diff --git a/src/main/java/net/minecraft/server/BlockStateInteger.java b/src/main/java/net/minecraft/server/BlockStateInteger.java
index 36b84446e96faefad3b783f73df74e0f3bce8255..acae5fe0bff44d2bc3921c8e078b2f261de3a035 100644
--- a/src/main/java/net/minecraft/server/BlockStateInteger.java
+++ b/src/main/java/net/minecraft/server/BlockStateInteger.java
@@ -13,6 +13,16 @@ public class BlockStateInteger extends IBlockState<Integer> {
public final int min;
public final int max;
+ // Tuinity start - optimise iblockdata state lookup
+ @Override
+ public final int getIdFor(final Integer value) {
+ final int val = value.intValue();
+ final int ret = val - this.min;
+
+ return ret | ((this.max - ret) >> 31);
+ }
+ // Tuinity end - optimise iblockdata state lookup
+
protected BlockStateInteger(String s, int i, int j) {
super(s, Integer.class);
this.min = i;
diff --git a/src/main/java/net/minecraft/server/IBlockDataHolder.java b/src/main/java/net/minecraft/server/IBlockDataHolder.java
index b19c694cf01bc868dd7c4ec6432b613d19f2ca40..06d2dd7584253a406aa77867fac5543aa01020fd 100644
--- a/src/main/java/net/minecraft/server/IBlockDataHolder.java
+++ b/src/main/java/net/minecraft/server/IBlockDataHolder.java
@@ -39,11 +39,13 @@ public abstract class IBlockDataHolder<O, S> {
private final ImmutableMap<IBlockState<?>, Comparable<?>> b;
private Table<IBlockState<?>, Comparable<?>, S> e;
protected final MapCodec<S> d;
+ protected com.tuinity.tuinity.util.table.ZeroCollidingReferenceStateTable optimisedTable; // Tuinity - optimise state lookup
protected IBlockDataHolder(O o0, ImmutableMap<IBlockState<?>, Comparable<?>> immutablemap, MapCodec<S> mapcodec) {
this.c = o0;
this.b = immutablemap;
this.d = mapcodec;
+ this.optimisedTable = new com.tuinity.tuinity.util.table.ZeroCollidingReferenceStateTable(this, immutablemap); // Tuinity - optimise state lookup
}
public <T extends Comparable<T>> S a(IBlockState<T> iblockstate) {
@@ -85,11 +87,11 @@ public abstract class IBlockDataHolder<O, S> {
public <T extends Comparable<T>> boolean contains(IBlockState<T> iblockstate) { return this.b(iblockstate); } // Paper - OBFHELPER
public <T extends Comparable<T>> boolean b(IBlockState<T> iblockstate) {
- return this.b.containsKey(iblockstate);
+ return this.optimisedTable.get(iblockstate) != null; // Tuinity - optimise state lookup
}
public <T extends Comparable<T>> T get(IBlockState<T> iblockstate) {
- Comparable<?> comparable = (Comparable) this.b.get(iblockstate);
+ final Comparable<?> comparable = this.optimisedTable.get(iblockstate); // Tuinity - optimise state lookup
if (comparable == null) {
throw new IllegalArgumentException("Cannot get property " + iblockstate + " as it does not exist in " + this.c);
@@ -99,27 +101,21 @@ public abstract class IBlockDataHolder<O, S> {
}
public <T extends Comparable<T>> Optional<T> d(IBlockState<T> iblockstate) {
- Comparable<?> comparable = (Comparable) this.b.get(iblockstate);
+ final Comparable<?> comparable = this.optimisedTable.get(iblockstate); // Tuinity - optimise state lookup
return comparable == null ? Optional.empty() : Optional.of(iblockstate.getType().cast(comparable));
}
public <T extends Comparable<T>, V extends T> S set(IBlockState<T> iblockstate, V v0) {
- Comparable<?> comparable = (Comparable) this.b.get(iblockstate);
+ // Tuinity start - optimise state lookup
+ final S ret = (S)this.optimisedTable.get(iblockstate, v0);
- if (comparable == null) {
- throw new IllegalArgumentException("Cannot set property " + iblockstate + " as it does not exist in " + this.c);
- } else if (comparable == v0) {
- return (S) this; // Paper - decompile error
- } else {
- S s0 = this.e.get(iblockstate, v0);
-
- if (s0 == null) {
- throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on " + this.c + ", it is not an allowed value");
- } else {
- return s0;
- }
+ if (ret == null) {
+ throw new IllegalArgumentException("Cannot set property " + iblockstate + " to " + v0 + " on " + this.c + ", it is not an allowed value");
}
+
+ return ret;
+ // Tuinity end - optimise state lookup
}
public void a(Map<Map<IBlockState<?>, Comparable<?>>, S> map) {
@@ -143,7 +139,8 @@ public abstract class IBlockDataHolder<O, S> {
}
}
- this.e = (Table) (table.isEmpty() ? table : ArrayTable.create(table));
+ this.e = (Table) (table.isEmpty() ? table : ArrayTable.create(table)); this.optimisedTable.loadInTable((Table)this.e, this.b); // Tuinity - optimise state lookup
+
}
}
diff --git a/src/main/java/net/minecraft/server/IBlockState.java b/src/main/java/net/minecraft/server/IBlockState.java
index 6550b55067db31dbbc903fe17a13849383651c5a..30344d1e5703690d97ecb889af24fa5e7b35f895 100644
--- a/src/main/java/net/minecraft/server/IBlockState.java
+++ b/src/main/java/net/minecraft/server/IBlockState.java
@@ -15,6 +15,17 @@ public abstract class IBlockState<T extends Comparable<T>> {
private final Codec<T> d;
private final Codec<IBlockState.a<T>> e;
+ // Tuinity start - optimise iblockdata state lookup
+ private static final java.util.concurrent.atomic.AtomicInteger ID_GENERATOR = new java.util.concurrent.atomic.AtomicInteger();
+ private final int id = ID_GENERATOR.getAndIncrement();
+
+ public final int getId() {
+ return this.id;
+ }
+
+ public abstract int getIdFor(final T value);
+ // Tuinity end - optimise state lookup
+
protected IBlockState(String s, Class<T> oclass) {
this.d = Codec.STRING.comapFlatMap((s1) -> this.b(s1).map(DataResult::success).orElseGet(() -> { // Paper - decompile error
return DataResult.error("Unable to read property: " + this + " with value: " + s1);

View File

@ -0,0 +1,29 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Thu, 11 Mar 2021 21:17:02 -0800
Subject: [PATCH] Use hash table for maintaing changed block set
When a lot of block changes occur the iteration for checking can
add up a bit and cause a small performance impact.
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 3127fc9dd87e82243e167862cae83ac87b7f4fa0..c3e466ae9a2f4d9c168b4ace6902550e54cad875 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -3,6 +3,7 @@ package net.minecraft.server;
import com.mojang.datafixers.util.Either;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; // Paper
import it.unimi.dsi.fastutil.shorts.ShortArraySet;
+import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; // Tuinity
import it.unimi.dsi.fastutil.shorts.ShortSet;
import java.util.List;
import java.util.Optional;
@@ -378,7 +379,7 @@ public class PlayerChunk {
if (b0 < 0 || b0 >= this.dirtyBlocks.length) return; // CraftBukkit - SPIGOT-6086, SPIGOT-6296
if (this.dirtyBlocks[b0] == null) {
this.p = true;
- this.dirtyBlocks[b0] = new ShortArraySet();
+ this.dirtyBlocks[b0] = new ShortOpenHashSet(); // Tuinity - use a set to make setting constant-time
}
this.dirtyBlocks[b0].add(SectionPosition.b(blockposition));

File diff suppressed because it is too large Load Diff

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