Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-14 18:40:10 +01:00
[ci skip] Remove removed patches
Dieser Commit ist enthalten in:
Ursprung
11645e3268
Commit
51bef80755
@ -1,61 +0,0 @@
|
||||
From 656824f3d0c0f73417897c1ce3391a91849ec476 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Tue, 1 Mar 2016 14:27:13 -0600
|
||||
Subject: [PATCH] Configurable speed for water flowing over lava
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 4da846719..d3484489b 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -123,4 +123,10 @@ public class PaperWorldConfig {
|
||||
if (fallingBlockHeightNerf != 0) log("Falling Block Height Limit set to Y: " + fallingBlockHeightNerf);
|
||||
if (entityTNTHeightNerf != 0) log("TNT Entity Height Limit set to Y: " + entityTNTHeightNerf);
|
||||
}
|
||||
+
|
||||
+ public int waterOverLavaFlowSpeed;
|
||||
+ private void waterOverLawFlowSpeed() {
|
||||
+ waterOverLavaFlowSpeed = getInt("water-over-lava-flow-speed", 5);
|
||||
+ log("Water over lava flow speed: " + waterOverLavaFlowSpeed);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
index 7b74df5b9..62234a7c9 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
@@ -30,7 +30,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
b0 = 2;
|
||||
}
|
||||
|
||||
- int j = this.a(world);
|
||||
+ int j = this.getFlowSpeed(world, blockposition); // Paper
|
||||
int k;
|
||||
|
||||
if (i > 0) {
|
||||
@@ -261,8 +261,22 @@ public class BlockFlowing extends BlockFluids {
|
||||
|
||||
public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
if (!this.e(world, blockposition, iblockdata)) {
|
||||
- world.a(blockposition, (Block) this, this.a(world));
|
||||
+ world.a(blockposition, (Block) this, this.getFlowSpeed(world, blockposition)); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Paper - Get flow speed. Throttle if its water and flowing adjacent to lava
|
||||
+ */
|
||||
+ public int getFlowSpeed(World world, BlockPosition blockposition) {
|
||||
+ if (this.material == Material.WATER && (
|
||||
+ world.getType(blockposition.north(1)).getBlock().material == Material.LAVA ||
|
||||
+ world.getType(blockposition.south(1)).getBlock().material == Material.LAVA ||
|
||||
+ world.getType(blockposition.west(1)).getBlock().material == Material.LAVA ||
|
||||
+ world.getType(blockposition.east(1)).getBlock().material == Material.LAVA)) {
|
||||
+ return world.paperConfig.waterOverLavaFlowSpeed;
|
||||
+ }
|
||||
+ return super.a(world);
|
||||
+ }
|
||||
}
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,312 +0,0 @@
|
||||
From e894331adaa569423be8472929da3a809c4106bb Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 2 Mar 2016 02:17:54 -0600
|
||||
Subject: [PATCH] Generator Settings
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index db09711e4..7e5cd8042 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -147,4 +147,34 @@ public class PaperWorldConfig {
|
||||
disableEndCredits = getBoolean("game-mechanics.disable-end-credits", false);
|
||||
log("End credits disabled: " + disableEndCredits);
|
||||
}
|
||||
+
|
||||
+ public boolean generateCanyon;
|
||||
+ public boolean generateCaves;
|
||||
+ public boolean generateDungeon;
|
||||
+ public boolean generateFortress;
|
||||
+ public boolean generateMineshaft;
|
||||
+ public boolean generateMonument;
|
||||
+ public boolean generateStronghold;
|
||||
+ public boolean generateTemple;
|
||||
+ public boolean generateVillage;
|
||||
+ public boolean generateFlatBedrock;
|
||||
+ public boolean disableExtremeHillsEmeralds;
|
||||
+ public boolean disableExtremeHillsMonsterEggs;
|
||||
+ public boolean disableMesaAdditionalGold;
|
||||
+
|
||||
+ private void generatorSettings() {
|
||||
+ generateCanyon = getBoolean("generator-settings.canyon", true);
|
||||
+ generateCaves = getBoolean("generator-settings.caves", true);
|
||||
+ generateDungeon = getBoolean("generator-settings.dungeon", true);
|
||||
+ generateFortress = getBoolean("generator-settings.fortress", true);
|
||||
+ generateMineshaft = getBoolean("generator-settings.mineshaft", true);
|
||||
+ generateMonument = getBoolean("generator-settings.monument", true);
|
||||
+ generateStronghold = getBoolean("generator-settings.stronghold", true);
|
||||
+ generateTemple = getBoolean("generator-settings.temple", true);
|
||||
+ generateVillage = getBoolean("generator-settings.village", true);
|
||||
+ generateFlatBedrock = getBoolean("generator-settings.flat-bedrock", false);
|
||||
+ disableExtremeHillsEmeralds = getBoolean("generator-settings.disable-extreme-hills-emeralds", false);
|
||||
+ disableExtremeHillsMonsterEggs = getBoolean("generator-settings.disable-extreme-hills-monster-eggs", false);
|
||||
+ disableMesaAdditionalGold = getBoolean("generator-settings.disable-mesa-additional-gold", false);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/BiomeBase.java b/src/main/java/net/minecraft/server/BiomeBase.java
|
||||
index 1b7599769..ab6db7468 100644
|
||||
--- a/src/main/java/net/minecraft/server/BiomeBase.java
|
||||
+++ b/src/main/java/net/minecraft/server/BiomeBase.java
|
||||
@@ -176,7 +176,7 @@ public abstract class BiomeBase {
|
||||
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
|
||||
|
||||
for (int l1 = 255; l1 >= 0; --l1) {
|
||||
- if (l1 <= random.nextInt(5)) {
|
||||
+ if (l1 <= (world.paperConfig.generateFlatBedrock ? 0 : random.nextInt(5))) { // Paper - Configurable flat bedrock
|
||||
chunksnapshot.a(k1, l1, j1, BiomeBase.c);
|
||||
} else {
|
||||
IBlockData iblockdata2 = chunksnapshot.a(k1, l1, j1);
|
||||
diff --git a/src/main/java/net/minecraft/server/BiomeBigHills.java b/src/main/java/net/minecraft/server/BiomeBigHills.java
|
||||
index 9c39bf7af..61680ab50 100644
|
||||
--- a/src/main/java/net/minecraft/server/BiomeBigHills.java
|
||||
+++ b/src/main/java/net/minecraft/server/BiomeBigHills.java
|
||||
@@ -32,6 +32,9 @@ public class BiomeBigHills extends BiomeBase {
|
||||
int k;
|
||||
int l;
|
||||
|
||||
+ // Paper start - Disable extreme hills emeralds
|
||||
+ if (!world.paperConfig.disableExtremeHillsEmeralds) {
|
||||
+
|
||||
for (j = 0; j < i; ++j) {
|
||||
k = random.nextInt(16);
|
||||
l = random.nextInt(28) + 4;
|
||||
@@ -43,6 +46,12 @@ public class BiomeBigHills extends BiomeBase {
|
||||
}
|
||||
}
|
||||
|
||||
+ }
|
||||
+ // Paper end block
|
||||
+
|
||||
+ // Paper start - Disable extreme hills monster eggs
|
||||
+ if (!world.paperConfig.disableExtremeHillsMonsterEggs) {
|
||||
+
|
||||
for (i = 0; i < 7; ++i) {
|
||||
j = random.nextInt(16);
|
||||
k = random.nextInt(64);
|
||||
@@ -50,6 +59,9 @@ public class BiomeBigHills extends BiomeBase {
|
||||
this.x.generate(world, random, blockposition.a(j, k, l));
|
||||
}
|
||||
|
||||
+ }
|
||||
+ // Paper end block
|
||||
+
|
||||
}
|
||||
|
||||
public void a(World world, Random random, ChunkSnapshot chunksnapshot, int i, int j, double d0) {
|
||||
diff --git a/src/main/java/net/minecraft/server/BiomeMesa.java b/src/main/java/net/minecraft/server/BiomeMesa.java
|
||||
index f2dd96a32..67f8ad8ed 100644
|
||||
--- a/src/main/java/net/minecraft/server/BiomeMesa.java
|
||||
+++ b/src/main/java/net/minecraft/server/BiomeMesa.java
|
||||
@@ -99,7 +99,7 @@ public class BiomeMesa extends BiomeBase {
|
||||
chunksnapshot.a(l, i2, k, BiomeMesa.a);
|
||||
}
|
||||
|
||||
- if (i2 <= random.nextInt(5)) {
|
||||
+ if (i2 <= (world.paperConfig.generateFlatBedrock ? 0 : random.nextInt(5))) { // Paper - Configurable flat bedrock
|
||||
chunksnapshot.a(l, i2, k, BiomeMesa.c);
|
||||
} else if (l1 < 15 || this.I) {
|
||||
IBlockData iblockdata2 = chunksnapshot.a(l, i2, k);
|
||||
@@ -259,6 +259,7 @@ public class BiomeMesa extends BiomeBase {
|
||||
|
||||
protected void a(World world, Random random) {
|
||||
super.a(world, random);
|
||||
+ if (world.paperConfig.disableMesaAdditionalGold) return; // Paper
|
||||
this.a(world, random, 20, this.n, 32, 80);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderFlat.java b/src/main/java/net/minecraft/server/ChunkProviderFlat.java
|
||||
index 1452ff657..8b1b79380 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderFlat.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderFlat.java
|
||||
@@ -26,7 +26,7 @@ public class ChunkProviderFlat implements ChunkGenerator {
|
||||
if (flag) {
|
||||
Map map = this.d.b();
|
||||
|
||||
- if (map.containsKey("village")) {
|
||||
+ if (map.containsKey("village") && world.paperConfig.generateVillage) { // Paper
|
||||
Map map1 = (Map) map.get("village");
|
||||
|
||||
if (!map1.containsKey("size")) {
|
||||
@@ -36,19 +36,19 @@ public class ChunkProviderFlat implements ChunkGenerator {
|
||||
this.e.put("Village", new WorldGenVillage(map1));
|
||||
}
|
||||
|
||||
- if (map.containsKey("biome_1")) {
|
||||
+ if (map.containsKey("biome_1") && world.paperConfig.generateTemple) { // Paper
|
||||
this.e.put("Temple", new WorldGenLargeFeature((Map) map.get("biome_1")));
|
||||
}
|
||||
|
||||
- if (map.containsKey("mineshaft")) {
|
||||
+ if (map.containsKey("mineshaft") && world.paperConfig.generateMineshaft) { // Paper
|
||||
this.e.put("Mineshaft", new WorldGenMineshaft((Map) map.get("mineshaft")));
|
||||
}
|
||||
|
||||
- if (map.containsKey("stronghold")) {
|
||||
+ if (map.containsKey("stronghold") && world.paperConfig.generateStronghold) { // Paper
|
||||
this.e.put("Stronghold", new WorldGenStronghold((Map) map.get("stronghold")));
|
||||
}
|
||||
|
||||
- if (map.containsKey("oceanmonument")) {
|
||||
+ if (map.containsKey("oceanmonument") && world.paperConfig.generateMonument) { // Paper
|
||||
this.e.put("Monument", new WorldGenMonument((Map) map.get("oceanmonument")));
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ public class ChunkProviderFlat implements ChunkGenerator {
|
||||
this.i = new WorldGenLakes(Blocks.LAVA);
|
||||
}
|
||||
|
||||
- this.g = this.d.b().containsKey("dungeon");
|
||||
+ this.g = world.paperConfig.generateDungeon && this.d.b().containsKey("dungeon"); // Paper
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
boolean flag1 = true;
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderGenerate.java b/src/main/java/net/minecraft/server/ChunkProviderGenerate.java
|
||||
index 22a24a39f..ee9e00e64 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderGenerate.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderGenerate.java
|
||||
@@ -160,32 +160,32 @@ public class ChunkProviderGenerate implements ChunkGenerator {
|
||||
this.a(i, j, chunksnapshot);
|
||||
this.D = this.n.getWorldChunkManager().getBiomeBlock(this.D, i * 16, j * 16, 16, 16);
|
||||
this.a(i, j, chunksnapshot, this.D);
|
||||
- if (this.s.r) {
|
||||
+ if (this.s.r && this.n.paperConfig.generateCaves) { // Paper
|
||||
this.v.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
- if (this.s.A) {
|
||||
+ if (this.s.A && this.n.paperConfig.generateCanyon) { // Paper
|
||||
this.A.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
if (this.o) {
|
||||
- if (this.s.w) {
|
||||
+ if (this.s.w && this.n.paperConfig.generateMineshaft) { // Paper
|
||||
this.y.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
- if (this.s.v) {
|
||||
+ if (this.s.v&& this.n.paperConfig.generateVillage) { // Paper
|
||||
this.x.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
- if (this.s.u) {
|
||||
+ if (this.s.u && this.n.paperConfig.generateStronghold) { // Paper
|
||||
this.w.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
- if (this.s.x) {
|
||||
+ if (this.s.x && this.n.paperConfig.generateTemple) { // Paper
|
||||
this.z.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
- if (this.s.y) {
|
||||
+ if (this.s.y && this.n.paperConfig.generateMonument) { // Paper
|
||||
this.B.a(this.n, i, j, chunksnapshot);
|
||||
}
|
||||
|
||||
@@ -329,23 +329,23 @@ public class ChunkProviderGenerate implements ChunkGenerator {
|
||||
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j);
|
||||
|
||||
if (this.o) {
|
||||
- if (this.s.w) {
|
||||
+ if (this.s.w && this.n.paperConfig.generateMineshaft) { // Paper
|
||||
this.y.a(this.n, this.i, chunkcoordintpair);
|
||||
}
|
||||
|
||||
- if (this.s.v) {
|
||||
+ if (this.s.v && this.n.paperConfig.generateVillage) { // Paper
|
||||
flag = this.x.a(this.n, this.i, chunkcoordintpair);
|
||||
}
|
||||
|
||||
- if (this.s.u) {
|
||||
+ if (this.s.u && this.n.paperConfig.generateStronghold) { // Paper
|
||||
this.w.a(this.n, this.i, chunkcoordintpair);
|
||||
}
|
||||
|
||||
- if (this.s.x) {
|
||||
+ if (this.s.x && this.n.paperConfig.generateTemple) { // Paper
|
||||
this.z.a(this.n, this.i, chunkcoordintpair);
|
||||
}
|
||||
|
||||
- if (this.s.y) {
|
||||
+ if (this.s.y && this.n.paperConfig.generateMonument) { // Paper
|
||||
this.B.a(this.n, this.i, chunkcoordintpair);
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ public class ChunkProviderGenerate implements ChunkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.s.s) {
|
||||
+ if (this.s.s && this.n.paperConfig.generateDungeon) { // Paper
|
||||
for (k1 = 0; k1 < this.s.t; ++k1) {
|
||||
l1 = this.i.nextInt(16) + 8;
|
||||
i2 = this.i.nextInt(256);
|
||||
@@ -443,23 +443,23 @@ public class ChunkProviderGenerate implements ChunkGenerator {
|
||||
|
||||
public void recreateStructures(Chunk chunk, int i, int j) {
|
||||
if (this.o) {
|
||||
- if (this.s.w) {
|
||||
+ if (this.s.w && this.n.paperConfig.generateMineshaft) { // Paper
|
||||
this.y.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
|
||||
- if (this.s.v) {
|
||||
+ if (this.s.v && this.n.paperConfig.generateVillage) { // Paper
|
||||
this.x.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
|
||||
- if (this.s.u) {
|
||||
+ if (this.s.u && this.n.paperConfig.generateStronghold) { // Paper
|
||||
this.w.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
|
||||
- if (this.s.x) {
|
||||
+ if (this.s.x && this.n.paperConfig.generateTemple) { // Paper
|
||||
this.z.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
|
||||
- if (this.s.y) {
|
||||
+ if (this.s.y && this.n.paperConfig.generateMonument) { // Paper
|
||||
this.B.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderHell.java b/src/main/java/net/minecraft/server/ChunkProviderHell.java
|
||||
index 9f738749f..12bc10ff0 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderHell.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderHell.java
|
||||
@@ -151,7 +151,10 @@ public class ChunkProviderHell implements ChunkGenerator {
|
||||
IBlockData iblockdata1 = ChunkProviderHell.b;
|
||||
|
||||
for (int l1 = 127; l1 >= 0; --l1) {
|
||||
- if (l1 < 127 - this.p.nextInt(5) && l1 > this.p.nextInt(5)) {
|
||||
+ // Paper start - Configurable flat bedrock worldgen
|
||||
+ if (l1 < 127 - (n.paperConfig.generateFlatBedrock ? 0 : this.p.nextInt(5)) &&
|
||||
+ l1 > (n.paperConfig.generateFlatBedrock ? 0 : this.p.nextInt(5))) {
|
||||
+ // Paper end
|
||||
IBlockData iblockdata2 = chunksnapshot.a(i1, l1, l);
|
||||
|
||||
if (iblockdata2.getBlock() != null && iblockdata2.getMaterial() != Material.AIR) {
|
||||
@@ -384,6 +387,6 @@ public class ChunkProviderHell implements ChunkGenerator {
|
||||
}
|
||||
|
||||
public void recreateStructures(Chunk chunk, int i, int j) {
|
||||
- this.I.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
+ if (this.n.paperConfig.generateFortress) this.I.a(this.n, i, j, (ChunkSnapshot) null);
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
index 66a80a776..34fd7edfe 100644
|
||||
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
@@ -128,6 +128,7 @@ public abstract class StructureGenerator extends WorldGenBase {
|
||||
}
|
||||
|
||||
public boolean a(World world, BlockPosition blockposition) {
|
||||
+ if (this.g == null) return false; // Paper
|
||||
this.a(world);
|
||||
ObjectIterator objectiterator = this.c.values().iterator();
|
||||
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,21 +0,0 @@
|
||||
From b347181112d7dd6655c11bbd324a2a4c62e9507d Mon Sep 17 00:00:00 2001
|
||||
From: Iceee <andrew@opticgaming.tv>
|
||||
Date: Wed, 2 Mar 2016 12:03:23 -0600
|
||||
Subject: [PATCH] Stop updating flowing block if material has changed
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
index 62234a7c9..3b47253a4 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
@@ -90,6 +90,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
this.f(world, blockposition, iblockdata);
|
||||
}
|
||||
|
||||
+ if (world.getType(blockposition).getBlock().getBlockData().getMaterial() != material) return; // Paper - Stop updating flowing block if material has changed
|
||||
org.bukkit.block.Block source = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ()); // CraftBukkit
|
||||
IBlockData iblockdata2 = world.getType(blockposition.down());
|
||||
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,113 +0,0 @@
|
||||
From 4b300fd41621071f122933ad9400521cb46228a0 Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 2 Mar 2016 12:20:52 -0600
|
||||
Subject: [PATCH] Fast draining
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 15675efbf..dbd82d5a9 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -183,4 +183,11 @@ public class PaperWorldConfig {
|
||||
optimizeExplosions = getBoolean("optimize-explosions", false);
|
||||
log("Optimize explosions: " + optimizeExplosions);
|
||||
}
|
||||
+
|
||||
+ public boolean fastDrainLava;
|
||||
+ public boolean fastDrainWater;
|
||||
+ private void fastDrain() {
|
||||
+ fastDrainLava = getBoolean("fast-drain.lava", false);
|
||||
+ fastDrainWater = getBoolean("fast-drain.water", false);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
index 3b47253a4..3aaa19b2f 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
@@ -69,7 +69,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
}
|
||||
}
|
||||
|
||||
- if (this.material == Material.LAVA && i < 8 && i1 < 8 && i1 > i && random.nextInt(4) != 0) {
|
||||
+ if (!world.paperConfig.fastDrainLava && this.material == Material.LAVA && i < 8 && i1 < 8 && i1 > i && random.nextInt(4) != 0) { // Paper
|
||||
j *= 4;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
this.f(world, blockposition, iblockdata);
|
||||
} else {
|
||||
i = i1;
|
||||
- if (i1 < 0) {
|
||||
+ if (i1 < 0 || canFastDrain(world, blockposition)) { // Paper - Fast draining
|
||||
world.setAir(blockposition);
|
||||
} else {
|
||||
iblockdata = iblockdata.set(BlockFlowing.LEVEL, Integer.valueOf(i1));
|
||||
@@ -267,6 +267,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
/**
|
||||
* Paper - Get flow speed. Throttle if its water and flowing adjacent to lava
|
||||
*/
|
||||
@@ -280,4 +281,57 @@ public class BlockFlowing extends BlockFluids {
|
||||
}
|
||||
return super.a(world);
|
||||
}
|
||||
+
|
||||
+ private int getFluidLevel(IBlockAccess iblockaccess, BlockPosition blockposition) {
|
||||
+ return iblockaccess.getType(blockposition).getMaterial() == this.material ? iblockaccess.getType(blockposition).get(BlockFluids.LEVEL) : -1;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Paper - Data check method for fast draining
|
||||
+ */
|
||||
+ public int getData(World world, BlockPosition position) {
|
||||
+ int data = this.getFluidLevel((IBlockAccess) world, position);
|
||||
+ return data < 8 ? data : 0;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Paper - Checks surrounding blocks to determine if block can be fast drained
|
||||
+ */
|
||||
+ public boolean canFastDrain(World world, BlockPosition position) {
|
||||
+ boolean result = false;
|
||||
+ int data = getData(world, position);
|
||||
+ if (this.material == Material.WATER) {
|
||||
+ if (world.paperConfig.fastDrainWater) {
|
||||
+ result = true;
|
||||
+ if (getData(world, position.down()) < 0) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.north()).getBlock().getBlockData().getMaterial() == Material.WATER && getData(world, position.north()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.south()).getBlock().getBlockData().getMaterial() == Material.WATER && getData(world, position.south()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.west()).getBlock().getBlockData().getMaterial() == Material.WATER && getData(world, position.west()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.east()).getBlock().getBlockData().getMaterial() == Material.WATER && getData(world, position.east()) < data) {
|
||||
+ result = false;
|
||||
+ }
|
||||
+ }
|
||||
+ } else if (this.material == Material.LAVA) {
|
||||
+ if (world.paperConfig.fastDrainLava) {
|
||||
+ result = true;
|
||||
+ if (getData(world, position.down()) < 0 || world.getType(position.up()).getBlock().getBlockData().getMaterial() != Material.AIR) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.north()).getBlock().getBlockData().getMaterial() == Material.LAVA && getData(world, position.north()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.south()).getBlock().getBlockData().getMaterial() == Material.LAVA && getData(world, position.south()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.west()).getBlock().getBlockData().getMaterial() == Material.LAVA && getData(world, position.west()) < data) {
|
||||
+ result = false;
|
||||
+ } else if (world.getType(position.east()).getBlock().getBlockData().getMaterial() == Material.LAVA && getData(world, position.east()) < data) {
|
||||
+ result = false;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return result;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,87 +0,0 @@
|
||||
From fe8bd60fe7b27283c696a5b746414187695174b0 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Wed, 2 Mar 2016 23:13:07 -0600
|
||||
Subject: [PATCH] Send absolute position the first time an entity is seen
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
index dd6c84b4a2..de0cf6b735 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
@@ -41,7 +41,19 @@ public class EntityTrackerEntry {
|
||||
private boolean x;
|
||||
private boolean y;
|
||||
public boolean b;
|
||||
- public final Set<EntityPlayer> trackedPlayers = Sets.newHashSet();
|
||||
+ // 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<EntityPlayer, Boolean>();
|
||||
+ public Set<EntityPlayer> trackedPlayers = trackedPlayerMap.keySet();
|
||||
+
|
||||
+ /**
|
||||
+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets
|
||||
+ */
|
||||
+ public void sendPlayerPacket(EntityPlayer player, Packet packet) {
|
||||
+ player.playerConnection.sendPacket(packet);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public EntityTrackerEntry(Entity entity, int i, int j, int k, boolean flag) {
|
||||
this.tracker = entity;
|
||||
@@ -142,6 +154,7 @@ public class EntityTrackerEntry {
|
||||
boolean flag1 = l1 * l1 + i2 * i2 + j2 * j2 >= 128L || this.a % 60 == 0;
|
||||
boolean flag2 = Math.abs(j1 - this.yRot) >= 1 || Math.abs(k1 - this.xRot) >= 1;
|
||||
|
||||
+ if (this.a > 0 || this.tracker instanceof EntityArrow) { // Paper - Moved up
|
||||
// CraftBukkit start - Code moved from below
|
||||
if (flag1) {
|
||||
this.xLoc = k;
|
||||
@@ -155,7 +168,6 @@ public class EntityTrackerEntry {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
- if (this.a > 0 || this.tracker instanceof EntityArrow) {
|
||||
if (l1 >= -32768L && l1 < 32768L && i2 >= -32768L && i2 < 32768L && j2 >= -32768L && j2 < 32768L && this.v <= 400 && !this.x && this.y == this.tracker.onGround) {
|
||||
if ((!flag1 || !flag2) && !(this.tracker instanceof EntityArrow)) {
|
||||
if (flag1) {
|
||||
@@ -201,7 +213,26 @@ public class EntityTrackerEntry {
|
||||
}
|
||||
|
||||
if (packet1 != null) {
|
||||
- this.broadcast((Packet) packet1);
|
||||
+ // Paper start - ensure fresh viewers get an absolute position on their first update,
|
||||
+ // since we can't be certain what position they received in the spawn packet.
|
||||
+ if (packet1 instanceof PacketPlayOutEntityTeleport) {
|
||||
+ this.broadcast((Packet) packet1);
|
||||
+ } else {
|
||||
+ PacketPlayOutEntityTeleport teleportPacket = null;
|
||||
+
|
||||
+ for (java.util.Map.Entry<EntityPlayer, Boolean> viewer : trackedPlayerMap.entrySet()) {
|
||||
+ if (viewer.getValue()) {
|
||||
+ viewer.setValue(false);
|
||||
+ if (teleportPacket == null) {
|
||||
+ teleportPacket = new PacketPlayOutEntityTeleport(this.tracker);
|
||||
+ }
|
||||
+ sendPlayerPacket(viewer.getKey(), teleportPacket);
|
||||
+ } else {
|
||||
+ sendPlayerPacket(viewer.getKey(), (Packet) packet1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
this.d();
|
||||
@@ -338,7 +369,7 @@ public class EntityTrackerEntry {
|
||||
|
||||
entityplayer.removeQueue.remove(Integer.valueOf(this.tracker.getId()));
|
||||
// CraftBukkit end
|
||||
- this.trackedPlayers.add(entityplayer);
|
||||
+ this.trackedPlayerMap.put(entityplayer, true); // Paper
|
||||
Packet<?> packet = this.e();
|
||||
|
||||
entityplayer.playerConnection.sendPacket(packet);
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 8a9b221bcd755747f0e03bb84f9ba7403eaac7fd Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 28 Mar 2016 22:03:09 -0400
|
||||
Subject: [PATCH] Prevent Waterflow BlockFromToEvent from loading chunks
|
||||
|
||||
Many protection plugins would unintentionally trigger chunk loads
|
||||
by calling .getToBlock() on an unloaded chunk, killing performance.
|
||||
|
||||
Simply skip the event call. as CraftBukkit blocks changing the block
|
||||
of unloaded chunks anyways.
|
||||
|
||||
This keeps behavior consistent, vs inconsistent flowing based on plugin triggered loads.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
index 739b9aac3..ff90e08eb 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockFlowing.java
|
||||
@@ -96,6 +96,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
|
||||
if (this.h(world, blockposition.down(), iblockdata2)) {
|
||||
// CraftBukkit start
|
||||
+ if (!canFlowTo(world, source, BlockFace.DOWN)) { return; } // Paper
|
||||
BlockFromToEvent event = new BlockFromToEvent(source, BlockFace.DOWN);
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
@@ -136,6 +137,7 @@ public class BlockFlowing extends BlockFluids {
|
||||
EnumDirection enumdirection1 = (EnumDirection) iterator1.next();
|
||||
|
||||
// CraftBukkit start
|
||||
+ if (!canFlowTo(world, source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1))) { continue; } // Paper
|
||||
BlockFromToEvent event = new BlockFromToEvent(source, org.bukkit.craftbukkit.block.CraftBlock.notchToBlockFace(enumdirection1));
|
||||
world.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
@@ -148,8 +150,14 @@ public class BlockFlowing extends BlockFluids {
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private boolean canFlowTo(World world, org.bukkit.block.Block source, BlockFace face) {
|
||||
+ return source.getWorld().isChunkLoaded((source.getX() + face.getModX()) >> 4, (source.getZ() + face.getModZ()) >> 4);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
private void flow(World world, BlockPosition blockposition, IBlockData iblockdata, int i) {
|
||||
- if (world.isLoaded(blockposition) && this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check
|
||||
+ if (/*world.isLoaded(blockposition) &&*/ this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check // Paper - Already checked before we get here for isLoaded
|
||||
if (iblockdata.getMaterial() != Material.AIR) {
|
||||
if (this.material == Material.LAVA) {
|
||||
this.fizz(world, blockposition);
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 3f31cdecde77021afea54370f1fb31ef0621b59f Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Thu, 14 Apr 2016 17:48:56 -0500
|
||||
Subject: [PATCH] Water mobs should only spawn in the water
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityWaterAnimal.java b/src/main/java/net/minecraft/server/EntityWaterAnimal.java
|
||||
index f430bdeec..0597edad6 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityWaterAnimal.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityWaterAnimal.java
|
||||
@@ -11,7 +11,15 @@ public abstract class EntityWaterAnimal extends EntityInsentient implements IAni
|
||||
}
|
||||
|
||||
public boolean P() {
|
||||
- return true;
|
||||
+ // Paper start - Don't let water mobs spawn in non-water blocks
|
||||
+ // Based around EntityAnimal's implementation
|
||||
+ int i = MathHelper.floor(this.locX);
|
||||
+ int j = MathHelper.floor(this.getBoundingBox().b); // minY of bounding box
|
||||
+ int k = MathHelper.floor(this.locZ);
|
||||
+ Block block = this.world.getType(new BlockPosition(i, j, k)).getBlock();
|
||||
+
|
||||
+ return block == Blocks.WATER || block == Blocks.FLOWING_WATER;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public boolean canSpawn() {
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,55 +0,0 @@
|
||||
From 7e347eb480cfb1eecd76b0c6fbc08090e439f8d5 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sun, 24 Apr 2016 19:49:33 -0500
|
||||
Subject: [PATCH] SPIGOT-1401: Fix dispenser, dropper, furnace placement
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockDispenser.java b/src/main/java/net/minecraft/server/BlockDispenser.java
|
||||
index 8e794976a..539b2b3ce 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockDispenser.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockDispenser.java
|
||||
@@ -20,6 +20,9 @@ public class BlockDispenser extends BlockTileEntity {
|
||||
return 4;
|
||||
}
|
||||
|
||||
+ // Paper start - Removed override of onPlace that was reversing placement direction when
|
||||
+ // adjacent to another block, which was not consistent with single player block placement
|
||||
+ /*
|
||||
public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
super.onPlace(world, blockposition, iblockdata);
|
||||
this.e(world, blockposition, iblockdata);
|
||||
@@ -49,6 +52,8 @@ public class BlockDispenser extends BlockTileEntity {
|
||||
world.setTypeAndData(blockposition, iblockdata.set(BlockDispenser.FACING, enumdirection).set(BlockDispenser.TRIGGERED, Boolean.valueOf(false)), 2);
|
||||
}
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
|
||||
public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) {
|
||||
if (world.isClientSide) {
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockFurnace.java b/src/main/java/net/minecraft/server/BlockFurnace.java
|
||||
index b6834d2d1..dae711708 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockFurnace.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockFurnace.java
|
||||
@@ -18,6 +18,9 @@ public class BlockFurnace extends BlockTileEntity {
|
||||
return Item.getItemOf(Blocks.FURNACE);
|
||||
}
|
||||
|
||||
+ // Paper start - Removed override of onPlace that was reversing placement direction when
|
||||
+ // adjacent to another block, which was not consistent with single player block placement
|
||||
+ /*
|
||||
public void onPlace(World world, BlockPosition blockposition, IBlockData iblockdata) {
|
||||
this.e(world, blockposition, iblockdata);
|
||||
}
|
||||
@@ -43,6 +46,8 @@ public class BlockFurnace extends BlockTileEntity {
|
||||
world.setTypeAndData(blockposition, iblockdata.set(BlockFurnace.FACING, enumdirection), 2);
|
||||
}
|
||||
}
|
||||
+ */
|
||||
+ // Paper end
|
||||
|
||||
public boolean interact(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) {
|
||||
if (world.isClientSide) {
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,83 +0,0 @@
|
||||
From cbe35161f2e8a59c22aca9a0d5412674d128df41 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 21 Mar 2018 19:57:10 -0400
|
||||
Subject: [PATCH] Configurable Unrestricted Signs
|
||||
|
||||
Bukkit restricts command execution of signs to test if the sender
|
||||
has permission to run the specified command. This breaks vanilla
|
||||
maps that use signs to intentionally run as elevated permission.
|
||||
|
||||
Bukkit provides an unrestricted advancements setting, so this setting
|
||||
compliments that one and allows for unrestricted signs.
|
||||
|
||||
We still filter sign update packets to strip out commands at edit phase,
|
||||
however there is no sanity in ever expecting creative mode to not be
|
||||
able to create signs with any command.
|
||||
|
||||
Creative servers should absolutely never enable this.
|
||||
Non creative servers, enable at own risk!!!
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/TileEntitySign.java b/src/main/java/net/minecraft/server/TileEntitySign.java
|
||||
index 3f2c5b2d5..67bd3bcbe 100644
|
||||
--- a/src/main/java/net/minecraft/server/TileEntitySign.java
|
||||
+++ b/src/main/java/net/minecraft/server/TileEntitySign.java
|
||||
@@ -38,7 +38,7 @@ public class TileEntitySign extends TileEntity {
|
||||
public void load(NBTTagCompound nbttagcompound) {
|
||||
this.isEditable = false;
|
||||
super.load(nbttagcompound);
|
||||
- ICommandListener icommandlistener = new ICommandListener() {
|
||||
+ ICommandListener icommandlistener = new ISignCommandListener() { // Paper
|
||||
public String getName() {
|
||||
return "Sign";
|
||||
}
|
||||
@@ -125,7 +125,7 @@ public class TileEntitySign extends TileEntity {
|
||||
}
|
||||
|
||||
public boolean b(final EntityHuman entityhuman) {
|
||||
- ICommandListener icommandlistener = new ICommandListener() {
|
||||
+ ICommandListener icommandlistener = new ISignCommandListener() { // Paper
|
||||
public String getName() {
|
||||
return entityhuman.getName();
|
||||
}
|
||||
@@ -200,4 +200,5 @@ public class TileEntitySign extends TileEntity {
|
||||
public CommandObjectiveExecutor f() {
|
||||
return this.i;
|
||||
}
|
||||
+ public interface ISignCommandListener extends ICommandListener {} // Paper
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index e86c16755..6095948e8 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -175,6 +175,7 @@ public final class CraftServer implements Server {
|
||||
private CraftIconCache icon;
|
||||
private boolean overrideAllCommandBlockCommands = false;
|
||||
private boolean unrestrictedAdvancements;
|
||||
+ private boolean unrestrictedSignCommands; // Paper
|
||||
private final List<CraftPlayer> playerView;
|
||||
public int reloadCount;
|
||||
public static Exception excessiveVelEx; // Paper - Velocity warnings
|
||||
@@ -253,6 +254,12 @@ public final class CraftServer implements Server {
|
||||
saveCommandsConfig();
|
||||
overrideAllCommandBlockCommands = commandsConfiguration.getStringList("command-block-overrides").contains("*");
|
||||
unrestrictedAdvancements = commandsConfiguration.getBoolean("unrestricted-advancements");
|
||||
+ // Paper start
|
||||
+ unrestrictedSignCommands = commandsConfiguration.getBoolean("unrestricted-signs");
|
||||
+ if (unrestrictedSignCommands) {
|
||||
+ logger.warning("Warning: Commands are no longer restricted on signs. If you allow players to use Creative Mode, there may be risk of players bypassing permissions. Use this setting at your own risk!!!!");
|
||||
+ }
|
||||
+ // Paper end
|
||||
pluginManager.useTimings(configuration.getBoolean("settings.plugin-profiling"));
|
||||
monsterSpawn = configuration.getInt("spawn-limits.monsters");
|
||||
animalSpawn = configuration.getInt("spawn-limits.animals");
|
||||
@@ -270,6 +277,7 @@ public final class CraftServer implements Server {
|
||||
listener = ((CommandListenerWrapper) listener).base;
|
||||
}
|
||||
|
||||
+ if (unrestrictedSignCommands && listener instanceof TileEntitySign.ISignCommandListener) return true; // Paper
|
||||
return unrestrictedAdvancements && listener instanceof AdvancementRewards.AdvancementCommandListener;
|
||||
}
|
||||
|
||||
--
|
||||
2.18.0
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <blake.galbreath@gmail.com>
|
||||
Date: Tue, 8 Dec 2020 20:14:20 -0600
|
||||
Subject: [PATCH] Fix curing zombie villager discount exploit
|
||||
|
||||
This fixes the exploit used to gain absurd trading discounts with infecting
|
||||
and curing a villager on repeat by simply resetting the relevant part of
|
||||
the reputation when it is cured.
|
||||
|
||||
This patch has been removed, as MC-181190 was fixed by mojang in 23w31a.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/npc/Villager.java b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
index f58be4e2529759cc64df2c70a69ef56eabbb762d..84cee8fb09f90424438de336f60d9388da1b39de 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/npc/Villager.java
|
||||
@@ -1009,6 +1009,15 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
|
||||
@Override
|
||||
public void onReputationEventFrom(ReputationEventType interaction, Entity entity) {
|
||||
if (interaction == ReputationEventType.ZOMBIE_VILLAGER_CURED) {
|
||||
+ // Paper start - fix MC-181190
|
||||
+ if (this.level().paperConfig().fixes.fixCuringZombieVillagerDiscountExploit) {
|
||||
+ final GossipContainer.EntityGossips playerReputation = this.getGossips().gossips.get(entity.getUUID());
|
||||
+ if (playerReputation != null) {
|
||||
+ playerReputation.remove(GossipType.MAJOR_POSITIVE);
|
||||
+ playerReputation.remove(GossipType.MINOR_POSITIVE);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.gossips.add(entity.getUUID(), GossipType.MAJOR_POSITIVE, 20);
|
||||
this.gossips.add(entity.getUUID(), GossipType.MINOR_POSITIVE, 25);
|
||||
} else if (interaction == ReputationEventType.TRADE) {
|
@ -1,218 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 25 May 2020 11:02:42 -0400
|
||||
Subject: [PATCH] Unload leaked Cached Chunks
|
||||
|
||||
Due to some complexity in mojangs complicated chain of juggling
|
||||
whether or not a chunk should be unloaded when the last ticket is
|
||||
removed, many chunks are remaining around in the cache.
|
||||
|
||||
These chunks are never being targetted for unload because they are
|
||||
vastly out of view distance range and have no reason to be looked at.
|
||||
|
||||
This is a huge issue for performance because we have to iterate these
|
||||
chunks EVERY TICK... This is what's been leading to high SELF time in
|
||||
Ticking Chunks timings/profiler results.
|
||||
|
||||
We will now detect these chunks in that iteration, and automatically
|
||||
add it to the unload queue when the chunk is found without any tickets.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkMapDistance.java b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
index 9805361e2d49fa1cfecf0c5811187fc503d0ad8e..62ed8e653c2060c314b407f698842e9c7c3312c0 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkMapDistance.java
|
||||
@@ -33,7 +33,7 @@ public abstract class ChunkMapDistance {
|
||||
public final Long2ObjectOpenHashMap<ArraySetSorted<Ticket<?>>> tickets = new Long2ObjectOpenHashMap();
|
||||
private final ChunkMapDistance.a e = new ChunkMapDistance.a();
|
||||
public static final int MOB_SPAWN_RANGE = 8; //private final ChunkMapDistance.b f = new ChunkMapDistance.b(8); // Paper - no longer used
|
||||
- private final ChunkMapDistance.c g = new ChunkMapDistance.c(33);
|
||||
+ private final ChunkMapDistance.c g = new ChunkMapDistance.c(33); public final ChunkMapDistance.c getLevelTracker() { return g; } // Paper
|
||||
// Paper start use a queue, but still keep unique requirement
|
||||
public final java.util.Queue<PlayerChunk> pendingChunkUpdates = new java.util.ArrayDeque<PlayerChunk>() {
|
||||
@Override
|
||||
@@ -478,7 +478,7 @@ public abstract class ChunkMapDistance {
|
||||
if (flag1) {
|
||||
ChunkMapDistance.this.j.a(ChunkTaskQueueSorter.a(() -> { // CraftBukkit - decompile error
|
||||
ChunkMapDistance.this.m.execute(() -> {
|
||||
- if (this.c(this.c(i))) {
|
||||
+ if (this.c(this.c(i))) { // Paper - diff above isChunkLoaded
|
||||
ChunkMapDistance.this.addTicket(i, ticket);
|
||||
ChunkMapDistance.this.l.add(i);
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 54e89c9cc6c47ff2c4f4dd5d4c22a391f8a3d6e0..144e91b303cbd9c58c9e6d598e9c9334f2a75c73 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -560,6 +560,7 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
}
|
||||
}
|
||||
// Paper start
|
||||
+ if (playerchunk != null) playerchunk.lastActivity = world.getTime(); // Paper
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> future = this.a(playerchunk, l) ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : playerchunk.a(chunkstatus, this.playerChunkMap);
|
||||
if (isUrgent) {
|
||||
future.thenAccept(either -> this.chunkMapDistance.clearUrgent(chunkcoordintpair));
|
||||
@@ -812,6 +813,7 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
this.world.timings.countNaturalMobs.stopTiming(); // Paper - timings
|
||||
this.world.getMethodProfiler().exit();
|
||||
// Paper - replaced by above
|
||||
+ final long time = world.getTime(); // Paper
|
||||
final int[] chunksTicked = {0}; this.playerChunkMap.forEachVisibleChunk((playerchunk) -> { // Paper - safe iterator incase chunk loads, also no wrapping
|
||||
Optional<Chunk> optional = ((Either) playerchunk.b().getNow(PlayerChunk.UNLOADED_CHUNK)).left();
|
||||
|
||||
@@ -897,7 +899,7 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper
|
||||
if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper
|
||||
}
|
||||
- }
|
||||
+ } else { checkInactiveChunk(playerchunk, time); } // Paper - check inaccessible chunks
|
||||
});
|
||||
this.world.getMethodProfiler().enter("customSpawners");
|
||||
if (flag1) {
|
||||
@@ -913,6 +915,30 @@ public class ChunkProviderServer extends IChunkProvider {
|
||||
this.playerChunkMap.g();
|
||||
}
|
||||
|
||||
+ // Paper start - remove inaccessible chunks leaked
|
||||
+ private void checkInactiveChunk(PlayerChunk playerchunk, long time) {
|
||||
+ int ticketLevel = playerchunk.getTicketLevel();
|
||||
+ if (ticketLevel > 33 && ticketLevel == playerchunk.oldTicketLevel &&
|
||||
+ (playerchunk.lastActivity == 0 || time - playerchunk.lastActivity > 20*120) &&
|
||||
+ playerchunk.location.pair() % 20 == 0 && playerChunkMap.unloadQueue.size() < 100
|
||||
+ ) {
|
||||
+ ChunkStatus chunkHolderStatus = playerchunk.getChunkHolderStatus();
|
||||
+ ChunkStatus desiredStatus = PlayerChunk.getChunkStatus(ticketLevel);
|
||||
+ if (chunkHolderStatus != null && !chunkHolderStatus.isAtLeastStatus(desiredStatus)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (playerchunk.lastActivity == 0) {
|
||||
+ playerchunk.lastActivity = time;
|
||||
+ return;
|
||||
+ }
|
||||
+ playerchunk.lastActivity = time;
|
||||
+ if (playerchunk.shouldBeUnloaded()) {
|
||||
+ playerChunkMap.unloadQueue.add(playerchunk.location.pair());
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Override
|
||||
public String getName() {
|
||||
return "ServerChunkCache: " + this.h();
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index b8fe42e8123e972b1ec97b048c35d90118076e66..18f9a2590f7fa5dfc9070fc5e13121d77f06e79f 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -44,6 +44,22 @@ public class PlayerChunk {
|
||||
|
||||
long lastAutoSaveTime; // Paper - incremental autosave
|
||||
long inactiveTimeStart; // Paper - incremental autosave
|
||||
+ // Paper start - unload leaked chunks
|
||||
+ long lastActivity;
|
||||
+ java.util.concurrent.ConcurrentHashMap<ChunkCoordIntPair, Boolean> dependendedOnBy = new java.util.concurrent.ConcurrentHashMap<>();
|
||||
+ public boolean shouldBeUnloaded() {
|
||||
+ if (!neighborPriorities.isEmpty() || !dependendedOnBy.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ long key = location.pair();
|
||||
+ if (chunkMap.playerViewDistanceNoTickMap.getObjectsInRange(key) != null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ PlayerChunkMap.a distanceManager = chunkMap.chunkDistanceManager;
|
||||
+ ArraySetSorted<Ticket<?>> tickets = distanceManager.tickets.get(key);
|
||||
+ return (tickets == null || tickets.isEmpty()) TODO: Figure out level map;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// Paper start - optimise isOutsideOfRange
|
||||
// cached here to avoid a map lookup
|
||||
@@ -562,6 +578,7 @@ public class PlayerChunk {
|
||||
protected void a(PlayerChunkMap playerchunkmap) {
|
||||
ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel);
|
||||
ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel);
|
||||
+ if (oldTicketLevel != ticketLevel) lastActivity = chunkMap.world.getTime(); // Paper - chunk leak
|
||||
boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET;
|
||||
boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range)
|
||||
PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel);
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index f42507f5a17f9388db738218f58ca76f863274ff..9ee13c741fdcc6b40d175e375e61bffa4c14f45f 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -639,6 +639,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
}
|
||||
}));
|
||||
}
|
||||
+ playerchunk.lastActivity = world.getTime(); // Paper - chunk leak
|
||||
|
||||
ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1);
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = playerchunk.a(chunkstatus, this);
|
||||
@@ -646,6 +647,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
if (requestingNeighbor != null && requestingNeighbor != playerchunk && !completablefuture.isDone()) {
|
||||
requestingNeighbor.onNeighborRequest(playerchunk, chunkstatus);
|
||||
completablefuture.thenAccept(either -> {
|
||||
+ playerchunk.lastActivity = world.getTime(); // Paper - chunk leak
|
||||
requestingNeighbor.onNeighborDone(playerchunk, chunkstatus, either.left().orElse(null));
|
||||
});
|
||||
}
|
||||
@@ -874,6 +876,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
PlayerChunk playerchunk = (PlayerChunk) this.updatingChunks.remove(j);
|
||||
|
||||
if (playerchunk != null) {
|
||||
+ // Paper start - don't unload chunks that should be loaded
|
||||
+ if (!playerchunk.shouldBeUnloaded()) {
|
||||
+ this.updatingChunks.put(j, playerchunk);
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.pendingUnload.put(j, playerchunk);
|
||||
this.updatingChunksModified = true;
|
||||
this.a(j, playerchunk); // Paper - Move up - don't leak chunks
|
||||
@@ -1147,9 +1155,27 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
return completablefuture.thenComposeAsync((either) -> {
|
||||
return either.map((list) -> { // Paper - Shut up.
|
||||
try {
|
||||
+ // Paper start
|
||||
+ list.forEach(chunk -> {
|
||||
+ PlayerChunk updatingChunk = getUpdatingChunk(chunk.getPos().pair());
|
||||
+ if (updatingChunk != null) {
|
||||
+ updatingChunk.dependendedOnBy.put(playerchunk.location, true);
|
||||
+ updatingChunk.lastActivity = world.getTime();
|
||||
+ }
|
||||
+ });
|
||||
+ // Paper end
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture1 = chunkstatus.a(this.world, this.chunkGenerator, this.definedStructureManager, this.lightEngine, (ichunkaccess) -> {
|
||||
return this.c(playerchunk);
|
||||
}, list);
|
||||
+ // Paper start
|
||||
+ completablefuture1.whenComplete((unused, unused2) -> list.forEach(chunk -> {
|
||||
+ PlayerChunk updatingChunk = getUpdatingChunk(chunk.getPos().pair());
|
||||
+ if (updatingChunk != null) {
|
||||
+ updatingChunk.dependendedOnBy.remove(playerchunk.location);
|
||||
+ updatingChunk.lastActivity = world.getTime();
|
||||
+ }
|
||||
+ }));
|
||||
+ // Paper end
|
||||
|
||||
this.worldLoadListener.a(chunkcoordintpair, chunkstatus);
|
||||
return completablefuture1;
|
||||
@@ -1167,6 +1193,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
|
||||
});
|
||||
}, (runnable) -> {
|
||||
+ playerchunk.lastActivity = world.getTime(); // Paper
|
||||
this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // CraftBukkit - decompile error
|
||||
});
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
index acfe732af5b9f63fc2f6b78499defabe2e73ee45..25b19346fc1c702cc37275d0ec16abbbfacfb418 100644
|
||||
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
@@ -160,7 +160,7 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
while (longiterator.hasNext()) {
|
||||
long k = longiterator.nextLong();
|
||||
IChunkAccess ichunkaccess1 = generatoraccess.getChunkAt(ChunkCoordIntPair.getX(k), ChunkCoordIntPair.getZ(k), ChunkStatus.STRUCTURE_STARTS, false); // CraftBukkit - don't load chunks
|
||||
- StructureStart structurestart = ichunkaccess1.a(this.b());
|
||||
+ StructureStart structurestart = ichunkaccess1 != null ? ichunkaccess1.a(this.b()) : null; // Paper - make sure not null
|
||||
|
||||
if (structurestart != null) {
|
||||
list.add(structurestart);
|
@ -1,280 +0,0 @@
|
||||
From 22baa6be4daa8a11770411b50f1fbf545196407d Mon Sep 17 00:00:00 2001
|
||||
From: Byteflux <byte@byteflux.net>
|
||||
Date: Wed, 2 Mar 2016 14:35:27 -0600
|
||||
Subject: [PATCH] Add player view distance API
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
|
||||
index 58e037e13b..e97bb2305c 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityHuman.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
|
||||
@@ -71,6 +71,15 @@ public abstract class EntityHuman extends EntityLiving {
|
||||
// Paper start
|
||||
public boolean affectsSpawning = true;
|
||||
// Paper end
|
||||
+ // Paper start - Player view distance API
|
||||
+ private int viewDistance = -1;
|
||||
+ public int getViewDistance() {
|
||||
+ return viewDistance == -1 ? ((WorldServer) world).getPlayerChunkMap().getViewDistance() : viewDistance;
|
||||
+ }
|
||||
+ public void setViewDistance(int viewDistance) {
|
||||
+ this.viewDistance = viewDistance;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean fauxSleeping;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java
|
||||
index 45ab33d1ae..3854ae9769 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTracker.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTracker.java
|
||||
@@ -200,6 +200,7 @@ public class EntityTracker {
|
||||
|
||||
}
|
||||
|
||||
+ public void updatePlayer(EntityPlayer entityplayer) { a(entityplayer); } // Paper - OBFHELPER
|
||||
public void a(EntityPlayer entityplayer) {
|
||||
Iterator iterator = this.c.iterator();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
index d00401ce14..dd6c84b4a2 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
@@ -435,7 +435,7 @@ public class EntityTrackerEntry {
|
||||
public boolean c(EntityPlayer entityplayer) {
|
||||
double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D;
|
||||
double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D;
|
||||
- int i = Math.min(this.e, this.f);
|
||||
+ int i = Math.min(this.e, (entityplayer.getViewDistance() - 1) * 16); // Paper - Use player view distance API
|
||||
|
||||
return d0 >= (double) (-i) && d0 <= (double) i && d1 >= (double) (-i) && d1 <= (double) i && this.tracker.a(entityplayer);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index e01222ad2b..55161af9c9 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -33,7 +33,7 @@ public class PlayerChunkMap {
|
||||
private final List<PlayerChunk> g = Lists.newLinkedList();
|
||||
private final List<PlayerChunk> h = Lists.newLinkedList();
|
||||
private final List<PlayerChunk> i = Lists.newArrayList();
|
||||
- private int j;
|
||||
+ private int j;public int getViewDistance() { return j; } // Paper OBFHELPER
|
||||
private long k;
|
||||
private boolean l = true;
|
||||
private boolean m = true;
|
||||
@@ -257,8 +257,11 @@ public class PlayerChunkMap {
|
||||
// CraftBukkit start - Load nearby chunks first
|
||||
List<ChunkCoordIntPair> chunkList = new LinkedList<ChunkCoordIntPair>();
|
||||
|
||||
- for (int k = i - this.j; k <= i + this.j; ++k) {
|
||||
- for (int l = j - this.j; l <= j + this.j; ++l) {
|
||||
+ // Paper start - Player view distance API
|
||||
+ int viewDistance = entityplayer.getViewDistance();
|
||||
+ for (int k = i - viewDistance; k <= i + viewDistance; ++k) {
|
||||
+ for (int l = j - viewDistance; l <= j + viewDistance; ++l) {
|
||||
+ // Paper end
|
||||
chunkList.add(new ChunkCoordIntPair(k, l));
|
||||
}
|
||||
}
|
||||
@@ -277,8 +280,11 @@ public class PlayerChunkMap {
|
||||
int i = (int) entityplayer.d >> 4;
|
||||
int j = (int) entityplayer.e >> 4;
|
||||
|
||||
- for (int k = i - this.j; k <= i + this.j; ++k) {
|
||||
- for (int l = j - this.j; l <= j + this.j; ++l) {
|
||||
+ // Paper start - Player view distance API
|
||||
+ int viewDistance = entityplayer.getViewDistance();
|
||||
+ for (int k = i - viewDistance; k <= i + viewDistance; ++k) {
|
||||
+ for (int l = j - viewDistance; l <= j + viewDistance; ++l) {
|
||||
+ // Paper end
|
||||
PlayerChunk playerchunk = this.getChunk(k, l);
|
||||
|
||||
if (playerchunk != null) {
|
||||
@@ -308,7 +314,8 @@ public class PlayerChunkMap {
|
||||
if (d2 >= 64.0D) {
|
||||
int k = (int) entityplayer.d >> 4;
|
||||
int l = (int) entityplayer.e >> 4;
|
||||
- int i1 = this.j;
|
||||
+ int i1 = entityplayer.getViewDistance(); // Paper - Player view distance API
|
||||
+
|
||||
int j1 = i - k;
|
||||
int k1 = j - l;
|
||||
|
||||
@@ -352,6 +359,8 @@ public class PlayerChunkMap {
|
||||
return playerchunk != null && playerchunk.d(entityplayer) && playerchunk.e();
|
||||
}
|
||||
|
||||
+ public final void setViewDistanceForAll(int viewDistance) { this.a(viewDistance); } // Paper - OBFHELPER
|
||||
+ // Paper start - Separate into two methods
|
||||
public void a(int i) {
|
||||
i = MathHelper.clamp(i, 3, 32);
|
||||
if (i != this.j) {
|
||||
@@ -361,36 +370,55 @@ public class PlayerChunkMap {
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
EntityPlayer entityplayer = (EntityPlayer) iterator.next();
|
||||
- int k = (int) entityplayer.locX >> 4;
|
||||
- int l = (int) entityplayer.locZ >> 4;
|
||||
- int i1;
|
||||
- int j1;
|
||||
-
|
||||
- if (j > 0) {
|
||||
- for (i1 = k - i; i1 <= k + i; ++i1) {
|
||||
- for (j1 = l - i; j1 <= l + i; ++j1) {
|
||||
- PlayerChunk playerchunk = this.c(i1, j1);
|
||||
-
|
||||
- if (!playerchunk.d(entityplayer)) {
|
||||
- playerchunk.a(entityplayer);
|
||||
- }
|
||||
+ this.setViewDistance(entityplayer, i, false); // Paper - Split, don't mark sort pending, we'll handle it after
|
||||
+ }
|
||||
+
|
||||
+ this.j = i;
|
||||
+ this.e();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void setViewDistance(EntityPlayer entityplayer, int i) {
|
||||
+ this.setViewDistance(entityplayer, i, true); // Mark sort pending by default so we don't have to remember to do so all the time
|
||||
+ }
|
||||
+
|
||||
+ // Copied from above with minor changes
|
||||
+ public void setViewDistance(EntityPlayer entityplayer, int i, boolean markSort) {
|
||||
+ i = MathHelper.clamp(i, 3, 32);
|
||||
+ int oldViewDistance = entityplayer.getViewDistance();
|
||||
+ if (i != oldViewDistance) {
|
||||
+ int j = i - oldViewDistance;
|
||||
+
|
||||
+ int k = (int) entityplayer.locX >> 4;
|
||||
+ int l = (int) entityplayer.locZ >> 4;
|
||||
+ int i1;
|
||||
+ int j1;
|
||||
+
|
||||
+ if (j > 0) {
|
||||
+ for (i1 = k - i; i1 <= k + i; ++i1) {
|
||||
+ for (j1 = l - i; j1 <= l + i; ++j1) {
|
||||
+ PlayerChunk playerchunk = this.c(i1, j1);
|
||||
+
|
||||
+ if (!playerchunk.d(entityplayer)) {
|
||||
+ playerchunk.a(entityplayer);
|
||||
}
|
||||
}
|
||||
- } else {
|
||||
- for (i1 = k - this.j; i1 <= k + this.j; ++i1) {
|
||||
- for (j1 = l - this.j; j1 <= l + this.j; ++j1) {
|
||||
- if (!this.a(i1, j1, k, l, i)) {
|
||||
- this.c(i1, j1).b(entityplayer);
|
||||
- }
|
||||
+ }
|
||||
+ } else {
|
||||
+ for (i1 = k - oldViewDistance; i1 <= k + oldViewDistance; ++i1) {
|
||||
+ for (j1 = l - oldViewDistance; j1 <= l + oldViewDistance; ++j1) {
|
||||
+ if (!this.a(i1, j1, k, l, i)) {
|
||||
+ this.c(i1, j1).b(entityplayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
+ if (markSort) {
|
||||
+ this.e();
|
||||
+ }
|
||||
}
|
||||
-
|
||||
- this.j = i;
|
||||
- this.e();
|
||||
}
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
private void e() {
|
||||
this.l = true;
|
||||
@@ -469,4 +497,32 @@ public class PlayerChunkMap {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ // Paper start - Player view distance API
|
||||
+ public void updateViewDistance(EntityPlayer player, int distanceIn) {
|
||||
+ final int oldViewDistance = player.getViewDistance();
|
||||
+
|
||||
+ // This represents the view distance that we will set on the player
|
||||
+ // It can exist as a negative value
|
||||
+ int playerViewDistance = MathHelper.clamp(distanceIn, 3, 32);
|
||||
+
|
||||
+ // This value is the one we actually use to update the chunk map
|
||||
+ // We don't ever want this to be a negative
|
||||
+ int toSet = playerViewDistance;
|
||||
+
|
||||
+ if (distanceIn < 0) {
|
||||
+ playerViewDistance = -1;
|
||||
+ toSet = world.getPlayerChunkMap().getViewDistance();
|
||||
+ }
|
||||
+
|
||||
+ if (toSet != oldViewDistance) {
|
||||
+ // Order matters
|
||||
+ this.setViewDistance(player, toSet);
|
||||
+ player.setViewDistance(playerViewDistance);
|
||||
+
|
||||
+ //Force update entity trackers
|
||||
+ this.getWorld().getTracker().updatePlayer(player);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
index 4eaa5d93b4..6720a9648e 100644
|
||||
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
||||
@@ -44,7 +44,7 @@ public final class SpawnerCreature {
|
||||
boolean flag3 = true;
|
||||
// Spigot Start
|
||||
byte b0 = worldserver.spigotConfig.mobSpawnRange;
|
||||
- b0 = ( b0 > worldserver.spigotConfig.viewDistance ) ? (byte) worldserver.spigotConfig.viewDistance : b0;
|
||||
+ b0 = ( b0 > entityhuman.getViewDistance() ) ? (byte) entityhuman.getViewDistance() : b0; // Paper - Use player view distance API
|
||||
b0 = ( b0 > 8 ) ? 8 : b0;
|
||||
|
||||
for (int i1 = -b0; i1 <= b0; ++i1) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
index 0ee063bcd3..5496fae409 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
||||
@@ -1626,6 +1626,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
||||
public boolean getAffectsSpawning() {
|
||||
return this.getHandle().affectsSpawning;
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public int getViewDistance() {
|
||||
+ return getHandle().getViewDistance();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void setViewDistance(int viewDistance) {
|
||||
+ ((WorldServer) getHandle().world).getPlayerChunkMap().updateViewDistance(getHandle(), viewDistance);
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
index a95f93eb76..09df00e94b 100644
|
||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
@@ -108,13 +108,13 @@ public class ActivationRange
|
||||
|
||||
int maxRange = Math.max( monsterActivationRange, animalActivationRange );
|
||||
maxRange = Math.max( maxRange, miscActivationRange );
|
||||
- maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange );
|
||||
+ //maxRange = Math.min( ( world.spigotConfig.viewDistance << 4 ) - 8, maxRange ); Paper - Use player view distance API below instead
|
||||
|
||||
for ( EntityHuman player : world.players )
|
||||
{
|
||||
-
|
||||
+ int playerMaxRange = maxRange = Math.min( ( player.getViewDistance() << 4 ) - 8, maxRange ); // Paper - Use player view distance API
|
||||
player.activatedTick = MinecraftServer.currentTick;
|
||||
- maxBB = player.getBoundingBox().grow( maxRange, 256, maxRange );
|
||||
+ maxBB = player.getBoundingBox().grow( playerMaxRange, 256, playerMaxRange ); // Paper - Use player view distance API
|
||||
miscBB = player.getBoundingBox().grow( miscActivationRange, 256, miscActivationRange );
|
||||
animalBB = player.getBoundingBox().grow( animalActivationRange, 256, animalActivationRange );
|
||||
monsterBB = player.getBoundingBox().grow( monsterActivationRange, 256, monsterActivationRange );
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,206 +0,0 @@
|
||||
From 208077ba7ae7f41d3bdfcc4f5bc577faa8095905 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 4 Mar 2016 18:18:37 -0600
|
||||
Subject: [PATCH] Chunk save queue improvements
|
||||
|
||||
For some unknown reason, Minecraft is sleeping 10ms between every single chunk being saved to disk.
|
||||
Under high chunk load/unload activity (lots of movement / teleporting), this causes the chunk unload queue
|
||||
to build up in size.
|
||||
|
||||
This has multiple impacts:
|
||||
1) Performance of the unload queue itself - The save thread is pretty ineffecient for how it accesses it
|
||||
By letting the queue get larger, checking and popping work off the queue can get less performant.
|
||||
2) Performance of chunk loading - As with #1, chunk loads also have to check this queue when loading
|
||||
chunk data so that it doesn't load stale data if new data is pending write to disk.
|
||||
3) Memory Usage - The entire chunk has been serialized to NBT, and now sits in this queue. This leads to
|
||||
elevated memory usage, and then the objects used in the serialization sit around longer than needed,
|
||||
resulting in promotion to Old Generation instead of dying young.
|
||||
|
||||
To optimize this, we change the entire unload queue to be a proper queue. This improves the behavior of popping
|
||||
the first queued chunk off, instead of abusing iterators like Mojang was doing.
|
||||
|
||||
This also improves reliability of chunk saving, as the previous hack job had a race condition that could
|
||||
fail to save some chunks.
|
||||
|
||||
Then finally, Sleeping will by default be removed, but due to known issues with 1.9, a config option was added.
|
||||
But if sleeps are to remain enabled, we at least lower the sleep interval so it doesn't have as much negative impact.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index cfcc244672..4e932ea235 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -217,4 +217,10 @@ public class PaperConfig {
|
||||
" - Interval: " + timeSummary(Timings.getHistoryInterval() / 20) +
|
||||
" - Length: " + timeSummary(Timings.getHistoryLength() / 20));
|
||||
}
|
||||
+
|
||||
+ public static boolean enableFileIOThreadSleep;
|
||||
+ private static void enableFileIOThreadSleep() {
|
||||
+ enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false);
|
||||
+ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues");
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
index b0c004b1f2..d2cece2651 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
@@ -20,6 +20,7 @@ public class ChunkCoordIntPair {
|
||||
this.z = (int) (i >> 32);
|
||||
}
|
||||
|
||||
+ public long asLong() { return a(); } // Paper
|
||||
public long a() {
|
||||
return a(this.x, this.z);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
index 35976a26f3..21ee154a57 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
@@ -20,6 +20,7 @@ import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
+import java.util.concurrent.ConcurrentLinkedQueue; // Paper
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
// Spigot start
|
||||
@@ -29,8 +30,28 @@ import org.spigotmc.SupplierUtils;
|
||||
|
||||
public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
|
||||
+ // Paper start - Chunk queue improvements
|
||||
+ private static class QueuedChunk {
|
||||
+ public ChunkCoordIntPair coords;
|
||||
+ public Supplier<NBTTagCompound> compoundSupplier;
|
||||
+ public Runnable onSave;
|
||||
+
|
||||
+ public QueuedChunk(Runnable run) {
|
||||
+ this.coords = null;
|
||||
+ this.compoundSupplier = null;
|
||||
+ this.onSave = run;
|
||||
+ }
|
||||
+
|
||||
+ public QueuedChunk(ChunkCoordIntPair coords, Supplier<NBTTagCompound> compoundSupplier) {
|
||||
+ this.coords = coords;
|
||||
+ this.compoundSupplier = compoundSupplier;
|
||||
+ }
|
||||
+ }
|
||||
+ final private ConcurrentLinkedQueue<QueuedChunk> queue = new ConcurrentLinkedQueue<>();
|
||||
+ // Paper end
|
||||
+
|
||||
private static final Logger a = LogManager.getLogger();
|
||||
- private final Map<ChunkCoordIntPair, Supplier<NBTTagCompound>> b = Maps.newHashMap();
|
||||
+ private final it.unimi.dsi.fastutil.longs.Long2ObjectMap<Supplier<NBTTagCompound>> saveMap = it.unimi.dsi.fastutil.longs.Long2ObjectMaps.synchronize(new it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap<>()); // Paper
|
||||
private final File c;
|
||||
private final DataFixer d;
|
||||
private PersistentStructureLegacy e;
|
||||
@@ -86,7 +107,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
return null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.b.get(new ChunkCoordIntPair(i, j))); // Spigot
|
||||
+ NBTTagCompound nbttagcompound = SupplierUtils.getIfExists(this.saveMap.get(ChunkCoordIntPair.asLong(i, j))); // Spigot // Paper
|
||||
|
||||
if (nbttagcompound != null) {
|
||||
return nbttagcompound;
|
||||
@@ -314,7 +335,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
};
|
||||
}
|
||||
|
||||
- this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded && this.b.size() < SAVE_QUEUE_TARGET_SIZE));
|
||||
+ this.a(chunkcoordintpair, SupplierUtils.createUnivaluedSupplier(completion, unloaded)); // Paper - Remove save queue target size
|
||||
// Spigot end
|
||||
} catch (Exception exception) {
|
||||
ChunkRegionLoader.a.error("Failed to save chunk", exception);
|
||||
@@ -323,7 +344,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
}
|
||||
|
||||
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
|
||||
- this.b.put(chunkcoordintpair, nbttagcompound);
|
||||
+ this.saveMap.put(chunkcoordintpair.asLong(), nbttagcompound); // Paper
|
||||
+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
|
||||
FileIOThread.a().a(this);
|
||||
}
|
||||
|
||||
@@ -333,20 +355,24 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
}
|
||||
|
||||
private boolean processSaveQueueEntry(boolean logCompletion) {
|
||||
- Iterator<Entry<ChunkCoordIntPair, Supplier<NBTTagCompound>>> iterator = this.b.entrySet().iterator(); // Spigot
|
||||
-
|
||||
- if (!iterator.hasNext()) {
|
||||
+ // Paper start - Chunk queue improvements
|
||||
+ QueuedChunk chunk = queue.poll();
|
||||
+ if (chunk == null) {
|
||||
+ // Paper - end
|
||||
if (logCompletion) { // CraftBukkit
|
||||
ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.c.getName());
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
- Entry<ChunkCoordIntPair, NBTTagCompound> entry = (Entry) iterator.next();
|
||||
-
|
||||
- iterator.remove();
|
||||
- ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) entry.getKey();
|
||||
- Supplier<NBTTagCompound> nbttagcompound = (Supplier<NBTTagCompound>) entry.getValue(); // Spigot
|
||||
+ // Paper start
|
||||
+ if (chunk.onSave != null) {
|
||||
+ chunk.onSave.run();
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+ ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements
|
||||
+ Supplier<NBTTagCompound> nbttagcompound = chunk.compoundSupplier; // Spigot // Paper
|
||||
|
||||
if (nbttagcompound == null) {
|
||||
return true;
|
||||
@@ -355,6 +381,15 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
// CraftBukkit start
|
||||
RegionFileCache.write(this.c, chunkcoordintpair.x, chunkcoordintpair.z, SupplierUtils.getIfExists(nbttagcompound)); // Spigot
|
||||
|
||||
+ // Paper start remove from map only if this was the latest version of the chunk
|
||||
+ synchronized (this.saveMap) {
|
||||
+ long k = chunkcoordintpair.asLong();
|
||||
+ // This will not equal if a newer version is still pending - wait until newest is saved to remove
|
||||
+ if (this.saveMap.get(k) == chunk.compoundSupplier) {
|
||||
+ this.saveMap.remove(k);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
/*
|
||||
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
|
||||
dataoutputstream.close();
|
||||
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
index 8c3537ab8d..3c688f546c 100644
|
||||
--- a/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
+++ b/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
@@ -38,20 +38,21 @@ public class FileIOThread implements Runnable {
|
||||
IAsyncChunkSaver iasyncchunksaver = (IAsyncChunkSaver) this.c.get(i);
|
||||
boolean flag;
|
||||
|
||||
- synchronized (iasyncchunksaver) {
|
||||
+ //synchronized (iasyncchunksaver) { // Paper - remove synchronized
|
||||
flag = iasyncchunksaver.a();
|
||||
- }
|
||||
+ //} // Paper
|
||||
|
||||
if (!flag) {
|
||||
this.c.remove(i--);
|
||||
++this.e;
|
||||
}
|
||||
|
||||
+ if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { // Paper
|
||||
try {
|
||||
- Thread.sleep(this.f ? 0L : 10L);
|
||||
+ Thread.sleep(this.f ? 0L : 1L); // Paper
|
||||
} catch (InterruptedException interruptedexception) {
|
||||
interruptedexception.printStackTrace();
|
||||
- }
|
||||
+ }} // Paper
|
||||
}
|
||||
|
||||
if (this.c.isEmpty()) {
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,90 +0,0 @@
|
||||
From 62de9801d97be7f583f88f20b374660bb4349cc8 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 18 Mar 2016 21:22:56 -0400
|
||||
Subject: [PATCH] Optimized Light Level Comparisons
|
||||
|
||||
Use an optimized method to test if a block position meets a desired light level.
|
||||
|
||||
This method benefits from returning as soon as the desired light level matches.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockCrops.java b/src/main/java/net/minecraft/server/BlockCrops.java
|
||||
index fe0dde1461..9d53f1118c 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockCrops.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockCrops.java
|
||||
@@ -44,7 +44,7 @@ public class BlockCrops extends BlockPlant implements IBlockFragilePlantElement
|
||||
|
||||
public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Random random) {
|
||||
super.a(iblockdata, world, blockposition, random);
|
||||
- if (world.getLightLevel(blockposition.up(), 0) >= 9) {
|
||||
+ if (world.isLightLevel(blockposition.up(), 9)) { // Paper
|
||||
int i = this.k(iblockdata);
|
||||
|
||||
if (i < this.e()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockSapling.java b/src/main/java/net/minecraft/server/BlockSapling.java
|
||||
index 81ea9bcb4f..291cc9a398 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockSapling.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockSapling.java
|
||||
@@ -30,7 +30,7 @@ public class BlockSapling extends BlockPlant implements IBlockFragilePlantElemen
|
||||
|
||||
public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Random random) {
|
||||
super.a(iblockdata, world, blockposition, random);
|
||||
- if (world.getLightLevel(blockposition.up()) >= 9 && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot
|
||||
+ if (world.isLightLevel(blockposition.up(), 9) && random.nextInt(Math.max(2, (int) (((100.0F / world.spigotConfig.saplingModifier) * 7) + 0.5F))) == 0) { // Spigot // Paper
|
||||
// CraftBukkit start
|
||||
world.captureTreeGeneration = true;
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockStem.java b/src/main/java/net/minecraft/server/BlockStem.java
|
||||
index 53f091835c..f8dda1b7a1 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockStem.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockStem.java
|
||||
@@ -27,7 +27,7 @@ public class BlockStem extends BlockPlant implements IBlockFragilePlantElement {
|
||||
|
||||
public void a(IBlockData iblockdata, World world, BlockPosition blockposition, Random random) {
|
||||
super.a(iblockdata, world, blockposition, random);
|
||||
- if (world.getLightLevel(blockposition.up(), 0) >= 9) {
|
||||
+ if (world.isLightLevel(blockposition.up(), 9)) { // Paper
|
||||
float f = BlockCrops.a((Block) this, (IBlockAccess) world, blockposition);
|
||||
|
||||
if (random.nextInt((int) ((100.0F / (this == Blocks.PUMPKIN_STEM ? world.spigotConfig.pumpkinModifier : world.spigotConfig.melonModifier)) * (25.0F / f)) + 1) == 0) { // Spigot
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityMonster.java b/src/main/java/net/minecraft/server/EntityMonster.java
|
||||
index 5ea5170436..dc61263a3f 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityMonster.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityMonster.java
|
||||
@@ -66,9 +66,18 @@ public abstract class EntityMonster extends EntityCreature implements IMonster {
|
||||
if (this.world.getBrightness(EnumSkyBlock.SKY, blockposition) > this.random.nextInt(32)) {
|
||||
return false;
|
||||
} else {
|
||||
- int i = this.world.Y() ? this.world.d(blockposition, 10) : this.world.getLightLevel(blockposition);
|
||||
-
|
||||
- return i <= this.random.nextInt(8);
|
||||
+ // Paper start - optimized light check, returns faster
|
||||
+ boolean passes;
|
||||
+ if (this.world.Y()) {
|
||||
+ final int orig = world.getSkylightSubtracted();
|
||||
+ world.setSkylightSubtracted(10);
|
||||
+ passes = !this.world.isLightLevel(blockposition, this.random.nextInt(8));
|
||||
+ world.setSkylightSubtracted(orig);
|
||||
+ } else {
|
||||
+ passes = !this.world.isLightLevel(blockposition, this.random.nextInt(8));
|
||||
+ }
|
||||
+ return passes;
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
index 002be7f7be..7a943a6c27 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
@@ -267,7 +267,7 @@ public class EntityZombie extends EntityMonster {
|
||||
int j1 = j + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
|
||||
int k1 = k + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
|
||||
|
||||
- if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).q() && this.world.getLightLevel(new BlockPosition(i1, j1, k1)) < 10) {
|
||||
+ if (this.world.getType(new BlockPosition(i1, j1 - 1, k1)).q() && !this.world.isLightLevel(new BlockPosition(i1, j1, k1), 10)) { // Paper
|
||||
entityzombie.setPosition((double) i1, (double) j1, (double) k1);
|
||||
if (!this.world.isPlayerNearby((double) i1, (double) j1, (double) k1, 7.0D) && this.world.a_(entityzombie, entityzombie.getBoundingBox()) && this.world.getCubes(entityzombie, entityzombie.getBoundingBox()) && !this.world.containsLiquid(entityzombie.getBoundingBox())) {
|
||||
this.world.addEntity(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,36 +0,0 @@
|
||||
From b61f0153ccd138435700cfb4c711f477112574f6 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 19 Mar 2016 15:16:54 -0400
|
||||
Subject: [PATCH] Pass world to Village creation
|
||||
|
||||
fixes NPE bug #95
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PersistentVillage.java b/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
index 98c6bbc183..7a9fb97530 100644
|
||||
--- a/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
+++ b/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
@@ -237,7 +237,7 @@ public class PersistentVillage extends PersistentBase {
|
||||
|
||||
for (int i = 0; i < nbttaglist.size(); ++i) {
|
||||
NBTTagCompound nbttagcompound1 = nbttaglist.getCompound(i);
|
||||
- Village village = new Village();
|
||||
+ Village village = new Village(world); // Paper
|
||||
|
||||
village.a(nbttagcompound1);
|
||||
this.villages.add(village);
|
||||
diff --git a/src/main/java/net/minecraft/server/Village.java b/src/main/java/net/minecraft/server/Village.java
|
||||
index 68ad7bc213..b794572915 100644
|
||||
--- a/src/main/java/net/minecraft/server/Village.java
|
||||
+++ b/src/main/java/net/minecraft/server/Village.java
|
||||
@@ -24,7 +24,7 @@ public class Village {
|
||||
private final List<Village.Aggressor> k;
|
||||
private int l;
|
||||
|
||||
- public Village() {
|
||||
+ private Village() { // Paper - Nothing should call this - world needs to be set.
|
||||
this.c = BlockPosition.ZERO;
|
||||
this.d = BlockPosition.ZERO;
|
||||
this.j = Maps.newHashMap();
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,125 +0,0 @@
|
||||
From 11ab12d6efda726da59ca55d164a9ba49af71e59 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 27 Aug 2015 01:15:02 -0400
|
||||
Subject: [PATCH] Optimize Chunk Access
|
||||
|
||||
getting a loaded chunk is one of the most hottest pieces of code in the game.
|
||||
getChunkAt is called for the same chunk multiple times in a row, often from getType();
|
||||
|
||||
Optimize this look up by using a Last Access cache.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkMap.java b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
index 732c8793e5..8b3738c8f7 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
@@ -15,6 +15,7 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
|
||||
public Chunk put(long i, Chunk chunk) {
|
||||
chunk.world.timings.syncChunkLoadPostTimer.startTiming(); // Paper
|
||||
+ lastChunkByPos = chunk; // Paper
|
||||
Chunk chunk1 = (Chunk) super.put(i, chunk);
|
||||
ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i);
|
||||
|
||||
@@ -22,7 +23,7 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
for (int k = chunkcoordintpair.z - 1; k <= chunkcoordintpair.z + 1; ++k) {
|
||||
if (j != chunkcoordintpair.x || k != chunkcoordintpair.z) {
|
||||
long l = ChunkCoordIntPair.a(j, k);
|
||||
- Chunk chunk2 = (Chunk) this.get(l);
|
||||
+ Chunk chunk2 = (Chunk) super.get(l); // Paper - use super to avoid polluting last access cache
|
||||
|
||||
if (chunk2 != null) {
|
||||
chunk.H();
|
||||
@@ -40,7 +41,7 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
continue;
|
||||
}
|
||||
|
||||
- Chunk neighbor = this.get(ChunkCoordIntPair.a(chunkcoordintpair.x + x, chunkcoordintpair.z + z));
|
||||
+ Chunk neighbor = super.get(ChunkCoordIntPair.a(chunkcoordintpair.x + x, chunkcoordintpair.z + z)); // Paper - use super to avoid polluting last access cache
|
||||
if (neighbor != null) {
|
||||
neighbor.setNeighborLoaded(-x, -z);
|
||||
chunk.setNeighborLoaded(x, z);
|
||||
@@ -64,7 +65,7 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
for (int j = chunkcoordintpair.x - 1; j <= chunkcoordintpair.x + 1; ++j) {
|
||||
for (int k = chunkcoordintpair.z - 1; k <= chunkcoordintpair.z + 1; ++k) {
|
||||
if (j != chunkcoordintpair.x || k != chunkcoordintpair.z) {
|
||||
- Chunk chunk1 = (Chunk) this.get(ChunkCoordIntPair.a(j, k));
|
||||
+ Chunk chunk1 = (Chunk) super.get(ChunkCoordIntPair.a(j, k)); // Paper - use super to avoid polluting last access cache
|
||||
|
||||
if (chunk1 != null) {
|
||||
chunk1.I();
|
||||
@@ -73,8 +74,22 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ if (lastChunkByPos != null && i == lastChunkByPos.chunkKey) {
|
||||
+ lastChunkByPos = null;
|
||||
+ }
|
||||
return chunk;
|
||||
}
|
||||
+ private Chunk lastChunkByPos = null;
|
||||
+
|
||||
+ @Override
|
||||
+ public Chunk get(long l) {
|
||||
+ if (lastChunkByPos != null && l == lastChunkByPos.chunkKey) {
|
||||
+ return lastChunkByPos;
|
||||
+ }
|
||||
+ return lastChunkByPos = super.get(l);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public Chunk remove(Object object) {
|
||||
return this.remove((Long) object);
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 1ed7c7e2c9..c54df45837 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -76,15 +76,16 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
Chunk chunk;
|
||||
|
||||
synchronized (this.chunkLoader) {
|
||||
- if (this.lastChunk != null && this.lastChunk.getPos().x == i && this.lastChunk.getPos().z == j) {
|
||||
+ // Paper start - remove vanilla lastChunk, we do it more accurately
|
||||
+ /* if (this.lastChunk != null && this.lastChunk.locX == i && this.lastChunk.locZ == j) {
|
||||
return this.lastChunk;
|
||||
- }
|
||||
+ }*/ // Paper end
|
||||
|
||||
long k = ChunkCoordIntPair.a(i, j);
|
||||
|
||||
chunk = (Chunk) this.chunks.get(k);
|
||||
if (chunk != null) {
|
||||
- this.lastChunk = chunk;
|
||||
+ //this.lastChunk = chunk; // Paper remove vanilla lastChunk
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@@ -198,7 +199,7 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
}
|
||||
|
||||
this.chunks.put(k, chunk);
|
||||
- this.lastChunk = chunk;
|
||||
+ //this.lastChunk = chunk; // Paper
|
||||
}
|
||||
|
||||
this.asyncTaskHandler.postToMainThread(chunk::addEntities);
|
||||
@@ -344,7 +345,7 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
this.saveChunk(chunk, true); // Spigot
|
||||
}
|
||||
this.chunks.remove(chunk.chunkKey);
|
||||
- this.lastChunk = null;
|
||||
+ // this.lastChunk = null; // Paper
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -380,6 +381,6 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
}
|
||||
|
||||
public boolean isLoaded(int i, int j) {
|
||||
- return this.chunks.containsKey(ChunkCoordIntPair.a(i, j));
|
||||
+ return this.chunks.get(ChunkCoordIntPair.asLong(i, j)) != null; // Paper - use get for last access
|
||||
}
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,34 +0,0 @@
|
||||
From 2c462895126242c15395ff2033688c432492ad50 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 5 Apr 2016 19:42:22 -0400
|
||||
Subject: [PATCH] Don't spam reload spawn chunks in nether/end
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index b595536648..5fc2da0d92 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -2849,6 +2849,7 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
return this.K;
|
||||
}
|
||||
|
||||
+ public boolean isSpawnChunk(int i, int j) { return e(i, j); } // Paper - OBFHELPER
|
||||
public boolean e(int i, int j) {
|
||||
BlockPosition blockposition = this.getSpawn();
|
||||
int k = i * 16 + 8 - blockposition.getX();
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldProvider.java b/src/main/java/net/minecraft/server/WorldProvider.java
|
||||
index 5e87e537e4..3911e4947e 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldProvider.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldProvider.java
|
||||
@@ -69,7 +69,7 @@ public abstract class WorldProvider {
|
||||
public void l() {}
|
||||
|
||||
public boolean a(int i, int j) {
|
||||
- return !this.b.isForceLoaded(i, j);
|
||||
+ return !this.b.isSpawnChunk(i, j) && !this.b.isForceLoaded(i, j); // Paper - Use spawn chunks check for all worlds
|
||||
}
|
||||
|
||||
protected abstract void m();
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,103 +0,0 @@
|
||||
From 6d6e37ba0e3e91d7a711bc05c53daeeb304b82f4 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 17 Jun 2013 01:24:00 -0400
|
||||
Subject: [PATCH] Entity Tracking Improvements
|
||||
|
||||
If any part of a Vehicle/Passenger relationship is visible to a player,
|
||||
send all passenger/vehicles to the player in the chain.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
||||
index c9b37727ff..82994db643 100644
|
||||
--- a/src/main/java/net/minecraft/server/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/server/Entity.java
|
||||
@@ -70,6 +70,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
||||
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
||||
protected CraftEntity bukkitEntity;
|
||||
|
||||
+ EntityTrackerEntry tracker; // Paper
|
||||
public CraftEntity getBukkitEntity() {
|
||||
if (bukkitEntity == null) {
|
||||
bukkitEntity = CraftEntity.getEntity(world.getServer(), this);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
index de0cf6b735..5629f9909b 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
|
||||
@@ -56,6 +56,7 @@ public class EntityTrackerEntry {
|
||||
// Paper end
|
||||
|
||||
public EntityTrackerEntry(Entity entity, int i, int j, int k, boolean flag) {
|
||||
+ entity.tracker = this; // Paper
|
||||
this.tracker = entity;
|
||||
this.e = i;
|
||||
this.f = j;
|
||||
@@ -453,17 +454,59 @@ public class EntityTrackerEntry {
|
||||
|
||||
this.tracker.b(entityplayer);
|
||||
entityplayer.d(this.tracker);
|
||||
+ updatePassengers(entityplayer); // Paper
|
||||
}
|
||||
} else if (this.trackedPlayers.contains(entityplayer)) {
|
||||
this.trackedPlayers.remove(entityplayer);
|
||||
this.tracker.c(entityplayer);
|
||||
entityplayer.c(this.tracker);
|
||||
+ updatePassengers(entityplayer); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public boolean c(EntityPlayer entityplayer) {
|
||||
+ // Paper start
|
||||
+ if (tracker.isPassenger()) {
|
||||
+ return isTrackedBy(tracker.getVehicle(), entityplayer);
|
||||
+ } else if (hasPassengerInRange(tracker, entityplayer)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return isInRangeOfPlayer(entityplayer);
|
||||
+ }
|
||||
+ private static boolean hasPassengerInRange(Entity entity, EntityPlayer entityplayer) {
|
||||
+ if (!entity.isVehicle()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ for (Entity passenger : entity.passengers) {
|
||||
+ if (passenger.tracker != null && passenger.tracker.isInRangeOfPlayer(entityplayer)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (passenger.isVehicle()) {
|
||||
+ if (hasPassengerInRange(passenger, entityplayer)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ private static boolean isTrackedBy(Entity entity, EntityPlayer entityplayer) {
|
||||
+ return entity == entityplayer || entity.tracker != null && entity.tracker.trackedPlayers.contains(entityplayer);
|
||||
+ }
|
||||
+ private void updatePassengers(EntityPlayer player) {
|
||||
+ if (tracker.isVehicle()) {
|
||||
+ tracker.passengers.forEach((e) -> {
|
||||
+ if (e.tracker != null) {
|
||||
+ e.tracker.updatePlayer(player);
|
||||
+ }
|
||||
+ });
|
||||
+ player.playerConnection.sendPacket(new PacketPlayOutMount(this.tracker));
|
||||
+ }
|
||||
+ }
|
||||
+ private boolean isInRangeOfPlayer(EntityPlayer entityplayer) {
|
||||
+ // Paper end
|
||||
double d0 = entityplayer.locX - (double) this.xLoc / 4096.0D;
|
||||
double d1 = entityplayer.locZ - (double) this.zLoc / 4096.0D;
|
||||
int i = Math.min(this.e, (entityplayer.getViewDistance() - 1) * 16); // Paper - Use player view distance API
|
||||
@@ -604,6 +647,7 @@ public class EntityTrackerEntry {
|
||||
this.trackedPlayers.remove(entityplayer);
|
||||
this.tracker.c(entityplayer);
|
||||
entityplayer.c(this.tracker);
|
||||
+ updatePassengers(entityplayer); // Paper
|
||||
}
|
||||
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 036c518050a0972307568a014156d59bb90bf54c Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 27 May 2016 21:41:26 -0400
|
||||
Subject: [PATCH] Ensure Chunks never ever load async
|
||||
|
||||
Safely pushes the operation to main thread, then back to the posting thread
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java
|
||||
index e4fd9bc604..7ffb8f6172 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOExecutor.java
|
||||
@@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.chunkio;
|
||||
import net.minecraft.server.Chunk;
|
||||
import net.minecraft.server.ChunkProviderServer;
|
||||
import net.minecraft.server.ChunkRegionLoader;
|
||||
+import net.minecraft.server.MCUtil; // Paper
|
||||
import net.minecraft.server.World;
|
||||
import org.bukkit.craftbukkit.util.AsynchronousExecutor;
|
||||
|
||||
@@ -13,7 +14,7 @@ public class ChunkIOExecutor {
|
||||
private static final AsynchronousExecutor<QueuedChunk, Chunk, Runnable, RuntimeException> instance = new AsynchronousExecutor<QueuedChunk, Chunk, Runnable, RuntimeException>(new ChunkIOProvider(), BASE_THREADS);
|
||||
|
||||
public static Chunk syncChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z) {
|
||||
- return instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider));
|
||||
+ return MCUtil.ensureMain("Async Chunk Load", () -> instance.getSkipQueue(new QueuedChunk(x, z, loader, world, provider))); // Paper
|
||||
}
|
||||
|
||||
public static void queueChunkLoad(World world, ChunkRegionLoader loader, ChunkProviderServer provider, int x, int z, Runnable runnable) {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
|
||||
index 52a8c48fa4..4cfe24df15 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
|
||||
@@ -35,9 +35,9 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
|
||||
|
||||
// sync stuff
|
||||
public void callStage2(QueuedChunk queuedChunk, Chunk chunk) throws RuntimeException {
|
||||
- if (chunk == null) {
|
||||
+ if (chunk == null || queuedChunk.provider.chunks.containsKey(ChunkCoordIntPair.a(queuedChunk.x, queuedChunk.z))) { // Paper - also call original if it was already loaded
|
||||
// If the chunk loading failed just do it synchronously (may generate)
|
||||
- // queuedChunk.provider.originalGetChunkAt(queuedChunk.x, queuedChunk.z);
|
||||
+ queuedChunk.provider.getChunkAt(queuedChunk.x, queuedChunk.z, true, true); // Paper - actually call original if it was already loaded
|
||||
return;
|
||||
}
|
||||
try (Timing ignored = queuedChunk.provider.world.timings.chunkIOStage2.startTimingIfSync()) { // Paper
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,224 +0,0 @@
|
||||
From 2fbf2c556d7840198741959940696a14c7e3c26a Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 18 Jun 2016 23:22:12 -0400
|
||||
Subject: [PATCH] Delay Chunk Unloads based on Player Movement
|
||||
|
||||
When players are moving in the world, doing things such as building or exploring,
|
||||
they will commonly go back and forth in a small area. This causes a ton of chunk load
|
||||
and unload activity on the edge chunks of their view distance.
|
||||
|
||||
A simple back and forth movement in 6 blocks could spam a chunk to thrash a
|
||||
loading and unload cycle over and over again.
|
||||
|
||||
This is very wasteful. This system introduces a delay of inactivity on a chunk
|
||||
before it actually unloads, which is maintained separately from ChunkGC.
|
||||
|
||||
This allows servers with smaller worlds who do less long distance exploring to stop
|
||||
wasting cpu cycles on saving/unloading/reloading chunks repeatedly.
|
||||
|
||||
This also makes the Chunk GC System useless, by auto scheduling unload as soon as
|
||||
a spare chunk is added to the server thats outside of view distance.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index bcc2ecaa3a..c70771614d 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -310,4 +310,18 @@ public class PaperWorldConfig {
|
||||
preventTntFromMovingInWater = getBoolean("prevent-tnt-from-moving-in-water", false);
|
||||
log("Prevent TNT from moving in water: " + preventTntFromMovingInWater);
|
||||
}
|
||||
+
|
||||
+ public long delayChunkUnloadsBy;
|
||||
+ private void delayChunkUnloadsBy() {
|
||||
+ delayChunkUnloadsBy = PaperConfig.getSeconds(getString("delay-chunk-unloads-by", "10s"));
|
||||
+ if (delayChunkUnloadsBy > 0) {
|
||||
+ log("Delaying chunk unloads by " + delayChunkUnloadsBy + " seconds");
|
||||
+ delayChunkUnloadsBy *= 1000;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public boolean skipEntityTickingInChunksScheduledForUnload = true;
|
||||
+ private void skipEntityTickingInChunksScheduledForUnload() {
|
||||
+ skipEntityTickingInChunksScheduledForUnload = getBoolean("skip-entity-ticking-in-chunks-scheduled-for-unload", skipEntityTickingInChunksScheduledForUnload);
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index c74176daa5..bdf922db50 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -40,6 +40,7 @@ public class Chunk implements IChunkAccess {
|
||||
private boolean i;public boolean isLoaded() { return i; } // Paper - OBFHELPER
|
||||
public final World world;
|
||||
public final Map<HeightMap.Type, HeightMap> heightMap;
|
||||
+ public Long scheduledForUnload; // Paper - delay chunk unloads
|
||||
public final int locX;
|
||||
public final int locZ;
|
||||
private boolean l;
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkMap.java b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
index 8b3738c8f7..2021c0d02e 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkMap.java
|
||||
@@ -48,6 +48,15 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // Paper start - if this is a spare chunk (not part of any players view distance), go ahead and queue it for unload.
|
||||
+ if (!((WorldServer)chunk.world).getPlayerChunkMap().isChunkInUse(chunk.locX, chunk.locZ)) {
|
||||
+ if (chunk.world.paperConfig.delayChunkUnloadsBy > 0) {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ } else {
|
||||
+ ((WorldServer) chunk.world).getChunkProvider().unload(chunk);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
chunk.world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper
|
||||
// CraftBukkit end
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index c54df45837..d0bf0f72da 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -307,6 +307,19 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
}
|
||||
activityAccountant.endActivity(); // Spigot
|
||||
}
|
||||
+ // Paper start - delayed chunk unloads
|
||||
+ long now = System.currentTimeMillis();
|
||||
+ long unloadAfter = world.paperConfig.delayChunkUnloadsBy;
|
||||
+ if (unloadAfter > 0) {
|
||||
+ //noinspection Convert2streamapi
|
||||
+ for (Chunk chunk : chunks.values()) {
|
||||
+ if (chunk.scheduledForUnload != null && now - chunk.scheduledForUnload > unloadAfter) {
|
||||
+ chunk.scheduledForUnload = null;
|
||||
+ unload(chunk);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
this.chunkScheduler.a(booleansupplier);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index e47aae2f8b..b9d90c4fb8 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -29,8 +29,23 @@ public class PlayerChunk {
|
||||
|
||||
chunkproviderserver.a(i, j);
|
||||
this.chunk = chunkproviderserver.getChunkAt(i, j, true, false);
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private void markChunkUsed() {
|
||||
+ if (chunk == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ if (chunkHasPlayers) {
|
||||
+ chunk.scheduledForUnload = null;
|
||||
+ } else if (chunk.scheduledForUnload == null) {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ }
|
||||
+ }
|
||||
+ private boolean chunkHasPlayers = false;
|
||||
+ // Paper end
|
||||
+
|
||||
public ChunkCoordIntPair a() {
|
||||
return this.location;
|
||||
}
|
||||
@@ -41,6 +56,8 @@ public class PlayerChunk {
|
||||
} else {
|
||||
if (this.players.isEmpty()) {
|
||||
this.i = this.playerChunkMap.getWorld().getTime();
|
||||
+ chunkHasPlayers = true; // Paper - delay chunk unloads
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
}
|
||||
|
||||
this.players.add(entityplayer);
|
||||
@@ -59,6 +76,8 @@ public class PlayerChunk {
|
||||
|
||||
this.players.remove(entityplayer);
|
||||
if (this.players.isEmpty()) {
|
||||
+ chunkHasPlayers = false; // Paper - delay chunk unloads
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
this.playerChunkMap.b(this);
|
||||
}
|
||||
|
||||
@@ -70,6 +89,7 @@ public class PlayerChunk {
|
||||
return true;
|
||||
} else {
|
||||
this.chunk = this.playerChunkMap.getWorld().getChunkProvider().getChunkAt(this.location.x, this.location.z, true, flag);
|
||||
+ markChunkUsed(); // Paper - delay chunk unloads
|
||||
return this.chunk != null;
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 2064576501..ab4f3b7223 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -452,7 +452,13 @@ public class PlayerChunkMap {
|
||||
Chunk chunk = playerchunk.f();
|
||||
|
||||
if (chunk != null) {
|
||||
- this.getWorld().getChunkProvider().unload(chunk);
|
||||
+ // Paper start - delay chunk unloads
|
||||
+ if (world.paperConfig.delayChunkUnloadsBy <= 0) {
|
||||
+ this.getWorld().getChunkProvider().unload(chunk);
|
||||
+ } else {
|
||||
+ chunk.scheduledForUnload = System.currentTimeMillis();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 32ee298648..dcff6c8d8a 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -1293,7 +1293,13 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
if (!tileentity.x() && tileentity.hasWorld()) {
|
||||
BlockPosition blockposition = tileentity.getPosition();
|
||||
|
||||
- if (this.isLoaded(blockposition) && this.K.a(blockposition)) {
|
||||
+ // Paper start - Skip ticking in chunks scheduled for unload
|
||||
+ net.minecraft.server.Chunk chunk = this.getChunkIfLoaded(blockposition);
|
||||
+ boolean shouldTick = chunk != null;
|
||||
+ if(this.paperConfig.skipEntityTickingInChunksScheduledForUnload)
|
||||
+ shouldTick = shouldTick && chunk.scheduledForUnload == null;
|
||||
+ if (shouldTick && this.K.a(blockposition)) {
|
||||
+ // Paper end
|
||||
try {
|
||||
this.methodProfiler.a(() -> {
|
||||
return String.valueOf(TileEntityTypes.a(tileentity.C()));
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index a8c7e7931e..f7883e7085 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1772,7 +1772,7 @@ public class CraftWorld implements World {
|
||||
ChunkProviderServer cps = world.getChunkProvider();
|
||||
for (net.minecraft.server.Chunk chunk : cps.chunks.values()) {
|
||||
// If in use, skip it
|
||||
- if (isChunkInUse(chunk.locX, chunk.locZ)) {
|
||||
+ if (isChunkInUse(chunk.locX, chunk.locZ) || chunk.scheduledForUnload != null) { // Paper - delayed chunk unloads
|
||||
continue;
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
index d08ef3fe10..081789a8fe 100644
|
||||
--- a/src/main/java/org/spigotmc/ActivationRange.java
|
||||
+++ b/src/main/java/org/spigotmc/ActivationRange.java
|
||||
@@ -323,6 +323,11 @@ public class ActivationRange
|
||||
{
|
||||
isActive = false;
|
||||
}
|
||||
+ // Paper start - Skip ticking in chunks scheduled for unload
|
||||
+ else if (entity.world.paperConfig.skipEntityTickingInChunksScheduledForUnload && (chunk == null || chunk.scheduledForUnload != null)) {
|
||||
+ isActive = false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
return isActive;
|
||||
}
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,58 +0,0 @@
|
||||
From 266fe023d1d38728ba461724a7f2a23a2ee07cfd Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 3 Nov 2016 21:52:22 -0400
|
||||
Subject: [PATCH] Prevent Auto Save if Save Queue is full
|
||||
|
||||
If the save queue already has 50 (configurable) of chunks pending,
|
||||
then avoid processing auto save (which would add more)
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 7e847af00b..9829b3b64b 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -341,6 +341,11 @@ public class PaperWorldConfig {
|
||||
maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24);
|
||||
}
|
||||
|
||||
+ public int queueSizeAutoSaveThreshold = 50;
|
||||
+ private void queueSizeAutoSaveThreshold() {
|
||||
+ queueSizeAutoSaveThreshold = getInt("save-queue-limit-for-auto-save", 50);
|
||||
+ }
|
||||
+
|
||||
public boolean removeCorruptTEs = false;
|
||||
private void removeCorruptTEs() {
|
||||
removeCorruptTEs = getBoolean("remove-corrupt-tile-entities", false);
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index fbc69b5ba5..9b5908a5b4 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -236,6 +236,13 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
synchronized (this.chunkLoader) {
|
||||
ObjectIterator objectiterator = this.chunks.values().iterator();
|
||||
|
||||
+ // Paper start
|
||||
+ final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProvider().chunkLoader;
|
||||
+ final int queueSize = chunkLoader.getQueueSize();
|
||||
+ if (!flag && queueSize > world.paperConfig.queueSizeAutoSaveThreshold){
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
while (objectiterator.hasNext()) {
|
||||
Chunk chunk = (Chunk) objectiterator.next();
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
index a144118f66..adfb5d056f 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
@@ -156,6 +156,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
|
||||
}
|
||||
|
||||
+ public int getQueueSize() { return queue.size(); } // Paper
|
||||
+
|
||||
// CraftBukkit start - Add async variant, provide compatibility
|
||||
@Nullable
|
||||
public Chunk a(GeneratorAccess generatoraccess, int i, int j, Consumer<Chunk> consumer) throws IOException {
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,93 +0,0 @@
|
||||
From 8efbb3a0533a16d6c9e3ac27e41cd03bba1e35d8 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 4 Nov 2016 02:12:10 -0400
|
||||
Subject: [PATCH] Chunk Save Stats Debug Option
|
||||
|
||||
Adds a command line flag to enable stats on how chunk saves are processing.
|
||||
|
||||
Stats on current queue, how many was processed and how many were queued.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 9b5908a5b4..2997767282 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -28,6 +28,11 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
public final LongSet unloadQueue = new LongOpenHashSet();
|
||||
public final ChunkGenerator<?> chunkGenerator;
|
||||
public final IChunkLoader chunkLoader;
|
||||
+ // Paper start - chunk save stats
|
||||
+ private long lastQueuedSaves = 0L; // Paper
|
||||
+ private long lastProcessedSaves = 0L; // Paper
|
||||
+ private long lastSaveStatPrinted = System.currentTimeMillis();
|
||||
+ // Paper end
|
||||
public final Long2ObjectMap<Chunk> chunks = Long2ObjectMaps.synchronize(new ChunkMap(8192));
|
||||
private Chunk lastChunk;
|
||||
private final ChunkTaskScheduler chunkScheduler;
|
||||
@@ -239,6 +244,29 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
// Paper start
|
||||
final ChunkRegionLoader chunkLoader = (ChunkRegionLoader) world.getChunkProvider().chunkLoader;
|
||||
final int queueSize = chunkLoader.getQueueSize();
|
||||
+
|
||||
+ final long now = System.currentTimeMillis();
|
||||
+ final long timeSince = (now - lastSaveStatPrinted) / 1000;
|
||||
+ final Integer printRateSecs = Integer.getInteger("printSaveStats");
|
||||
+ if (printRateSecs != null && timeSince >= printRateSecs) {
|
||||
+ final String timeStr = "/" + timeSince +"s";
|
||||
+ final long queuedSaves = chunkLoader.getQueuedSaves();
|
||||
+ long queuedDiff = queuedSaves - lastQueuedSaves;
|
||||
+ lastQueuedSaves = queuedSaves;
|
||||
+
|
||||
+ final long processedSaves = chunkLoader.getProcessedSaves();
|
||||
+ long processedDiff = processedSaves - lastProcessedSaves;
|
||||
+ lastProcessedSaves = processedSaves;
|
||||
+
|
||||
+ lastSaveStatPrinted = now;
|
||||
+ if (processedDiff > 0 || queueSize > 0 || queuedDiff > 0) {
|
||||
+ System.out.println("[Chunk Save Stats] " + world.worldData.getName() +
|
||||
+ " - Current: " + queueSize +
|
||||
+ " - Queued: " + queuedDiff + timeStr +
|
||||
+ " - Processed: " +processedDiff + timeStr
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
if (!flag && queueSize > world.paperConfig.queueSizeAutoSaveThreshold){
|
||||
return false;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
index adfb5d056f..0fc4d9f520 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||||
@@ -156,7 +156,13 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
|
||||
}
|
||||
|
||||
- public int getQueueSize() { return queue.size(); } // Paper
|
||||
+ // Paper start
|
||||
+ private long queuedSaves = 0;
|
||||
+ private final java.util.concurrent.atomic.AtomicLong processedSaves = new java.util.concurrent.atomic.AtomicLong(0L);
|
||||
+ public int getQueueSize() { return queue.size(); }
|
||||
+ public long getQueuedSaves() { return queuedSaves; }
|
||||
+ public long getProcessedSaves() { return processedSaves.longValue(); }
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start - Add async variant, provide compatibility
|
||||
@Nullable
|
||||
@@ -348,6 +354,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
protected void a(ChunkCoordIntPair chunkcoordintpair, Supplier<NBTTagCompound> nbttagcompound) { // Spigot
|
||||
this.saveMap.put(chunkcoordintpair.asLong(), nbttagcompound); // Paper
|
||||
queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements
|
||||
+ queuedSaves++; // Paper
|
||||
FileIOThread.a().a(this);
|
||||
}
|
||||
|
||||
@@ -375,6 +382,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
|
||||
// Paper end
|
||||
ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements
|
||||
Supplier<NBTTagCompound> nbttagcompound = chunk.compoundSupplier; // Spigot // Paper
|
||||
+ processedSaves.incrementAndGet(); // Paper
|
||||
|
||||
if (nbttagcompound == null) {
|
||||
return true;
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,22 +0,0 @@
|
||||
From 635cfbbdad0af0805e7eadf3de564462628d732f Mon Sep 17 00:00:00 2001
|
||||
From: Michael Himing <mhiming@gmail.com>
|
||||
Date: Sun, 8 Jan 2017 18:50:35 +1100
|
||||
Subject: [PATCH] Fix block break desync
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
index fd8d30e5cb..b34a0fb350 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
|
||||
@@ -1185,6 +1185,8 @@ public class PlayerConnection implements PacketListenerPlayIn {
|
||||
double d3 = d0 * d0 + d1 * d1 + d2 * d2;
|
||||
|
||||
if (d3 > 36.0D) {
|
||||
+ if (worldserver.isChunkLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4)) // Paper - Fix block break desync - Don't send for unloaded chunks
|
||||
+ this.sendPacket(new PacketPlayOutBlockChange(worldserver, blockposition)); // Paper - Fix block break desync
|
||||
return;
|
||||
} else if (blockposition.getY() >= this.minecraftServer.getMaxBuildHeight()) {
|
||||
return;
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,23 +0,0 @@
|
||||
From 16ba1e065d52597408a18d8bbb9fa3686271fc6a Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 2 Jan 2017 16:32:56 -0500
|
||||
Subject: [PATCH] ShulkerBox Dupe Prevention
|
||||
|
||||
This ensures that Shulker Boxes can never drop their contents twice, and
|
||||
that the inventory is cleared incase it some how also got saved to the world.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockShulkerBox.java b/src/main/java/net/minecraft/server/BlockShulkerBox.java
|
||||
index ab0ece557c..997ed795b1 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockShulkerBox.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockShulkerBox.java
|
||||
@@ -100,6 +100,7 @@ public class BlockShulkerBox extends BlockTileEntity {
|
||||
}
|
||||
|
||||
a(world, blockposition, itemstack);
|
||||
+ tileentityshulkerbox.clear(); // Paper - This was intended to be called in Vanilla (is checked in the if statement above if has been called) - Fixes dupe issues
|
||||
}
|
||||
}
|
||||
world.updateAdjacentComparators(blockposition, iblockdata.getBlock());
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,128 +0,0 @@
|
||||
From 1648e767bbdfe53802b2c3a864c74cdaaca6909e Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 5 Jun 2018 00:32:22 -0400
|
||||
Subject: [PATCH] Configurable Villages loading chunks for door checks
|
||||
|
||||
This avoids villages spam loading chunks sync.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 0a270b899d..4727ac6eb5 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -434,4 +434,12 @@ public class PaperWorldConfig {
|
||||
disableEnderpearlExploit = getBoolean("game-mechanics.disable-unloaded-chunk-enderpearl-exploit", disableEnderpearlExploit);
|
||||
log("Disable Unloaded Chunk Enderpearl Exploit: " + (disableEnderpearlExploit ? "enabled" : "disabled"));
|
||||
}
|
||||
+
|
||||
+ public boolean villagesLoadChunks = false;
|
||||
+ private void villagesLoadChunks() {
|
||||
+ villagesLoadChunks = getBoolean("game-mechanics.villages-load-chunks", false);
|
||||
+ if (villagesLoadChunks) {
|
||||
+ log("Villages can load chunks - Warning this can cause intense TPS loss. Strongly consider disabling this.");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/PersistentVillage.java b/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
index 7a9fb97530..e40cd41869 100644
|
||||
--- a/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
+++ b/src/main/java/net/minecraft/server/PersistentVillage.java
|
||||
@@ -136,7 +136,7 @@ public class PersistentVillage extends PersistentBase {
|
||||
for (int j = -4; j < 4; ++j) {
|
||||
for (int k = -16; k < 16; ++k) {
|
||||
blockposition_mutableblockposition.g(blockposition).d(i, j, k);
|
||||
- IBlockData iblockdata = this.world.getType(blockposition_mutableblockposition);
|
||||
+ IBlockData iblockdata = this.world.paperConfig.villagesLoadChunks ? this.world.getType(blockposition_mutableblockposition) : this.world.getTypeIfLoaded(blockposition_mutableblockposition); // Paper
|
||||
|
||||
if (this.a(iblockdata)) {
|
||||
VillageDoor villagedoor = this.c(blockposition_mutableblockposition);
|
||||
@@ -228,7 +228,7 @@ public class PersistentVillage extends PersistentBase {
|
||||
}
|
||||
|
||||
private boolean a(IBlockData iblockdata) {
|
||||
- return iblockdata.getBlock() instanceof BlockDoor && iblockdata.getMaterial() == Material.WOOD;
|
||||
+ return iblockdata != null && iblockdata.getBlock() instanceof BlockDoor && iblockdata.getMaterial() == Material.WOOD; // Paper
|
||||
}
|
||||
|
||||
public void a(NBTTagCompound nbttagcompound) {
|
||||
diff --git a/src/main/java/net/minecraft/server/Village.java b/src/main/java/net/minecraft/server/Village.java
|
||||
index b794572915..1363c53ff0 100644
|
||||
--- a/src/main/java/net/minecraft/server/Village.java
|
||||
+++ b/src/main/java/net/minecraft/server/Village.java
|
||||
@@ -11,10 +11,10 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class Village {
|
||||
|
||||
- private World a;
|
||||
+ private World a; private World getWorld() { return a; } // Paper - OBFHELPER
|
||||
private final List<VillageDoor> b = Lists.newArrayList();
|
||||
private BlockPosition c;
|
||||
- private BlockPosition d;
|
||||
+ private BlockPosition d;private BlockPosition getCenter() { return d; } // Paper - OBFHELPER
|
||||
private int e;
|
||||
private int f;
|
||||
private int g;
|
||||
@@ -44,6 +44,12 @@ public class Village {
|
||||
}
|
||||
|
||||
public void a(int i) {
|
||||
+ // Paper - don't tick village if chunk isn't loaded
|
||||
+ Chunk chunk = getWorld().getChunkIfLoaded(getCenter());
|
||||
+ if (chunk == null || !chunk.areNeighborsLoaded(1)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.g = i;
|
||||
this.m();
|
||||
this.l();
|
||||
@@ -292,6 +298,12 @@ public class Village {
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
VillageDoor villagedoor = (VillageDoor) iterator.next();
|
||||
+ // Paper start - don't remove doors from unloaded chunks
|
||||
+ if (!getWorld().isLoaded(villagedoor.getPosition())) {
|
||||
+ villagedoor.setLastSeen(villagedoor.getLastSeen() + 1);
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (flag1) {
|
||||
villagedoor.a();
|
||||
@@ -312,7 +324,9 @@ public class Village {
|
||||
}
|
||||
|
||||
private boolean g(BlockPosition blockposition) {
|
||||
- IBlockData iblockdata = this.a.getType(blockposition);
|
||||
+ IBlockData iblockdata = this.a.paperConfig.villagesLoadChunks ? this.a.getType(blockposition) : this.a.getTypeIfLoaded(blockposition); // Paper
|
||||
+ if (iblockdata == null) return false; // Paper
|
||||
+
|
||||
Block block = iblockdata.getBlock();
|
||||
|
||||
return block instanceof BlockDoor ? iblockdata.getMaterial() == Material.WOOD : false;
|
||||
diff --git a/src/main/java/net/minecraft/server/VillageDoor.java b/src/main/java/net/minecraft/server/VillageDoor.java
|
||||
index 33ad5faa3e..1edffc4629 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillageDoor.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillageDoor.java
|
||||
@@ -55,6 +55,7 @@ public class VillageDoor {
|
||||
return this.f;
|
||||
}
|
||||
|
||||
+ public BlockPosition getPosition() { return d(); } // Paper - OBFHELPER
|
||||
public BlockPosition d() {
|
||||
return this.a;
|
||||
}
|
||||
@@ -71,10 +72,12 @@ public class VillageDoor {
|
||||
return this.c.getAdjacentZ() * 2;
|
||||
}
|
||||
|
||||
+ public int getLastSeen() { return h(); } // Paper - OBFHELPER
|
||||
public int h() {
|
||||
return this.d;
|
||||
}
|
||||
|
||||
+ public void setLastSeen(int i) { a(i); } // Paper - OBFHELPER
|
||||
public void a(int i) {
|
||||
this.d = i;
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,51 +0,0 @@
|
||||
From 8a4b7bff6950703ef13ea7ce72e80af4cee67d13 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 10 Jun 2018 20:04:42 -0400
|
||||
Subject: [PATCH] Properly remove entities on dimension teleport
|
||||
|
||||
To teleport an entity between dimensions, the server makes a copy
|
||||
and puts the copy in the new location, and marks the old one dead.
|
||||
|
||||
If this method got called for the same world in the same tick,
|
||||
the entity would not have been removed from the UUID map, and the
|
||||
world readd would fail.
|
||||
|
||||
This can be triggered even with a plugin if the entity is teleported
|
||||
twice in the same tick, from world A to B, then back from B to A.
|
||||
|
||||
The re-add to A will fail to add the entity to the world. It will
|
||||
actually be there, but it will not be visible on the client until
|
||||
the server is restarted to re-try the add to world process again.
|
||||
|
||||
This bug was unlikely to be seen by many due to the double teleport
|
||||
requirement, but plugins (such as my own) use this method to
|
||||
trigger a "reload" of the entity on the client.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
|
||||
index 92a15ba947..debab1a715 100644
|
||||
--- a/src/main/java/net/minecraft/server/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/server/Entity.java
|
||||
@@ -2611,7 +2611,7 @@ public abstract class Entity implements INamableTileEntity, ICommandListener, Ke
|
||||
}
|
||||
// CraftBukkit end */
|
||||
|
||||
- this.world.kill(this);
|
||||
+ this.world.removeEntity(this); // Paper - Fully remove entity, can't have dupes in the UUID map
|
||||
this.dead = false;
|
||||
this.world.methodProfiler.enter("reposition");
|
||||
/* CraftBukkit start - Handled in calculateTarget
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index e4730352d3..c08ee62e84 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -997,6 +997,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
}
|
||||
|
||||
protected void c(Entity entity) {
|
||||
+ if (!this.entitiesByUUID.containsKey(entity.getUniqueID()) && !entity.valid) return; // Paper - Already removed, dont fire twice - this looks like it can happen even without our changes
|
||||
super.c(entity);
|
||||
this.entitiesById.d(entity.getId());
|
||||
this.entitiesByUUID.remove(entity.getUniqueID());
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 349376a18c6a86ab6bb07513849d403ab6c71669 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 19 Jul 2018 01:23:00 -0400
|
||||
Subject: [PATCH] Don't process despawn if entity is in a chunk scheduled for
|
||||
unload
|
||||
|
||||
This won't happen anyways if the user has
|
||||
"skip ticking for entities in chunks scheduled for unload" turned on,
|
||||
but if they don't, protect from this instant killing the entity to
|
||||
keep it vanilla in behavior
|
||||
|
||||
a player may teleport away, and trigger instant despawn
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityInsentient.java b/src/main/java/net/minecraft/server/EntityInsentient.java
|
||||
index 98e214cdd6..ee5078370c 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityInsentient.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityInsentient.java
|
||||
@@ -634,6 +634,8 @@ public abstract class EntityInsentient extends EntityLiving {
|
||||
if (this.persistent) {
|
||||
this.ticksFarFromPlayer = 0;
|
||||
} else {
|
||||
+ Chunk currentChunk = getChunkAtLocation(); // Paper
|
||||
+ if (currentChunk != null && currentChunk.scheduledForUnload != null) return; // Paper
|
||||
EntityHuman entityhuman = this.world.findNearbyPlayer(this, -1.0D);
|
||||
|
||||
if (entityhuman != null && entityhuman.affectsSpawning) { // Paper - Affects Spawning API
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,81 +0,0 @@
|
||||
From c630ddd10b4711ffcd5318829821fb44f48294df Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 29 Aug 2018 21:59:22 -0400
|
||||
Subject: [PATCH] Optimize getChunkIfLoaded type calls
|
||||
|
||||
Uses optimized check to avoid major locks and large method.
|
||||
|
||||
Will improve inlining across many hot methods.
|
||||
|
||||
Improve getBrightness to not do double chunk map lookups.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
index 41926a361b..186cfda7e4 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -379,7 +379,7 @@ public class ChunkProviderServer implements IChunkProvider {
|
||||
continue;
|
||||
}
|
||||
|
||||
- Chunk neighbor = this.getChunkAt(chunk.locX + x, chunk.locZ + z, false, false);
|
||||
+ Chunk neighbor = this.chunks.get(chunk.chunkKey); // Paper
|
||||
if (neighbor != null) {
|
||||
neighbor.setNeighborUnloaded(-x, -z);
|
||||
chunk.setNeighborUnloaded(x, z);
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 14f419deb8..630ebfb37c 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -162,7 +162,7 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
}
|
||||
|
||||
public Chunk getChunkIfLoaded(int x, int z) {
|
||||
- return ((ChunkProviderServer) this.chunkProvider).getChunkAt(x, z, false, false);
|
||||
+ return ((ChunkProviderServer) this.chunkProvider).chunks.get(ChunkCoordIntPair.a(x, z)); // Paper - optimize getChunkIfLoaded
|
||||
}
|
||||
|
||||
protected World(IDataManager idatamanager, @Nullable PersistentCollection persistentcollection, WorldData worlddata, WorldProvider worldprovider, MethodProfiler methodprofiler, boolean flag, ChunkGenerator gen, org.bukkit.World.Environment env) {
|
||||
@@ -724,7 +724,8 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
blockposition = new BlockPosition(blockposition.getX(), 0, blockposition.getZ());
|
||||
}
|
||||
|
||||
- return !blockposition.isValidLocation() ? enumskyblock.c : (!this.isLoaded(blockposition) ? enumskyblock.c : this.getChunkAtWorldCoords(blockposition).getBrightness(enumskyblock, blockposition)); // Paper
|
||||
+ Chunk chunk; // Paper
|
||||
+ return !blockposition.isValidLocation() ? enumskyblock.c : ((chunk = this.getChunkIfLoaded(blockposition)) == null ? enumskyblock.c : chunk.getBrightness(enumskyblock, blockposition)); // Paper - optimize ifChunkLoaded
|
||||
}
|
||||
|
||||
public void a(EnumSkyBlock enumskyblock, BlockPosition blockposition, int i) {
|
||||
@@ -1959,7 +1960,7 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
if (blockposition.isInvalidYLocation()) { // Paper
|
||||
return false;
|
||||
} else {
|
||||
- Chunk chunk = this.chunkProvider.getChunkAt(blockposition.getX() >> 4, blockposition.getZ() >> 4, false, false);
|
||||
+ Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4); // Paper - optimize ifLoaded
|
||||
|
||||
return chunk != null && !chunk.isEmpty();
|
||||
}
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 72eb8ed4f4..7e52859c1d 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -218,7 +218,7 @@ public class CraftWorld implements World {
|
||||
return false;
|
||||
}
|
||||
|
||||
- net.minecraft.server.Chunk chunk = world.getChunkProvider().getChunkAt(x, z, false, false);
|
||||
+ net.minecraft.server.Chunk chunk = world.getChunkIfLoaded(x, z); // Paper - optimize ifLaoded
|
||||
if (chunk != null) {
|
||||
world.getChunkProvider().unload(chunk);
|
||||
}
|
||||
@@ -237,7 +237,7 @@ public class CraftWorld implements World {
|
||||
|
||||
private boolean unloadChunk0(int x, int z, boolean save) {
|
||||
Boolean result = MCUtil.ensureMain("Unload Chunk", () -> { // Paper - Ensure never async
|
||||
- net.minecraft.server.Chunk chunk = world.getChunkProvider().getChunkAt(x, z, false, false);
|
||||
+ net.minecraft.server.Chunk chunk = world.getChunkIfLoaded(x, z); // Paper - optimize ifLoaded
|
||||
if (chunk == null) {
|
||||
return true;
|
||||
}
|
||||
--
|
||||
2.21.0
|
||||
|
Datei-Diff unterdrückt, da er zu groß ist
Diff laden
@ -1,52 +0,0 @@
|
||||
From 68d53d355f81300b2cbd41c12ef16efe87a3d8fb Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 28 Sep 2018 20:46:29 -0400
|
||||
Subject: [PATCH] Optimize Light Recalculations
|
||||
|
||||
Optimizes to not repeatedly look up the same chunk for
|
||||
light lookups.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index 4f64072a7b..966879a894 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -353,7 +353,7 @@ public class Chunk implements IChunkAccess {
|
||||
private void a(int i, int j, int k, int l) {
|
||||
if (l > k && this.areNeighborsLoaded(1)) { // Paper
|
||||
for (int i1 = k; i1 < l; ++i1) {
|
||||
- this.world.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
|
||||
+ this.world.updateBrightness(EnumSkyBlock.SKY, new BlockPosition(i, i1, j), this); // Paper
|
||||
}
|
||||
|
||||
this.x = true;
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 97a0fbd55c..fb71879ac0 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -591,8 +591,9 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
}
|
||||
|
||||
if (this.worldProvider.g()) {
|
||||
- for (i1 = k; i1 <= l; ++i1) {
|
||||
- this.c(EnumSkyBlock.SKY, new BlockPosition(i, i1, j));
|
||||
+ Chunk chunk = getChunkIfLoaded(i >> 4, j >> 4); // Paper
|
||||
+ for (i1 = k; chunk != null && i1 <= l; ++i1) { // Paper
|
||||
+ this.updateBrightness(EnumSkyBlock.SKY, new BlockPosition(i, i1, j), chunk); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2220,6 +2221,11 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition) {
|
||||
// CraftBukkit start - Use neighbor cache instead of looking up
|
||||
Chunk chunk = this.getChunkIfLoaded(blockposition.getX() >> 4, blockposition.getZ() >> 4);
|
||||
+ // Paper start - optimize light updates where chunk is known
|
||||
+ return updateBrightness(enumskyblock, blockposition, chunk);
|
||||
+ }
|
||||
+ public boolean updateBrightness(EnumSkyBlock enumskyblock, BlockPosition blockposition, Chunk chunk) {
|
||||
+ // Paper end
|
||||
if (chunk == null || !chunk.areNeighborsLoaded(1) /*!this.areChunksLoaded(blockposition, 17, false)*/) {
|
||||
// CraftBukkit end
|
||||
return false;
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,66 +0,0 @@
|
||||
From 07a00d527e871eadaf4a96af5ad367ddcbfa9cc3 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 29 Sep 2018 01:18:16 -0400
|
||||
Subject: [PATCH] Fix Sending Chunks to Client
|
||||
|
||||
Vanilla has some screwy logic that doesn't send a chunk until
|
||||
it has been post processed. This is an issue as post processing
|
||||
doesn't occur until all neighbor chunks have been loaded.
|
||||
|
||||
This can reduce view distance while generating terrain, but also
|
||||
cause bugs where chunks are never sent to the client.
|
||||
|
||||
This fix always sends chunks to the client, and simply updates
|
||||
the client anytime post processing is triggered with the new chunk data.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||||
index 0d51c1baeb..46804203fe 100644
|
||||
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||||
@@ -1190,7 +1190,7 @@ public class Chunk implements IChunkAccess {
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
- return this.C.a(ChunkStatus.POSTPROCESSED);
|
||||
+ return true; // Paper - Always send chunks
|
||||
}
|
||||
|
||||
public boolean v() {
|
||||
@@ -1428,6 +1428,13 @@ public class Chunk implements IChunkAccess {
|
||||
this.h.clear();
|
||||
this.a(ChunkStatus.POSTPROCESSED);
|
||||
this.m.a(this);
|
||||
+ // Paper start - resend chunk after post process
|
||||
+ PlayerChunk playerChunk = ((WorldServer) world).getPlayerChunkMap().getChunk(locX, locZ);
|
||||
+ if (playerChunk != null) {
|
||||
+ playerChunk.done = false;
|
||||
+ playerChunk.sendAll();
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index e4cf8548d3..ac5d158093 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -20,7 +20,7 @@ public class PlayerChunk {
|
||||
private int dirtyCount;
|
||||
private int h;
|
||||
private long i;
|
||||
- private boolean done;
|
||||
+ boolean done; // Paper - package-private
|
||||
boolean chunkExists; // Paper
|
||||
// Paper start
|
||||
PaperAsyncChunkProvider.CancellableChunkRequest chunkRequest;
|
||||
@@ -147,6 +147,7 @@ public class PlayerChunk {
|
||||
}
|
||||
}
|
||||
|
||||
+ public boolean sendAll() { return b(); } // Paper - OBFHELPER
|
||||
public boolean b() {
|
||||
if (this.done) {
|
||||
return true;
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 4e5812633b869d071215da93dc3cffd797de9951 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Wed, 3 Oct 2018 19:04:53 +0100
|
||||
Subject: [PATCH] Fix FileIOThread concurrency issues
|
||||
|
||||
FileIOThread was using two volatile counters in order to track if
|
||||
any pending work was in the queue, this causes potential concurrency
|
||||
issues when this counter is updated from multiple threads, potentially
|
||||
causing these counters to desync due to the unsafe volatile update
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
index 3c688f546c..570624600d 100644
|
||||
--- a/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
+++ b/src/main/java/net/minecraft/server/FileIOThread.java
|
||||
@@ -10,7 +10,7 @@ public class FileIOThread implements Runnable {
|
||||
|
||||
private static final Logger a = LogManager.getLogger();
|
||||
private static final FileIOThread b = new FileIOThread();
|
||||
- private final List<IAsyncChunkSaver> c = Collections.synchronizedList(Lists.newArrayList());
|
||||
+ private final List<IAsyncChunkSaver> c = Collections.synchronizedList(Lists.newArrayList()); private List<IAsyncChunkSaver> getThreadedIOQueue() { return c; } // Paper - OBFHELPER
|
||||
private volatile long d;
|
||||
private volatile long e;
|
||||
private volatile boolean f;
|
||||
@@ -75,7 +75,7 @@ public class FileIOThread implements Runnable {
|
||||
public void b() throws InterruptedException {
|
||||
this.f = true;
|
||||
|
||||
- while (this.d != this.e) {
|
||||
+ while(!this.getThreadedIOQueue().isEmpty()) { // Paper - check actual list size
|
||||
Thread.sleep(10L);
|
||||
}
|
||||
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,66 +0,0 @@
|
||||
From a576811cfbd84b86003b6d81569f8e4399447a10 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 29 Mar 2019 01:25:11 -0400
|
||||
Subject: [PATCH] Optimize Persistent Data Loading
|
||||
|
||||
removes Mineshaft loading legacy as we had pre 1.13.2 to avoid managing
|
||||
that very large data file from legacy systems.
|
||||
|
||||
Previous to 1.13.2 these data files were never loaded to begin with, so they
|
||||
effectively do not contain valid/relevant data.
|
||||
|
||||
These files take a long time to convert on large worlds and crashes the server.
|
||||
|
||||
Additionally, cache the result of a file being missing so we don't keep spam checking it.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldPersistentData.java b/src/main/java/net/minecraft/server/WorldPersistentData.java
|
||||
index 00e9a17355..153809432c 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldPersistentData.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldPersistentData.java
|
||||
@@ -26,6 +26,7 @@ public class WorldPersistentData {
|
||||
this.c = datafixer;
|
||||
this.d = file;
|
||||
}
|
||||
+ private static final PersistentBase NO_RESULT = new ForcedChunk(); // Paper
|
||||
|
||||
private File a(String s) {
|
||||
return new File(this.d, s + ".dat");
|
||||
@@ -46,14 +47,17 @@ public class WorldPersistentData {
|
||||
|
||||
@Nullable
|
||||
public <T extends PersistentBase> T b(Supplier<T> supplier, String s) {
|
||||
+ if ("Mineshaft_index".equals(s) || "Mineshaft".equals(s)) return null; // Paper - mineshaft is useless data
|
||||
T persistentbase = (T) this.data.get(s); // Paper - decompile fix
|
||||
|
||||
if (persistentbase == null && !this.data.containsKey(s)) {
|
||||
persistentbase = this.c(supplier, s);
|
||||
this.data.put(s, persistentbase);
|
||||
+ } else { // Paper
|
||||
+ this.data.put(s, NO_RESULT); // Paper
|
||||
}
|
||||
|
||||
- return persistentbase;
|
||||
+ return persistentbase == NO_RESULT ? null : persistentbase; // Paper
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -66,7 +70,7 @@ public class WorldPersistentData {
|
||||
NBTTagCompound nbttagcompound = this.a(s, SharedConstants.a().getWorldVersion());
|
||||
|
||||
t0.a(nbttagcompound.getCompound("data"));
|
||||
- return t0;
|
||||
+ return t0 == NO_RESULT ? null : t0; // Paper
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
WorldPersistentData.LOGGER.error("Error loading saved data: {}", s, exception);
|
||||
@@ -80,6 +84,7 @@ public class WorldPersistentData {
|
||||
}
|
||||
|
||||
public NBTTagCompound a(String s, int i) throws IOException {
|
||||
+ if ("Mineshaft".equals(s) || "Mineshaft_index".equals(s)) return new NBTTagCompound(); // Paper
|
||||
File file = this.a(s);
|
||||
PushbackInputStream pushbackinputstream = new PushbackInputStream(new FileInputStream(file), 2);
|
||||
Throwable throwable = null;
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,872 +0,0 @@
|
||||
From a7f8efc50ad709eeb7991d8a460ed6075115175d Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Thu, 4 Oct 2018 10:08:02 -0500
|
||||
Subject: [PATCH] Use EntityTypes for living entities
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockMonsterEggs.java b/src/main/java/net/minecraft/server/BlockMonsterEggs.java
|
||||
index 5a0cc6d058..d385f647e7 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockMonsterEggs.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockMonsterEggs.java
|
||||
@@ -35,7 +35,7 @@ public class BlockMonsterEggs extends Block {
|
||||
|
||||
public void dropNaturally(IBlockData iblockdata, World world, BlockPosition blockposition, float f, int i) {
|
||||
if (!world.isClientSide && world.getGameRules().getBoolean("doTileDrops")) {
|
||||
- EntitySilverfish entitysilverfish = new EntitySilverfish(world);
|
||||
+ EntitySilverfish entitysilverfish = EntityTypes.SILVERFISH.create(world); // Paper
|
||||
|
||||
entitysilverfish.setPositionRotation((double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, 0.0F, 0.0F);
|
||||
world.addEntity(entitysilverfish, SpawnReason.SILVERFISH_BLOCK); // CraftBukkit - add SpawnReason
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockPumpkinCarved.java b/src/main/java/net/minecraft/server/BlockPumpkinCarved.java
|
||||
index 75622fbdf8..2653699840 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockPumpkinCarved.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockPumpkinCarved.java
|
||||
@@ -52,7 +52,7 @@ public class BlockPumpkinCarved extends BlockFacingHorizontal {
|
||||
blockList.setTypeAndData(shapedetectorblock1.getPosition(), Blocks.AIR.getBlockData(), 2); // CraftBukkit
|
||||
}
|
||||
|
||||
- EntitySnowman entitysnowman = new EntitySnowman(world);
|
||||
+ EntitySnowman entitysnowman = EntityTypes.SNOW_GOLEM.create(world); // Paper
|
||||
BlockPosition blockposition1 = shapedetector_shapedetectorcollection.a(0, 2, 0).getPosition();
|
||||
|
||||
entitysnowman.setPositionRotation((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.05D, (double) blockposition1.getZ() + 0.5D, 0.0F, 0.0F);
|
||||
@@ -87,7 +87,7 @@ public class BlockPumpkinCarved extends BlockFacingHorizontal {
|
||||
}
|
||||
|
||||
BlockPosition blockposition2 = shapedetector_shapedetectorcollection.a(1, 2, 0).getPosition();
|
||||
- EntityIronGolem entityirongolem = new EntityIronGolem(world);
|
||||
+ EntityIronGolem entityirongolem = EntityTypes.IRON_GOLEM.create(world); // Paper
|
||||
|
||||
entityirongolem.setPlayerCreated(true);
|
||||
entityirongolem.setPositionRotation((double) blockposition2.getX() + 0.5D, (double) blockposition2.getY() + 0.05D, (double) blockposition2.getZ() + 0.5D, 0.0F, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockTurtleEgg.java b/src/main/java/net/minecraft/server/BlockTurtleEgg.java
|
||||
index 0f0872c1e0..1c1bf85a0e 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockTurtleEgg.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockTurtleEgg.java
|
||||
@@ -94,7 +94,7 @@ public class BlockTurtleEgg extends Block {
|
||||
if (!world.isClientSide) {
|
||||
for (int j = 0; j < (Integer) iblockdata.get(BlockTurtleEgg.b); ++j) {
|
||||
world.triggerEffect(2001, blockposition, Block.getCombinedId(iblockdata));
|
||||
- EntityTurtle entityturtle = new EntityTurtle(world);
|
||||
+ EntityTurtle entityturtle = EntityTypes.TURTLE.create(world); // Paper
|
||||
|
||||
entityturtle.setAgeRaw(-24000);
|
||||
entityturtle.g(blockposition);
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockWitherSkull.java b/src/main/java/net/minecraft/server/BlockWitherSkull.java
|
||||
index 93bf32dc1a..e6063bb462 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockWitherSkull.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockWitherSkull.java
|
||||
@@ -52,7 +52,7 @@ public class BlockWitherSkull extends BlockSkull {
|
||||
}
|
||||
|
||||
BlockPosition blockposition1 = shapedetector_shapedetectorcollection.a(1, 0, 0).getPosition();
|
||||
- EntityWither entitywither = new EntityWither(world);
|
||||
+ EntityWither entitywither = EntityTypes.WITHER.create(world); // Paper
|
||||
BlockPosition blockposition2 = shapedetector_shapedetectorcollection.a(1, 2, 0).getPosition();
|
||||
|
||||
entitywither.setPositionRotation((double) blockposition2.getX() + 0.5D, (double) blockposition2.getY() + 0.55D, (double) blockposition2.getZ() + 0.5D, shapedetector_shapedetectorcollection.getFacing().k() == EnumDirection.EnumAxis.X ? 0.0F : 90.0F, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/EnderDragonBattle.java b/src/main/java/net/minecraft/server/EnderDragonBattle.java
|
||||
index aad7ce93f6..09eabf1235 100644
|
||||
--- a/src/main/java/net/minecraft/server/EnderDragonBattle.java
|
||||
+++ b/src/main/java/net/minecraft/server/EnderDragonBattle.java
|
||||
@@ -412,7 +412,7 @@ public class EnderDragonBattle {
|
||||
|
||||
private EntityEnderDragon n() {
|
||||
this.d.getChunkAtWorldCoords(new BlockPosition(0, 128, 0));
|
||||
- EntityEnderDragon entityenderdragon = new EntityEnderDragon(this.d);
|
||||
+ EntityEnderDragon entityenderdragon = EntityTypes.ENDER_DRAGON.create(this.d); // Paper
|
||||
|
||||
entityenderdragon.getDragonControllerManager().setControllerPhase(DragonControllerPhase.HOLDING_PATTERN);
|
||||
entityenderdragon.setPositionRotation(0.0D, 128.0D, 0.0D, this.d.random.nextFloat() * 360.0F, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityChicken.java b/src/main/java/net/minecraft/server/EntityChicken.java
|
||||
index ee159e0a81..070a9e7b14 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityChicken.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityChicken.java
|
||||
@@ -96,7 +96,7 @@ public class EntityChicken extends EntityAnimal {
|
||||
}
|
||||
|
||||
public EntityChicken createChild(EntityAgeable entityageable) {
|
||||
- return new EntityChicken(this.world);
|
||||
+ return EntityTypes.CHICKEN.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean f(ItemStack itemstack) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityCow.java b/src/main/java/net/minecraft/server/EntityCow.java
|
||||
index 5874d2993c..cc53e915d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityCow.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityCow.java
|
||||
@@ -88,7 +88,7 @@ public class EntityCow extends EntityAnimal {
|
||||
}
|
||||
|
||||
public EntityCow createChild(EntityAgeable entityageable) {
|
||||
- return new EntityCow(this.world);
|
||||
+ return EntityTypes.COW.create(world); // Paper
|
||||
}
|
||||
|
||||
public float getHeadHeight() {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityEnderPearl.java b/src/main/java/net/minecraft/server/EntityEnderPearl.java
|
||||
index 961afa5c42..a372f6508f 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityEnderPearl.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityEnderPearl.java
|
||||
@@ -74,7 +74,7 @@ public class EntityEnderPearl extends EntityProjectile {
|
||||
|
||||
if (!teleEvent.isCancelled() && !entityplayer.playerConnection.isDisconnected()) {
|
||||
if (this.random.nextFloat() < 0.05F && this.world.getGameRules().getBoolean("doMobSpawning")) {
|
||||
- EntityEndermite entityendermite = new EntityEndermite(this.world);
|
||||
+ EntityEndermite entityendermite = EntityTypes.ENDERMITE.create(world); // Paper
|
||||
|
||||
entityendermite.setPlayerSpawned(true);
|
||||
entityendermite.setPositionRotation(entityliving.locX, entityliving.locY, entityliving.locZ, entityliving.yaw, entityliving.pitch);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityEvoker.java b/src/main/java/net/minecraft/server/EntityEvoker.java
|
||||
index 963b6fbb9c..fc20bbe272 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityEvoker.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityEvoker.java
|
||||
@@ -188,8 +188,7 @@ public class EntityEvoker extends EntityIllagerWizard {
|
||||
protected void j() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
BlockPosition blockposition = (new BlockPosition(EntityEvoker.this)).a(-2 + EntityEvoker.this.random.nextInt(5), 1, -2 + EntityEvoker.this.random.nextInt(5));
|
||||
- EntityVex entityvex = new EntityVex(EntityEvoker.this.world);
|
||||
-
|
||||
+ EntityVex entityvex = EntityTypes.VEX.create(EntityEvoker.this.world); // Paper
|
||||
entityvex.setPositionRotation(blockposition, 0.0F, 0.0F);
|
||||
entityvex.prepare(EntityEvoker.this.world.getDamageScaler(blockposition), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
entityvex.a((EntityInsentient) EntityEvoker.this);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityHorse.java b/src/main/java/net/minecraft/server/EntityHorse.java
|
||||
index 4e8a97c557..1b9425f3e6 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityHorse.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityHorse.java
|
||||
@@ -208,11 +208,11 @@ public class EntityHorse extends EntityHorseAbstract {
|
||||
Object object;
|
||||
|
||||
if (entityageable instanceof EntityHorseDonkey) {
|
||||
- object = new EntityHorseMule(this.world);
|
||||
+ object = EntityTypes.MULE.create(world); // Paper
|
||||
} else {
|
||||
EntityHorse entityhorse = (EntityHorse) entityageable;
|
||||
|
||||
- object = new EntityHorse(this.world);
|
||||
+ object = EntityTypes.HORSE.create(world); // Paper
|
||||
int i = this.random.nextInt(9);
|
||||
int j;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityHorseDonkey.java b/src/main/java/net/minecraft/server/EntityHorseDonkey.java
|
||||
index 72eed22eb9..65c40e72bf 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityHorseDonkey.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityHorseDonkey.java
|
||||
@@ -33,7 +33,7 @@ public class EntityHorseDonkey extends EntityHorseChestedAbstract {
|
||||
}
|
||||
|
||||
public EntityAgeable createChild(EntityAgeable entityageable) {
|
||||
- Object object = entityageable instanceof EntityHorse ? new EntityHorseMule(this.world) : new EntityHorseDonkey(this.world);
|
||||
+ Object object = entityageable instanceof EntityHorse ? EntityTypes.MULE.create(world) : EntityTypes.DONKEY.create(world); // Paper
|
||||
|
||||
this.a(entityageable, (EntityHorseAbstract) object);
|
||||
return (EntityAgeable) object;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java
|
||||
index eae2b26655..0a092acdfe 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityHorseSkeleton.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityHorseSkeleton.java
|
||||
@@ -134,7 +134,7 @@ public class EntityHorseSkeleton extends EntityHorseAbstract {
|
||||
|
||||
@Nullable
|
||||
public EntityAgeable createChild(EntityAgeable entityageable) {
|
||||
- return new EntityHorseSkeleton(this.world);
|
||||
+ return EntityTypes.SKELETON_HORSE.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean a(EntityHuman entityhuman, EnumHand enumhand) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityHorseZombie.java b/src/main/java/net/minecraft/server/EntityHorseZombie.java
|
||||
index c23bc72fc8..a1873f557c 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityHorseZombie.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityHorseZombie.java
|
||||
@@ -41,7 +41,7 @@ public class EntityHorseZombie extends EntityHorseAbstract {
|
||||
|
||||
@Nullable
|
||||
public EntityAgeable createChild(EntityAgeable entityageable) {
|
||||
- return new EntityHorseZombie(this.world);
|
||||
+ return EntityTypes.ZOMBIE_HORSE.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean a(EntityHuman entityhuman, EnumHand enumhand) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityLlama.java b/src/main/java/net/minecraft/server/EntityLlama.java
|
||||
index 5e19768710..82a32c61ed 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityLlama.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityLlama.java
|
||||
@@ -285,7 +285,7 @@ public class EntityLlama extends EntityHorseChestedAbstract implements IRangedEn
|
||||
}
|
||||
|
||||
public EntityLlama createChild(EntityAgeable entityageable) {
|
||||
- EntityLlama entityllama = new EntityLlama(this.world);
|
||||
+ EntityLlama entityllama = EntityTypes.LLAMA.create(world); // Paper
|
||||
|
||||
this.a(entityageable, (EntityHorseAbstract) entityllama);
|
||||
EntityLlama entityllama1 = (EntityLlama) entityageable;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityMushroomCow.java b/src/main/java/net/minecraft/server/EntityMushroomCow.java
|
||||
index dde9f1e61e..638dbe978d 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityMushroomCow.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityMushroomCow.java
|
||||
@@ -40,7 +40,7 @@ public class EntityMushroomCow extends EntityCow {
|
||||
this.world.addParticle(Particles.u, this.locX, this.locY + (double) (this.length / 2.0F), this.locZ, 0.0D, 0.0D, 0.0D);
|
||||
if (!this.world.isClientSide) {
|
||||
// this.die(); // CraftBukkit - moved down
|
||||
- EntityCow entitycow = new EntityCow(this.world);
|
||||
+ EntityCow entitycow = EntityTypes.COW.create(world); // Paper
|
||||
|
||||
entitycow.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
|
||||
entitycow.setHealth(this.getHealth());
|
||||
@@ -74,7 +74,7 @@ public class EntityMushroomCow extends EntityCow {
|
||||
}
|
||||
|
||||
public EntityMushroomCow createChild(EntityAgeable entityageable) {
|
||||
- return new EntityMushroomCow(this.world);
|
||||
+ return EntityTypes.MOOSHROOM.create(world); // Paper
|
||||
}
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityOcelot.java b/src/main/java/net/minecraft/server/EntityOcelot.java
|
||||
index ba074c10c6..13c84bda84 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityOcelot.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityOcelot.java
|
||||
@@ -154,7 +154,7 @@ public class EntityOcelot extends EntityTameableAnimal {
|
||||
}
|
||||
|
||||
public EntityOcelot createChild(EntityAgeable entityageable) {
|
||||
- EntityOcelot entityocelot = new EntityOcelot(this.world);
|
||||
+ EntityOcelot entityocelot = EntityTypes.OCELOT.create(world); // Paper
|
||||
|
||||
if (this.isTamed()) {
|
||||
entityocelot.setOwnerUUID(this.getOwnerUUID());
|
||||
@@ -237,7 +237,7 @@ public class EntityOcelot extends EntityTameableAnimal {
|
||||
groupdataentity = super.prepare(difficultydamagescaler, groupdataentity, nbttagcompound);
|
||||
if (spawnBonus && this.getCatType() == 0 && this.world.random.nextInt(7) == 0) { // Spigot
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
- EntityOcelot entityocelot = new EntityOcelot(this.world);
|
||||
+ EntityOcelot entityocelot = EntityTypes.OCELOT.create(world); // Paper
|
||||
|
||||
entityocelot.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
|
||||
entityocelot.setAgeRaw(-24000);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java
|
||||
index 9dc2d8be27..d1689dc33a 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPig.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPig.java
|
||||
@@ -153,7 +153,7 @@ public class EntityPig extends EntityAnimal {
|
||||
|
||||
public void onLightningStrike(EntityLightning entitylightning) {
|
||||
if (!this.world.isClientSide && !this.dead) {
|
||||
- EntityPigZombie entitypigzombie = new EntityPigZombie(this.world);
|
||||
+ EntityPigZombie entitypigzombie = EntityTypes.ZOMBIE_PIGMAN.create(world); // Paper
|
||||
|
||||
entitypigzombie.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD));
|
||||
entitypigzombie.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
|
||||
@@ -242,7 +242,7 @@ public class EntityPig extends EntityAnimal {
|
||||
}
|
||||
|
||||
public EntityPig createChild(EntityAgeable entityageable) {
|
||||
- return new EntityPig(this.world);
|
||||
+ return EntityTypes.PIG.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean f(ItemStack itemstack) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPolarBear.java b/src/main/java/net/minecraft/server/EntityPolarBear.java
|
||||
index a02020d5fc..dbb534c9cd 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPolarBear.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPolarBear.java
|
||||
@@ -18,7 +18,7 @@ public class EntityPolarBear extends EntityAnimal {
|
||||
}
|
||||
|
||||
public EntityAgeable createChild(EntityAgeable entityageable) {
|
||||
- return new EntityPolarBear(this.world);
|
||||
+ return EntityTypes.POLAR_BEAR.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean f(ItemStack itemstack) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityRabbit.java b/src/main/java/net/minecraft/server/EntityRabbit.java
|
||||
index e545b1c9b3..d6bac06a7a 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityRabbit.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityRabbit.java
|
||||
@@ -251,7 +251,7 @@ public class EntityRabbit extends EntityAnimal {
|
||||
}
|
||||
|
||||
public EntityRabbit createChild(EntityAgeable entityageable) {
|
||||
- EntityRabbit entityrabbit = new EntityRabbit(this.world);
|
||||
+ EntityRabbit entityrabbit = EntityTypes.RABBIT.create(world); // Paper
|
||||
int i = this.dJ();
|
||||
|
||||
if (this.random.nextInt(20) != 0) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntitySheep.java b/src/main/java/net/minecraft/server/EntitySheep.java
|
||||
index f7a25c1483..c35d1eef43 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntitySheep.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntitySheep.java
|
||||
@@ -247,7 +247,7 @@ public class EntitySheep extends EntityAnimal {
|
||||
|
||||
public EntitySheep createChild(EntityAgeable entityageable) {
|
||||
EntitySheep entitysheep = (EntitySheep) entityageable;
|
||||
- EntitySheep entitysheep1 = new EntitySheep(this.world);
|
||||
+ EntitySheep entitysheep1 = EntityTypes.SHEEP.create(world); // Paper
|
||||
|
||||
entitysheep1.setColor(this.a((EntityAnimal) this, (EntityAnimal) entitysheep));
|
||||
return entitysheep1;
|
||||
diff --git a/src/main/java/net/minecraft/server/EntitySpider.java b/src/main/java/net/minecraft/server/EntitySpider.java
|
||||
index a42b8d554f..9ef1c9baf2 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntitySpider.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntitySpider.java
|
||||
@@ -111,7 +111,7 @@ public class EntitySpider extends EntityMonster {
|
||||
Object object = super.prepare(difficultydamagescaler, groupdataentity, nbttagcompound);
|
||||
|
||||
if (this.world.random.nextInt(100) == 0) {
|
||||
- EntitySkeleton entityskeleton = new EntitySkeleton(this.world);
|
||||
+ EntitySkeleton entityskeleton = EntityTypes.SKELETON.create(world); // Paper
|
||||
|
||||
entityskeleton.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
|
||||
entityskeleton.prepare(difficultydamagescaler, (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTurtle.java b/src/main/java/net/minecraft/server/EntityTurtle.java
|
||||
index a533e0eb5b..270b950820 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTurtle.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTurtle.java
|
||||
@@ -218,7 +218,7 @@ public class EntityTurtle extends EntityAnimal {
|
||||
|
||||
@Nullable
|
||||
public EntityAgeable createChild(EntityAgeable entityageable) {
|
||||
- return new EntityTurtle(this.world);
|
||||
+ return EntityTypes.TURTLE.create(world); // Paper
|
||||
}
|
||||
|
||||
public boolean f(ItemStack itemstack) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
index d74bfa1201..24ca351194 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
|
||||
@@ -269,6 +269,7 @@ public class EntityTypes<T extends Entity> {
|
||||
return this.aX;
|
||||
}
|
||||
|
||||
+ @Nullable public T create(World world) { return a(world); } // Paper - OBFHELPER
|
||||
@Nullable
|
||||
public T a(World world) {
|
||||
return this.aT.apply(world); // CraftBukkit - decompile error
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityVillager.java b/src/main/java/net/minecraft/server/EntityVillager.java
|
||||
index f01e776fe5..40b3ffd8ca 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityVillager.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityVillager.java
|
||||
@@ -592,7 +592,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant {
|
||||
}
|
||||
|
||||
public EntityVillager createChild(EntityAgeable entityageable) {
|
||||
- EntityVillager entityvillager = new EntityVillager(this.world);
|
||||
+ EntityVillager entityvillager = EntityTypes.VILLAGER.create(world); // Paper
|
||||
|
||||
entityvillager.prepare(this.world.getDamageScaler(new BlockPosition(entityvillager)), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
return entityvillager;
|
||||
@@ -604,7 +604,7 @@ public class EntityVillager extends EntityAgeable implements NPC, IMerchant {
|
||||
|
||||
public void onLightningStrike(EntityLightning entitylightning) {
|
||||
if (!this.world.isClientSide && !this.dead) {
|
||||
- EntityWitch entitywitch = new EntityWitch(this.world);
|
||||
+ EntityWitch entitywitch = EntityTypes.WITCH.create(world); // Paper
|
||||
|
||||
// Paper start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityZapEvent(this, entitylightning, entitywitch).isCancelled()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityWolf.java b/src/main/java/net/minecraft/server/EntityWolf.java
|
||||
index 4f1696d018..46d8e0a1f4 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityWolf.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityWolf.java
|
||||
@@ -342,7 +342,7 @@ public class EntityWolf extends EntityTameableAnimal {
|
||||
}
|
||||
|
||||
public EntityWolf createChild(EntityAgeable entityageable) {
|
||||
- EntityWolf entitywolf = new EntityWolf(this.world);
|
||||
+ EntityWolf entitywolf = EntityTypes.WOLF.create(world); // Paper
|
||||
UUID uuid = this.getOwnerUUID();
|
||||
|
||||
if (uuid != null) {
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
index 7998b80c17..81cc0c3b33 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityZombie.java
|
||||
@@ -208,7 +208,7 @@ public class EntityZombie extends EntityMonster {
|
||||
}
|
||||
|
||||
protected void dE() {
|
||||
- this.a((EntityZombie) (new EntityDrowned(this.world)));
|
||||
+ this.a((EntityZombie) EntityTypes.DROWNED.create(world)); // Paper
|
||||
this.world.a((EntityHuman) null, 1040, new BlockPosition((int) this.locX, (int) this.locY, (int) this.locZ), 0);
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ public class EntityZombie extends EntityMonster {
|
||||
int i = MathHelper.floor(this.locX);
|
||||
int j = MathHelper.floor(this.locY);
|
||||
int k = MathHelper.floor(this.locZ);
|
||||
- EntityZombie entityzombie = new EntityZombie(this.world);
|
||||
+ EntityZombie entityzombie = EntityTypes.ZOMBIE.create(world); // Paper
|
||||
|
||||
for (int l = 0; l < 50; ++l) {
|
||||
int i1 = i + MathHelper.nextInt(this.random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
|
||||
@@ -385,7 +385,7 @@ public class EntityZombie extends EntityMonster {
|
||||
}
|
||||
|
||||
EntityVillager entityvillager = (EntityVillager) entityliving;
|
||||
- EntityZombieVillager entityzombievillager = new EntityZombieVillager(this.world);
|
||||
+ EntityZombieVillager entityzombievillager = EntityTypes.ZOMBIE_VILLAGER.create(world); // Paper
|
||||
|
||||
entityzombievillager.u(entityvillager);
|
||||
// this.world.kill(entityvillager); // CraftBukkit - moved down
|
||||
@@ -450,7 +450,7 @@ public class EntityZombie extends EntityMonster {
|
||||
this.startRiding(entitychicken);
|
||||
}
|
||||
} else if ((double) this.world.random.nextFloat() < 0.05D) {
|
||||
- EntityChicken entitychicken1 = new EntityChicken(this.world);
|
||||
+ EntityChicken entitychicken1 = EntityTypes.CHICKEN.create(world); // Paper
|
||||
|
||||
entitychicken1.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
|
||||
entitychicken1.prepare(difficultydamagescaler, (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityZombieHusk.java b/src/main/java/net/minecraft/server/EntityZombieHusk.java
|
||||
index 85d402965b..0cca7b6d51 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityZombieHusk.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityZombieHusk.java
|
||||
@@ -54,7 +54,7 @@ public class EntityZombieHusk extends EntityZombie {
|
||||
}
|
||||
|
||||
protected void dE() {
|
||||
- this.a(new EntityZombie(this.world));
|
||||
+ this.a(EntityTypes.ZOMBIE.create(world)); // Paper
|
||||
this.world.a((EntityHuman) null, 1041, new BlockPosition((int) this.locX, (int) this.locY, (int) this.locZ), 0);
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityZombieVillager.java b/src/main/java/net/minecraft/server/EntityZombieVillager.java
|
||||
index 359ac8b88c..96a1b1d3f2 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityZombieVillager.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityZombieVillager.java
|
||||
@@ -119,7 +119,7 @@ public class EntityZombieVillager extends EntityZombie {
|
||||
}
|
||||
|
||||
protected void dJ() {
|
||||
- EntityVillager entityvillager = new EntityVillager(this.world);
|
||||
+ EntityVillager entityvillager = EntityTypes.VILLAGER.create(world); // Paper
|
||||
|
||||
entityvillager.u(this);
|
||||
entityvillager.setProfession(this.getProfession());
|
||||
diff --git a/src/main/java/net/minecraft/server/ItemArmorStand.java b/src/main/java/net/minecraft/server/ItemArmorStand.java
|
||||
index 576b3c5650..4dd0e39ec3 100644
|
||||
--- a/src/main/java/net/minecraft/server/ItemArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/server/ItemArmorStand.java
|
||||
@@ -34,7 +34,7 @@ public class ItemArmorStand extends Item {
|
||||
if (!world.isClientSide) {
|
||||
world.setAir(blockposition);
|
||||
world.setAir(blockposition1);
|
||||
- EntityArmorStand entityarmorstand = new EntityArmorStand(world, d0 + 0.5D, d1, d2 + 0.5D);
|
||||
+ EntityArmorStand entityarmorstand = EntityTypes.ARMOR_STAND.create(world); // Paper
|
||||
float f = (float) MathHelper.d((MathHelper.g(itemactioncontext.h() - 180.0F) + 22.5F) / 45.0F) * 45.0F;
|
||||
|
||||
entityarmorstand.setPositionRotation(d0 + 0.5D, d1, d2 + 0.5D, f, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/MobSpawnerPhantom.java b/src/main/java/net/minecraft/server/MobSpawnerPhantom.java
|
||||
index 5ddf66eef5..bb7e072ee1 100644
|
||||
--- a/src/main/java/net/minecraft/server/MobSpawnerPhantom.java
|
||||
+++ b/src/main/java/net/minecraft/server/MobSpawnerPhantom.java
|
||||
@@ -59,7 +59,7 @@ public class MobSpawnerPhantom {
|
||||
continue;
|
||||
}
|
||||
// Paper end
|
||||
- EntityPhantom entityphantom = new EntityPhantom(world);
|
||||
+ EntityPhantom entityphantom = EntityTypes.PHANTOM.create(world); // Paper
|
||||
entityphantom.spawningEntity = entityhuman.uniqueID; // Paper
|
||||
entityphantom.setPositionRotation(blockposition1, 0.0F, 0.0F);
|
||||
groupdataentity = entityphantom.prepare(difficultydamagescaler, groupdataentity, (NBTTagCompound) null);
|
||||
diff --git a/src/main/java/net/minecraft/server/PathfinderGoalHorseTrap.java b/src/main/java/net/minecraft/server/PathfinderGoalHorseTrap.java
|
||||
index d4fdcbdfd6..887e4461f3 100644
|
||||
--- a/src/main/java/net/minecraft/server/PathfinderGoalHorseTrap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PathfinderGoalHorseTrap.java
|
||||
@@ -36,7 +36,7 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal {
|
||||
}
|
||||
|
||||
private EntityHorseAbstract a(DifficultyDamageScaler difficultydamagescaler) {
|
||||
- EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this.a.world);
|
||||
+ EntityHorseSkeleton entityhorseskeleton = EntityTypes.SKELETON_HORSE.create(a.world); // Paper
|
||||
|
||||
entityhorseskeleton.prepare(difficultydamagescaler, (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
entityhorseskeleton.setPosition(this.a.locX, this.a.locY, this.a.locZ);
|
||||
@@ -49,7 +49,7 @@ public class PathfinderGoalHorseTrap extends PathfinderGoal {
|
||||
}
|
||||
|
||||
private EntitySkeleton a(DifficultyDamageScaler difficultydamagescaler, EntityHorseAbstract entityhorseabstract) {
|
||||
- EntitySkeleton entityskeleton = new EntitySkeleton(entityhorseabstract.world);
|
||||
+ EntitySkeleton entityskeleton = EntityTypes.SKELETON.create(entityhorseabstract.world); // Paper
|
||||
|
||||
entityskeleton.prepare(difficultydamagescaler, (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
entityskeleton.setPosition(entityhorseabstract.locX, entityhorseabstract.locY, entityhorseabstract.locZ);
|
||||
diff --git a/src/main/java/net/minecraft/server/VillageSiege.java b/src/main/java/net/minecraft/server/VillageSiege.java
|
||||
index 0ac1fb53a4..509d62f6b6 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillageSiege.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillageSiege.java
|
||||
@@ -134,7 +134,7 @@ public class VillageSiege {
|
||||
EntityZombie entityzombie;
|
||||
|
||||
try {
|
||||
- entityzombie = new EntityZombie(this.a);
|
||||
+ entityzombie = EntityTypes.ZOMBIE.create(this.a); // Paper
|
||||
entityzombie.prepare(this.a.getDamageScaler(new BlockPosition(entityzombie)), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenEndCityPieces.java b/src/main/java/net/minecraft/server/WorldGenEndCityPieces.java
|
||||
index 94b21693e2..0a223cfe5a 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenEndCityPieces.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenEndCityPieces.java
|
||||
@@ -270,7 +270,7 @@ public class WorldGenEndCityPieces {
|
||||
TileEntityLootable.a(generatoraccess, random, blockposition1, LootTables.c);
|
||||
}
|
||||
} else if (s.startsWith("Sentry")) {
|
||||
- EntityShulker entityshulker = new EntityShulker(generatoraccess.getMinecraftWorld());
|
||||
+ EntityShulker entityshulker = EntityTypes.SHULKER.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
|
||||
entityshulker.setPosition((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D);
|
||||
entityshulker.g(blockposition);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenFeatureOceanRuinPieces.java b/src/main/java/net/minecraft/server/WorldGenFeatureOceanRuinPieces.java
|
||||
index 2def56b067..abeb4aa025 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenFeatureOceanRuinPieces.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenFeatureOceanRuinPieces.java
|
||||
@@ -154,8 +154,7 @@ public class WorldGenFeatureOceanRuinPieces {
|
||||
((TileEntityChest) tileentity).setLootTable(this.h ? LootTables.q : LootTables.p, random.nextLong());
|
||||
}
|
||||
} else if ("drowned".equals(s)) {
|
||||
- EntityDrowned entitydrowned = new EntityDrowned(generatoraccess.getMinecraftWorld());
|
||||
-
|
||||
+ EntityDrowned entitydrowned = EntityTypes.DROWNED.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
entitydrowned.di();
|
||||
entitydrowned.setPositionRotation(blockposition, 0.0F, 0.0F);
|
||||
entitydrowned.prepare(generatoraccess.getDamageScaler(blockposition), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenMonumentPieces.java b/src/main/java/net/minecraft/server/WorldGenMonumentPieces.java
|
||||
index 0e7aed09d1..493a86e1bf 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenMonumentPieces.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenMonumentPieces.java
|
||||
@@ -1800,7 +1800,7 @@ public class WorldGenMonumentPieces {
|
||||
protected static final IBlockData d = WorldGenMonumentPieces.WorldGenMonumentPiece.b;
|
||||
protected static final IBlockData e = Blocks.SEA_LANTERN.getBlockData();
|
||||
protected static final IBlockData f = Blocks.WATER.getBlockData();
|
||||
- protected static final Set<Block> g = ImmutableSet.builder().add(Blocks.ICE).add(Blocks.PACKED_ICE).add(Blocks.BLUE_ICE).add(WorldGenMonumentPieces.WorldGenMonumentPiece.f.getBlock()).build();
|
||||
+ protected static final Set<Block> g = ImmutableSet.<Block>builder().add(Blocks.ICE).add(Blocks.PACKED_ICE).add(Blocks.BLUE_ICE).add(WorldGenMonumentPieces.WorldGenMonumentPiece.f.getBlock()).build(); // Paper - decompile fix
|
||||
protected static final int h = b(2, 0, 0);
|
||||
protected static final int i = b(2, 2, 0);
|
||||
protected static final int j = b(0, 1, 0);
|
||||
@@ -1923,7 +1923,7 @@ public class WorldGenMonumentPieces {
|
||||
int j1 = this.b(i, k);
|
||||
|
||||
if (structureboundingbox.b((BaseBlockPosition) (new BlockPosition(l, i1, j1)))) {
|
||||
- EntityGuardianElder entityguardianelder = new EntityGuardianElder(generatoraccess.getMinecraftWorld());
|
||||
+ EntityGuardianElder entityguardianelder = EntityTypes.ELDER_GUARDIAN.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
|
||||
entityguardianelder.heal(entityguardianelder.getMaxHealth());
|
||||
entityguardianelder.setPositionRotation((double) l + 0.5D, (double) i1, (double) j1 + 0.5D, 0.0F, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenVillagePieces.java b/src/main/java/net/minecraft/server/WorldGenVillagePieces.java
|
||||
index 5fa2987d2a..967e33b3d7 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenVillagePieces.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenVillagePieces.java
|
||||
@@ -1640,7 +1640,7 @@ public class WorldGenVillagePieces {
|
||||
|
||||
++this.a;
|
||||
if (this.h) {
|
||||
- EntityZombieVillager entityzombievillager = new EntityZombieVillager(generatoraccess.getMinecraftWorld());
|
||||
+ EntityZombieVillager entityzombievillager = EntityTypes.ZOMBIE_VILLAGER.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
|
||||
entityzombievillager.setPositionRotation((double) j1 + 0.5D, (double) k1, (double) l1 + 0.5D, 0.0F, 0.0F);
|
||||
entityzombievillager.prepare(generatoraccess.getDamageScaler(new BlockPosition(entityzombievillager)), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
@@ -1648,7 +1648,7 @@ public class WorldGenVillagePieces {
|
||||
entityzombievillager.di();
|
||||
generatoraccess.addEntity(entityzombievillager, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason
|
||||
} else {
|
||||
- EntityVillager entityvillager = new EntityVillager(generatoraccess.getMinecraftWorld());
|
||||
+ EntityVillager entityvillager = EntityTypes.VILLAGER.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
|
||||
entityvillager.setPositionRotation((double) j1 + 0.5D, (double) k1, (double) l1 + 0.5D, 0.0F, 0.0F);
|
||||
entityvillager.setProfession(this.c(i1, generatoraccess.m().nextInt(6)));
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenWitchHut.java b/src/main/java/net/minecraft/server/WorldGenWitchHut.java
|
||||
index efb0379ce3..3d8193c477 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenWitchHut.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenWitchHut.java
|
||||
@@ -81,7 +81,7 @@ public class WorldGenWitchHut extends WorldGenScatteredPiece {
|
||||
|
||||
if (structureboundingbox.b((BaseBlockPosition) (new BlockPosition(j, i, k)))) {
|
||||
this.e = true;
|
||||
- EntityWitch entitywitch = new EntityWitch(generatoraccess.getMinecraftWorld());
|
||||
+ EntityWitch entitywitch = EntityTypes.WITCH.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
|
||||
entitywitch.di();
|
||||
entitywitch.setPositionRotation((double) j + 0.5D, (double) i, (double) k + 0.5D, 0.0F, 0.0F);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenWoodlandMansionPieces.java b/src/main/java/net/minecraft/server/WorldGenWoodlandMansionPieces.java
|
||||
index 11010d8e12..4eb746ebb0 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenWoodlandMansionPieces.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenWoodlandMansionPieces.java
|
||||
@@ -23,14 +23,14 @@ public class WorldGenWoodlandMansionPieces {
|
||||
static class h extends WorldGenWoodlandMansionPieces.f {
|
||||
|
||||
private h() {
|
||||
- super(null);
|
||||
+ super(); // Paper - decompile fix
|
||||
}
|
||||
}
|
||||
|
||||
static class f extends WorldGenWoodlandMansionPieces.b {
|
||||
|
||||
private f() {
|
||||
- super(null);
|
||||
+ super(); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public String a(Random random) {
|
||||
@@ -65,7 +65,7 @@ public class WorldGenWoodlandMansionPieces {
|
||||
static class a extends WorldGenWoodlandMansionPieces.b {
|
||||
|
||||
private a() {
|
||||
- super(null);
|
||||
+ super(); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public String a(Random random) {
|
||||
@@ -1065,15 +1065,13 @@ public class WorldGenWoodlandMansionPieces {
|
||||
|
||||
this.a(generatoraccess, structureboundingbox, random, blockposition, LootTables.o, iblockdata);
|
||||
} else if ("Mage".equals(s)) {
|
||||
- EntityEvoker entityevoker = new EntityEvoker(generatoraccess.getMinecraftWorld());
|
||||
-
|
||||
+ EntityEvoker entityevoker = EntityTypes.EVOKER.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
entityevoker.di();
|
||||
entityevoker.setPositionRotation(blockposition, 0.0F, 0.0F);
|
||||
generatoraccess.addEntity(entityevoker);
|
||||
generatoraccess.setTypeAndData(blockposition, Blocks.AIR.getBlockData(), 2);
|
||||
} else if ("Warrior".equals(s)) {
|
||||
- EntityVindicator entityvindicator = new EntityVindicator(generatoraccess.getMinecraftWorld());
|
||||
-
|
||||
+ EntityVindicator entityvindicator = EntityTypes.VINDICATOR.create(generatoraccess.getMinecraftWorld()); // Paper
|
||||
entityvindicator.di();
|
||||
entityvindicator.setPositionRotation(blockposition, 0.0F, 0.0F);
|
||||
entityvindicator.prepare(generatoraccess.getDamageScaler(new BlockPosition(entityvindicator)), (GroupDataEntity) null, (NBTTagCompound) null);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index 53e7834cca..5c2421ac38 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -495,7 +495,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
|
||||
boolean flag2 = this.getGameRules().getBoolean("doMobSpawning") && this.random.nextDouble() < (double) difficultydamagescaler.b() * paperConfig.skeleHorseSpawnChance; // Paper
|
||||
|
||||
if (flag2) {
|
||||
- EntityHorseSkeleton entityhorseskeleton = new EntityHorseSkeleton(this);
|
||||
+ EntityHorseSkeleton entityhorseskeleton = EntityTypes.SKELETON_HORSE.create(this); // Paper
|
||||
|
||||
entityhorseskeleton.s(true);
|
||||
entityhorseskeleton.setAgeRaw(0);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 7c0a530533..40ee34675c 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1181,153 +1181,153 @@ public class CraftWorld implements World {
|
||||
entity.setPositionRotation(x, y, z, 0, 0);
|
||||
} else if (LivingEntity.class.isAssignableFrom(clazz)) {
|
||||
if (Chicken.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityChicken(world);
|
||||
+ entity = EntityTypes.CHICKEN.create(world); // Paper
|
||||
} else if (Cow.class.isAssignableFrom(clazz)) {
|
||||
if (MushroomCow.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityMushroomCow(world);
|
||||
+ entity = EntityTypes.MOOSHROOM.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntityCow(world);
|
||||
+ entity = EntityTypes.COW.create(world); // Paper
|
||||
}
|
||||
} else if (Golem.class.isAssignableFrom(clazz)) {
|
||||
if (Snowman.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySnowman(world);
|
||||
+ entity = EntityTypes.SNOW_GOLEM.create(world); // Paper
|
||||
} else if (IronGolem.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityIronGolem(world);
|
||||
+ entity = EntityTypes.IRON_GOLEM.create(world); // Paper
|
||||
} else if (Shulker.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityShulker(world);
|
||||
+ entity = EntityTypes.SHULKER.create(world); // Paper
|
||||
}
|
||||
} else if (Creeper.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityCreeper(world);
|
||||
+ entity = EntityTypes.CREEPER.create(world); // Paper
|
||||
} else if (Ghast.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityGhast(world);
|
||||
+ entity = EntityTypes.GHAST.create(world); // Paper
|
||||
} else if (Pig.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityPig(world);
|
||||
+ entity = EntityTypes.PIG.create(world); // Paper
|
||||
} else if (Player.class.isAssignableFrom(clazz)) {
|
||||
// need a net server handler for this one
|
||||
} else if (Sheep.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySheep(world);
|
||||
+ entity = EntityTypes.SHEEP.create(world); // Paper
|
||||
} else if (AbstractHorse.class.isAssignableFrom(clazz)) {
|
||||
if (ChestedHorse.class.isAssignableFrom(clazz)) {
|
||||
if (Donkey.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityHorseDonkey(world);
|
||||
+ entity = EntityTypes.DONKEY.create(world); // Paper
|
||||
} else if (Mule.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityHorseMule(world);
|
||||
+ entity = EntityTypes.MULE.create(world); // Paper
|
||||
} else if (Llama.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityLlama(world);
|
||||
+ entity = EntityTypes.LLAMA.create(world); // Paper
|
||||
}
|
||||
} else if (SkeletonHorse.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityHorseSkeleton(world);
|
||||
+ entity = EntityTypes.SKELETON_HORSE.create(world); // Paper
|
||||
} else if (ZombieHorse.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityHorseZombie(world);
|
||||
+ entity = EntityTypes.ZOMBIE_HORSE.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntityHorse(world);
|
||||
+ entity = EntityTypes.HORSE.create(world); // Paper
|
||||
}
|
||||
} else if (Skeleton.class.isAssignableFrom(clazz)) {
|
||||
if (Stray.class.isAssignableFrom(clazz)){
|
||||
- entity = new EntitySkeletonStray(world);
|
||||
+ entity = EntityTypes.STRAY.create(world); // Paper
|
||||
} else if (WitherSkeleton.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySkeletonWither(world);
|
||||
+ entity = EntityTypes.WITHER_SKELETON.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntitySkeleton(world);
|
||||
+ entity = EntityTypes.SKELETON.create(world); // Paper
|
||||
}
|
||||
} else if (Slime.class.isAssignableFrom(clazz)) {
|
||||
if (MagmaCube.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityMagmaCube(world);
|
||||
+ entity = EntityTypes.MAGMA_CUBE.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntitySlime(world);
|
||||
+ entity = EntityTypes.SLIME.create(world); // Paper
|
||||
}
|
||||
} else if (Spider.class.isAssignableFrom(clazz)) {
|
||||
if (CaveSpider.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityCaveSpider(world);
|
||||
+ entity = EntityTypes.CAVE_SPIDER.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntitySpider(world);
|
||||
+ entity = EntityTypes.SPIDER.create(world); // Paper
|
||||
}
|
||||
} else if (Squid.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySquid(world);
|
||||
+ entity = EntityTypes.SQUID.create(world); // Paper
|
||||
} else if (Tameable.class.isAssignableFrom(clazz)) {
|
||||
if (Wolf.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityWolf(world);
|
||||
+ entity = EntityTypes.WOLF.create(world); // Paper
|
||||
} else if (Ocelot.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityOcelot(world);
|
||||
+ entity = EntityTypes.OCELOT.create(world); // Paper
|
||||
} else if (Parrot.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityParrot(world);
|
||||
+ entity = EntityTypes.PARROT.create(world); // Paper
|
||||
}
|
||||
} else if (PigZombie.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityPigZombie(world);
|
||||
+ entity = EntityTypes.ZOMBIE_PIGMAN.create(world); // Paper
|
||||
} else if (Zombie.class.isAssignableFrom(clazz)) {
|
||||
if (Husk.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityZombieHusk(world);
|
||||
+ entity = EntityTypes.HUSK.create(world); // Paper
|
||||
} else if (ZombieVillager.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityZombieVillager(world);
|
||||
+ entity = EntityTypes.ZOMBIE_VILLAGER.create(world); // Paper
|
||||
} else if (Drowned.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityDrowned(world);
|
||||
+ entity = EntityTypes.DROWNED.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntityZombie(world);
|
||||
+ entity = EntityTypes.ZOMBIE.create(world); // Paper
|
||||
}
|
||||
} else if (Giant.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityGiantZombie(world);
|
||||
+ entity = EntityTypes.GIANT.create(world); // Paper
|
||||
} else if (Silverfish.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySilverfish(world);
|
||||
+ entity = EntityTypes.SILVERFISH.create(world); // Paper
|
||||
} else if (Enderman.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityEnderman(world);
|
||||
+ entity = EntityTypes.ENDERMAN.create(world); // Paper
|
||||
} else if (Blaze.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityBlaze(world);
|
||||
+ entity = EntityTypes.BLAZE.create(world); // Paper
|
||||
} else if (Villager.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityVillager(world);
|
||||
+ entity = EntityTypes.VILLAGER.create(world); // Paper
|
||||
} else if (Witch.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityWitch(world);
|
||||
+ entity = EntityTypes.WITCH.create(world); // Paper
|
||||
} else if (Wither.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityWither(world);
|
||||
+ entity = EntityTypes.WITHER.create(world); // Paper
|
||||
} else if (ComplexLivingEntity.class.isAssignableFrom(clazz)) {
|
||||
if (EnderDragon.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityEnderDragon(world);
|
||||
+ entity = EntityTypes.ENDER_DRAGON.create(world); // Paper
|
||||
}
|
||||
} else if (Ambient.class.isAssignableFrom(clazz)) {
|
||||
if (Bat.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityBat(world);
|
||||
+ entity = EntityTypes.BAT.create(world); // Paper
|
||||
}
|
||||
} else if (Rabbit.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityRabbit(world);
|
||||
+ entity = EntityTypes.RABBIT.create(world); // Paper
|
||||
} else if (Endermite.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityEndermite(world);
|
||||
+ entity = EntityTypes.ENDERMITE.create(world); // Paper
|
||||
} else if (Guardian.class.isAssignableFrom(clazz)) {
|
||||
if (ElderGuardian.class.isAssignableFrom(clazz)){
|
||||
- entity = new EntityGuardianElder(world);
|
||||
+ entity = EntityTypes.ELDER_GUARDIAN.create(world); // Paper
|
||||
} else {
|
||||
- entity = new EntityGuardian(world);
|
||||
+ entity = EntityTypes.GUARDIAN.create(world); // Paper
|
||||
}
|
||||
} else if (ArmorStand.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityArmorStand(world, x, y, z);
|
||||
+ entity = EntityTypes.ARMOR_STAND.create(world); // Paper
|
||||
} else if (PolarBear.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityPolarBear(world);
|
||||
+ entity = EntityTypes.POLAR_BEAR.create(world); // Paper
|
||||
} else if (Vex.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityVex(world);
|
||||
+ entity = EntityTypes.VEX.create(world); // Paper
|
||||
} else if (Illager.class.isAssignableFrom(clazz)) {
|
||||
if (Spellcaster.class.isAssignableFrom(clazz)) {
|
||||
if (Evoker.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityEvoker(world);
|
||||
+ entity = EntityTypes.EVOKER.create(world); // Paper
|
||||
} else if (Illusioner.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityIllagerIllusioner(world);
|
||||
+ entity = EntityTypes.ILLUSIONER.create(world); // Paper
|
||||
}
|
||||
} else if (Vindicator.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityVindicator(world);
|
||||
+ entity = EntityTypes.VINDICATOR.create(world); // Paper
|
||||
}
|
||||
} else if (Turtle.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityTurtle(world);
|
||||
+ entity = EntityTypes.TURTLE.create(world); // Paper
|
||||
} else if (Phantom.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityPhantom(world);
|
||||
+ entity = EntityTypes.PHANTOM.create(world); // Paper
|
||||
} else if (Fish.class.isAssignableFrom(clazz)) {
|
||||
if (Cod.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityCod(world);
|
||||
+ entity = EntityTypes.COD.create(world); // Paper
|
||||
} else if (PufferFish.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityPufferFish(world);
|
||||
+ entity = EntityTypes.PUFFERFISH.create(world); // Paper
|
||||
} else if (Salmon.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntitySalmon(world);
|
||||
+ entity = EntityTypes.SALMON.create(world); // Paper
|
||||
} else if (TropicalFish.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityTropicalFish(world);
|
||||
+ entity = EntityTypes.TROPICAL_FISH.create(world); // Paper
|
||||
}
|
||||
} else if (Dolphin.class.isAssignableFrom(clazz)) {
|
||||
- entity = new EntityDolphin(world);
|
||||
+ entity = EntityTypes.DOLPHIN.create(world); // Paper
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,35 +0,0 @@
|
||||
From a55362012ae6439bd007bf980dc0e094b7e9257a Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Tue, 13 Nov 2018 14:01:00 +0000
|
||||
Subject: [PATCH] limit the range at which we'll consider an attackable target
|
||||
|
||||
This patch aims to ensure that MCP World#getNearestAttackablePlayer
|
||||
will not trigger chunk loads due to PathfinderGoalNearestAttackableTarget
|
||||
performing a ray trace operation by pre-checking the maximum limit;
|
||||
|
||||
Given that the implementation shows that the limit should only ever
|
||||
decrease when set, allowing us to skip further checks earlier on
|
||||
when looking for an attackable entity
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 645af17a58..7721dfee65 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -2721,8 +2721,13 @@ public abstract class World implements IEntityAccess, GeneratorAccess, IIBlockAc
|
||||
for (int i = 0; i < this.players.size(); ++i) {
|
||||
EntityHuman entityhuman1 = (EntityHuman) this.players.get(i);
|
||||
|
||||
+ // Paper start
|
||||
+ // move distance check up, if set, check distance^2 is less than XZlimit^2, continue
|
||||
+ // 4th method param is XZlimit (at least at the time of commit)
|
||||
+ double d6 = entityhuman1.d(d0, entityhuman1.locY, d2);
|
||||
+ if (d3 < 0.0D || d6 < d3 * d3)
|
||||
if (!entityhuman1.abilities.isInvulnerable && entityhuman1.isAlive() && !entityhuman1.isSpectator() && (predicate == null || predicate.test(entityhuman1))) {
|
||||
- double d6 = entityhuman1.d(d0, entityhuman1.locY, d2);
|
||||
+ // Paper end
|
||||
double d7 = d3;
|
||||
|
||||
if (entityhuman1.isSneaking()) {
|
||||
--
|
||||
2.21.0
|
||||
|
@ -1,52 +0,0 @@
|
||||
From 299ea42df7d2ad51015e65dbbf5bb77a3d4f4e09 Mon Sep 17 00:00:00 2001
|
||||
From: Antony Riley <antony@cyberiantiger.org>
|
||||
Date: Tue, 29 Mar 2016 06:56:23 +0300
|
||||
Subject: [PATCH] Reduce IO ops opening a new region file.
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
index fb529eac9..faf425588 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
@@ -26,7 +26,7 @@ public class RegionFile implements AutoCloseable {
|
||||
private final File file;
|
||||
// Spigot end
|
||||
private static final byte[] a = new byte[4096];
|
||||
- private final RandomAccessFile b; // PAIL dataFile
|
||||
+ private final RandomAccessFile b; private RandomAccessFile getDataFile() { return this.b; } // Paper - OBFHELPER // PAIL dataFile
|
||||
private final int[] c = new int[1024];
|
||||
private final int[] d = new int[1024];
|
||||
private final List<Boolean> e; // PAIL freeSectors
|
||||
@@ -59,10 +59,19 @@ public class RegionFile implements AutoCloseable {
|
||||
this.e.set(1, false);
|
||||
this.b.seek(0L);
|
||||
|
||||
+ // Paper start
|
||||
+ java.nio.ByteBuffer header = java.nio.ByteBuffer.allocate(8192);
|
||||
+ while (header.hasRemaining()) {
|
||||
+ if (this.getDataFile().getChannel().read(header) == -1) throw new java.io.EOFException();
|
||||
+ }
|
||||
+ ((java.nio.Buffer) header).clear();
|
||||
+ java.nio.IntBuffer headerAsInts = header.asIntBuffer();
|
||||
+ // Paper end
|
||||
+
|
||||
int k;
|
||||
|
||||
for (j = 0; j < 1024; ++j) {
|
||||
- k = this.b.readInt();
|
||||
+ k = headerAsInts.get(); // Paper
|
||||
this.c[j] = k;
|
||||
// Spigot start
|
||||
int length = k & 255;
|
||||
@@ -88,7 +97,7 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
|
||||
for (j = 0; j < 1024; ++j) {
|
||||
- k = this.b.readInt();
|
||||
+ k = headerAsInts.get(); // Paper
|
||||
this.d[j] = k;
|
||||
}
|
||||
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,23 +0,0 @@
|
||||
From 317532f24f529ff717533f65beadc821a7a62bc7 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 31 Mar 2016 19:17:58 -0400
|
||||
Subject: [PATCH] Do not load chunks for light checks
|
||||
|
||||
Should only happen for blocks on the edge that uses neighbors light level
|
||||
(certain blocks). In that case, there will be 3-4 other neighbors to get a light level from.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 1ffa8b42b..35fb686d8 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -592,6 +592,7 @@ public abstract class World implements IIBlockAccess, GeneratorAccess, AutoClose
|
||||
if (blockposition.getY() >= 256) {
|
||||
blockposition = new BlockPosition(blockposition.getX(), 255, blockposition.getZ());
|
||||
}
|
||||
+ if (!this.isLoaded(blockposition)) return 0; // Paper
|
||||
|
||||
return this.getChunkAtWorldCoords(blockposition).a(blockposition, i);
|
||||
}
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,230 +0,0 @@
|
||||
From 9c38be60e37133286ee35635cdc44ac7a4eb555e Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 29 Jul 2018 15:48:50 -0400
|
||||
Subject: [PATCH] Provide option to use a versioned world folder for testing
|
||||
|
||||
This should not ever be used in production!!
|
||||
|
||||
This setting is intended for testing so you can try out converting your world
|
||||
without actually modifying the world files.
|
||||
|
||||
This will add some additional overhead to your world, but you're
|
||||
just testing anyways so that's not a big deal :)
|
||||
|
||||
Will store in a folder named after the current version.
|
||||
|
||||
PlayerData and Data folders are copied on server start, so there
|
||||
may be some delay there, but region files are only copied on demand.
|
||||
|
||||
This is highly experiemental so backup your world before relying on this to not modify it
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index eeef7d330b..dfdc7c384d 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -13,6 +13,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
+import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
@@ -287,4 +288,27 @@ public class PaperConfig {
|
||||
Bukkit.getLogger().log(Level.INFO, "Using Aikar's Alternative Luck Formula to apply Luck attribute to all loot pool calculations. See https://luckformula.emc.gs");
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public static boolean useVersionedWorld = false;
|
||||
+ private static void useVersionedWorld() {
|
||||
+ useVersionedWorld = getBoolean("settings.use-versioned-world", false);
|
||||
+ if (useVersionedWorld) {
|
||||
+ Logger logger = Bukkit.getLogger();
|
||||
+ String ver = MinecraftServer.getServer().getVersion();
|
||||
+ logger.log(Level.INFO, "******************************************************");
|
||||
+ logger.log(Level.INFO, "*** Using a versioned world folder. Your world will be saved");
|
||||
+ logger.log(Level.INFO, "*** to into the " + ver + " folder, but copied from your current world.");
|
||||
+ logger.log(Level.INFO, "*** ");
|
||||
+ logger.log(Level.INFO, "*** This setting should not be used in your real world!!!");
|
||||
+ logger.log(Level.INFO, "*** If you want to retain the new world, you need to move ");
|
||||
+ logger.log(Level.INFO, "*** the folders out of the " + ver + " folder and overwrite existing");
|
||||
+ logger.log(Level.INFO, "*** ");
|
||||
+ logger.log(Level.INFO, "*** Deleting the " + ver + " folder will cause it to recreate again");
|
||||
+ logger.log(Level.INFO, "*** from your unversioned world files.");
|
||||
+ logger.log(Level.INFO, "*** ");
|
||||
+ logger.log(Level.INFO, "*** You should backup your original world files incase something goes");
|
||||
+ logger.log(Level.INFO, "*** wrong with this system! This is not a backup system.");
|
||||
+ logger.log(Level.INFO, "******************************************************");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
index 21b3b06f53..8718811655 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
@@ -10,13 +10,41 @@ import java.io.IOException;
|
||||
import javax.annotation.Nullable;
|
||||
import com.destroystokyo.paper.PaperConfig; // Paper
|
||||
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+
|
||||
public abstract class RegionFileCache implements AutoCloseable {
|
||||
|
||||
public final Long2ObjectLinkedOpenHashMap<RegionFile> cache = new Long2ObjectLinkedOpenHashMap();
|
||||
private final File a;
|
||||
+ // Paper start
|
||||
+ private final File templateWorld;
|
||||
+ private final File actualWorld;
|
||||
+ private boolean useAltWorld;
|
||||
+ // Paper end
|
||||
+
|
||||
|
||||
protected RegionFileCache(File file) {
|
||||
this.a = file;
|
||||
+ // Paper end
|
||||
+
|
||||
+ this.actualWorld = file;
|
||||
+ if (com.destroystokyo.paper.PaperConfig.useVersionedWorld) {
|
||||
+ this.useAltWorld = true;
|
||||
+ String name = file.getName();
|
||||
+ File container = file.getParentFile().getParentFile();
|
||||
+ if (name.equals("DIM-1") || name.equals("DIM1")) {
|
||||
+ container = container.getParentFile();
|
||||
+ }
|
||||
+ this.templateWorld = new File(container, name);
|
||||
+ File region = new File(file, "region");
|
||||
+ if (!region.exists()) {
|
||||
+ region.mkdirs();
|
||||
+ }
|
||||
+ } else {
|
||||
+ this.useAltWorld = false;
|
||||
+ this.templateWorld = file;
|
||||
+ }
|
||||
+ // Paper start
|
||||
}
|
||||
|
||||
private RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit
|
||||
@@ -34,6 +62,7 @@ public abstract class RegionFileCache implements AutoCloseable {
|
||||
this.a.mkdirs();
|
||||
}
|
||||
|
||||
+ copyIfNeeded(chunkcoordintpair.x, chunkcoordintpair.z); // Paper
|
||||
File file = new File(this.a, "r." + chunkcoordintpair.getRegionX() + "." + chunkcoordintpair.getRegionZ() + ".mca");
|
||||
if (existingOnly && !file.exists()) return null; // CraftBukkit
|
||||
RegionFile regionfile1 = new RegionFile(file);
|
||||
@@ -43,6 +72,15 @@ public abstract class RegionFileCache implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
+ public static File getRegionFileName(File file, int i, int j) {
|
||||
+ File file1 = new File(file, "region");
|
||||
+ return new File(file1, "r." + (i >> 5) + "." + (j >> 5) + ".mca");
|
||||
+ }
|
||||
+ public synchronized boolean hasRegionFile(File file, int i, int j) {
|
||||
+ return cache.containsKey(ChunkCoordIntPair.pair(i, j));
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@Nullable
|
||||
public NBTTagCompound read(ChunkCoordIntPair chunkcoordintpair) throws IOException {
|
||||
RegionFile regionfile = this.a(chunkcoordintpair, false); // CraftBukkit
|
||||
@@ -132,9 +170,33 @@ public abstract class RegionFileCache implements AutoCloseable {
|
||||
|
||||
// CraftBukkit start
|
||||
public boolean chunkExists(ChunkCoordIntPair pos) throws IOException {
|
||||
+ copyIfNeeded(pos.x, pos.z); // Paper
|
||||
RegionFile regionfile = a(pos, true);
|
||||
|
||||
return regionfile != null ? regionfile.d(pos) : false;
|
||||
}
|
||||
// CraftBukkit end
|
||||
+
|
||||
+ private void copyIfNeeded(int x, int z) {
|
||||
+ if (!useAltWorld) {
|
||||
+ return;
|
||||
+ }
|
||||
+ synchronized (RegionFileCache.class) {
|
||||
+ if (hasRegionFile(this.actualWorld, x, z)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ File actual = RegionFileCache.getRegionFileName(this.actualWorld, x, z);
|
||||
+ File template = RegionFileCache.getRegionFileName(this.templateWorld, x, z);
|
||||
+ if (!actual.exists() && template.exists()) {
|
||||
+ try {
|
||||
+ net.minecraft.server.MinecraftServer.LOGGER.info("Copying" + template + " to " + actual);
|
||||
+ java.nio.file.Files.copy(template.toPath(), actual.toPath(), java.nio.file.StandardCopyOption.COPY_ATTRIBUTES);
|
||||
+ } catch (IOException e1) {
|
||||
+ LogManager.getLogger().error("Error copying " + template + " to " + actual, e1);
|
||||
+ MinecraftServer.getServer().safeShutdown(false);
|
||||
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldNBTStorage.java b/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
||||
index 350ac42d6b..eaae446861 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldNBTStorage.java
|
||||
@@ -31,6 +31,58 @@ public class WorldNBTStorage implements IPlayerFileData {
|
||||
|
||||
public WorldNBTStorage(File file, String s, @Nullable MinecraftServer minecraftserver, DataFixer datafixer) {
|
||||
this.a = datafixer;
|
||||
+ // Paper start
|
||||
+ if (com.destroystokyo.paper.PaperConfig.useVersionedWorld) {
|
||||
+ File origBaseDir = new File(file, s);
|
||||
+ final String currentVersion = MinecraftServer.getServer().getVersion();
|
||||
+ file = new File(file, currentVersion);
|
||||
+ File baseDir = new File(file, s);
|
||||
+
|
||||
+ if (!baseDir.exists() && origBaseDir.exists() && !baseDir.mkdirs()) {
|
||||
+ LogManager.getLogger().error("Could not create world directory for " + file);
|
||||
+ System.exit(1);
|
||||
+ }
|
||||
+
|
||||
+ try {
|
||||
+ boolean printedHeader = false;
|
||||
+ String[] dirs = {"advancements", "data", "datapacks", "playerdata", "stats"};
|
||||
+ for (String dir : dirs) {
|
||||
+ File origPlayerData = new File(origBaseDir, dir);
|
||||
+ File targetPlayerData = new File(baseDir, dir);
|
||||
+ if (origPlayerData.exists() && !targetPlayerData.exists()) {
|
||||
+ if (!printedHeader) {
|
||||
+ LogManager.getLogger().info("**** VERSIONED WORLD - Copying files");
|
||||
+ printedHeader = true;
|
||||
+ }
|
||||
+ LogManager.getLogger().info("- Copying: " + dir);
|
||||
+ org.apache.commons.io.FileUtils.copyDirectory(origPlayerData, targetPlayerData);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ String[] files = {"level.dat", "level.dat_old", "session.lock", "uid.dat"};
|
||||
+ for (String fileName : files) {
|
||||
+ File origPlayerData = new File(origBaseDir, fileName);
|
||||
+ File targetPlayerData = new File(baseDir, fileName);
|
||||
+ if (origPlayerData.exists() && !targetPlayerData.exists()) {
|
||||
+ if (!printedHeader) {
|
||||
+ LogManager.getLogger().info("- Copying files");
|
||||
+ printedHeader = true;
|
||||
+ }
|
||||
+ LogManager.getLogger().info("- Copying: " + fileName);
|
||||
+ org.apache.commons.io.FileUtils.copyFile(origPlayerData, targetPlayerData);
|
||||
+
|
||||
+ }
|
||||
+ }
|
||||
+ if (printedHeader) {
|
||||
+ LogManager.getLogger().info("**** VERSIONED WORLD - Copying DONE");
|
||||
+ }
|
||||
+ } catch (IOException e) {
|
||||
+ LogManager.getLogger().error("Error copying versioned world data for " + origBaseDir + " to " + baseDir, e);
|
||||
+ com.destroystokyo.paper.util.SneakyThrow.sneaky(e);
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.baseDir = new File(file, s);
|
||||
this.baseDir.mkdirs();
|
||||
this.playerDir = new File(this.baseDir, "playerdata");
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,115 +0,0 @@
|
||||
From a1683b33a2ec42ca595cd7182ffdf5b376c844be Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 11 Aug 2018 00:49:20 -0400
|
||||
Subject: [PATCH] Detect and repair corrupt Region Files
|
||||
|
||||
If the file has partial data written but not the full 8192 bytes,
|
||||
then the server will be unable to load that region file...
|
||||
|
||||
I don't know why mojang only checks for 4096, when anything less than 8192 is a crash.
|
||||
|
||||
But to be safe, it will attempt to back up the file.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
index 3aeac69c26..17648c1c04 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
@@ -27,13 +27,13 @@ public class RegionFile implements AutoCloseable {
|
||||
// Spigot end
|
||||
private static final byte[] a = new byte[4096];
|
||||
private final RandomAccessFile b; private RandomAccessFile getDataFile() { return this.b; } // Paper - OBFHELPER // PAIL dataFile
|
||||
- private final int[] c = new int[1024];
|
||||
- private final int[] d = new int[1024];
|
||||
+ private final int[] c = new int[1024]; private final int[] offsets = c; // Paper - OBFHELPER
|
||||
+ private final int[] d = new int[1024]; private final int[] timestamps = d; // Paper - OBFHELPER
|
||||
private final List<Boolean> e; // PAIL freeSectors
|
||||
|
||||
public RegionFile(File file) throws IOException {
|
||||
this.b = new RandomAccessFile(file, "rw");
|
||||
- if (this.b.length() < 4096L) {
|
||||
+ if (this.b.length() < 8192L) { // Paper - headers should be 8192
|
||||
this.b.write(RegionFile.a);
|
||||
this.b.write(RegionFile.a);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ public class RegionFile implements AutoCloseable {
|
||||
this.b.seek(j * 4 + 4); // Go back to where we were
|
||||
}
|
||||
}
|
||||
- if (k != 0 && (k >> 8) + (length) <= this.e.size()) {
|
||||
+ if (k > 0 && (k >> 8) > 1 && (k >> 8) + (k & 255) <= this.e.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid
|
||||
for (int l = 0; l < (length); ++l) {
|
||||
// Spigot end
|
||||
this.e.set((k >> 8) + l, false);
|
||||
@@ -92,13 +92,14 @@ public class RegionFile implements AutoCloseable {
|
||||
// Spigot start
|
||||
else if (length > 0) {
|
||||
org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Invalid chunk: ({0}, {1}) Offset: {2} Length: {3} runs off end file. {4}", new Object[]{j % 32, (int) (j / 32), k >> 8, length, file});
|
||||
+ deleteChunk(j); // Paper
|
||||
}
|
||||
// Spigot end
|
||||
}
|
||||
|
||||
for (j = 0; j < 1024; ++j) {
|
||||
k = headerAsInts.get(); // Paper
|
||||
- this.d[j] = k;
|
||||
+ if (this.offsets[j] != 0) this.timestamps[j] = k; // Paper - don't set timestamp if it got 0'd above due to corruption
|
||||
}
|
||||
|
||||
this.file = file; // Spigot
|
||||
@@ -349,6 +350,53 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
// Spigot end
|
||||
|
||||
+ // Paper start
|
||||
+ public synchronized void deleteChunk(int j1) {
|
||||
+ backup();
|
||||
+ int k = offsets[j1];
|
||||
+ int x = j1 & 1024;
|
||||
+ int z = j1 >> 2;
|
||||
+ int offset = (k >> 8);
|
||||
+ int len = (k & 255);
|
||||
+ String debug = "idx:" + + j1 + " - " + x + "," + z + " - offset: " + offset + " - len: " + len;
|
||||
+ try {
|
||||
+ timestamps[j1] = 0;
|
||||
+ offsets[j1] = 0;
|
||||
+ RandomAccessFile file = getDataFile();
|
||||
+ file.seek(j1 * 4);
|
||||
+ file.writeInt(0);
|
||||
+ // clear the timestamp
|
||||
+ file.seek(4096 + j1 * 4);
|
||||
+ file.writeInt(0);
|
||||
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Deleted corrupt chunk (" + debug + ") " + this.file.getAbsolutePath(), e);
|
||||
+ } catch (IOException e) {
|
||||
+
|
||||
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Error deleting corrupt chunk (" + debug + ") " + this.file.getAbsolutePath(), e);
|
||||
+ }
|
||||
+ }
|
||||
+ private boolean backedUp = false;
|
||||
+ private synchronized void backup() {
|
||||
+ if (backedUp) {
|
||||
+ return;
|
||||
+ }
|
||||
+ backedUp = true;
|
||||
+ java.text.DateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
||||
+ java.util.Date today = new java.util.Date();
|
||||
+ File corrupt = new File(file.getParentFile(), file.getName() + "." + formatter.format(today) + ".corrupt");
|
||||
+ if (corrupt.exists()) {
|
||||
+ return;
|
||||
+ }
|
||||
+ org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger();
|
||||
+ logger.error("Region file " + file.getAbsolutePath() + " was corrupt. Backing up to " + corrupt.getAbsolutePath() + " and repairing");
|
||||
+ try {
|
||||
+ java.nio.file.Files.copy(file.toPath(), corrupt.toPath());
|
||||
+
|
||||
+ } catch (IOException e) {
|
||||
+ logger.error("Error backing up corrupt file" + file.getAbsolutePath(), e);
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
class ChunkBuffer extends ByteArrayOutputStream {
|
||||
|
||||
private final ChunkCoordIntPair b;
|
||||
--
|
||||
2.22.0
|
||||
|
@ -1,63 +0,0 @@
|
||||
From b03aa2b2428cf6e504fe4f069f208679e666676f Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 15 Apr 2019 02:24:52 +0100
|
||||
Subject: [PATCH] Handle bad chunks more gracefully
|
||||
|
||||
Prior to this change the server would crash when attempting to load a
|
||||
chunk from a region with bad data.
|
||||
|
||||
After this change the server will defer back to vanilla behavior. At
|
||||
this time, that means attempting to generate a chunk in its place
|
||||
(and occasionally just not generating anything and leaving small
|
||||
holes in the world (This statement might not be accurate as of 1.13.x)).
|
||||
|
||||
Should Mojang choose to alter this behavior in the future, this change
|
||||
will simply defer to whatever that new behavior is.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
index c53518a47..6f34d8aea 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFileCache.java
|
||||
@@ -171,8 +171,21 @@ public abstract class RegionFileCache implements AutoCloseable {
|
||||
private static NBTTagCompound readOversizedChunk(RegionFile regionfile, ChunkCoordIntPair chunkCoordinate) throws IOException {
|
||||
synchronized (regionfile) {
|
||||
try (DataInputStream datainputstream = regionfile.getReadStream(chunkCoordinate)) {
|
||||
- NBTTagCompound oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
|
||||
- NBTTagCompound chunk = NBTCompressedStreamTools.readNBT(datainputstream);
|
||||
+ // Paper start - Handle bad chunks more gracefully - also handle similarly with oversized data
|
||||
+ NBTTagCompound oversizedData = null;
|
||||
+
|
||||
+ try {
|
||||
+ oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
|
||||
+ } catch (Exception ex) {}
|
||||
+
|
||||
+ NBTTagCompound chunk;
|
||||
+
|
||||
+ try {
|
||||
+ chunk = NBTCompressedStreamTools.readNBT(datainputstream);
|
||||
+ } catch (final Exception ex) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (oversizedData == null) {
|
||||
return chunk;
|
||||
}
|
||||
@@ -231,8 +244,13 @@ public abstract class RegionFileCache implements AutoCloseable {
|
||||
|
||||
try {
|
||||
if (datainputstream != null) {
|
||||
- nbttagcompound = NBTCompressedStreamTools.a(datainputstream);
|
||||
- return nbttagcompound;
|
||||
+ // Paper start - Handle bad chunks more gracefully
|
||||
+ try {
|
||||
+ return NBTCompressedStreamTools.a(datainputstream);
|
||||
+ } catch (Exception ex) {
|
||||
+ return null;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
nbttagcompound = null;
|
||||
--
|
||||
2.23.0
|
||||
|
@ -1,23 +0,0 @@
|
||||
From 98e10786918880c728f3afc751290cdf5eb14cf5 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 5 Aug 2019 08:24:01 -0700
|
||||
Subject: [PATCH] Preserve old flush on save flag for reliable regionfiles
|
||||
|
||||
Originally this patch was in paper
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
index b487e8060..a8c8ace46 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
||||
@@ -349,7 +349,7 @@ public class RegionFile implements AutoCloseable {
|
||||
}
|
||||
|
||||
// Spigot start - Make region files reliable
|
||||
- private static final boolean FLUSH_ON_SAVE = Boolean.getBoolean("spigot.flush-on-save");
|
||||
+ private static final boolean FLUSH_ON_SAVE = Boolean.getBoolean("spigot.flush-on-save") || Boolean.getBoolean("paper.flush-on-save"); // Paper - preserve old flag
|
||||
private void syncRegionFile() throws IOException {
|
||||
if (!FLUSH_ON_SAVE) {
|
||||
return;
|
||||
--
|
||||
2.23.0
|
||||
|
@ -1,30 +0,0 @@
|
||||
From cf3689f611fad7d903831b63086deefad3cd8e92 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 19 Aug 2019 06:33:17 -0700
|
||||
Subject: [PATCH] Improve POI data saving logic
|
||||
|
||||
- Do not unload data if world saving is disabled
|
||||
- Aggressively target unloading
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/VillagePlace.java b/src/main/java/net/minecraft/server/VillagePlace.java
|
||||
index 0e98b7803..fb99b4306 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillagePlace.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillagePlace.java
|
||||
@@ -132,9 +132,12 @@ public class VillagePlace extends RegionFileSection<VillagePlaceSection> {
|
||||
// Paper start - async chunk io
|
||||
if (this.world == null) {
|
||||
super.a(booleansupplier);
|
||||
- } else {
|
||||
+ } else if (!this.world.isSavingDisabled()) { // Paper - only save if saving is enabled
|
||||
//super.a(booleansupplier); // re-implement below
|
||||
- while (!((RegionFileSection)this).d.isEmpty() && booleansupplier.getAsBoolean()) {
|
||||
+ // Paper start - target unloading aggressively
|
||||
+ int queueTarget = Math.min(this.d.size() - 100, (int)(this.d.size() * 0.96));
|
||||
+ while (!((RegionFileSection)this).d.isEmpty() && (this.d.size() > queueTarget || booleansupplier.getAsBoolean())) {
|
||||
+ // Paper end
|
||||
ChunkCoordIntPair chunkcoordintpair = SectionPosition.a(((RegionFileSection)this).d.firstLong()).u();
|
||||
|
||||
NBTTagCompound data;
|
||||
--
|
||||
2.23.0
|
||||
|
@ -1,75 +0,0 @@
|
||||
From 95da400b09518a7f98754568f41aca73afddb92a Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 Jul 2018 03:39:51 -0400
|
||||
Subject: [PATCH] Avoid Chunk Lookups for Entity/TileEntity Current Chunk
|
||||
|
||||
SPECIAL 1.14.1 NOTE:
|
||||
This patch caused a memory leak since the tile entity's chunk was set to null
|
||||
before it was removed. Ensure this issue is resolved!
|
||||
|
||||
In many places where we simply want the current chunk the entity
|
||||
is in, instead of doing a hashmap lookup for it, we now have access
|
||||
to the object directly on the Entity/TileEntity object we can directly grab.
|
||||
|
||||
Use that local value instead to reduce lookups in many hot places.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 2c92d3390a..3c3a504991 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -789,7 +789,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
if (!tileentity.isRemoved() && tileentity.hasWorld()) {
|
||||
BlockPosition blockposition = tileentity.getPosition();
|
||||
|
||||
- if (this.chunkProvider.a(blockposition) && this.getWorldBorder().a(blockposition)) {
|
||||
+ if (tileentity.getCurrentChunk() != null && this.getWorldBorder().a(blockposition)) { // Paper
|
||||
try {
|
||||
gameprofilerfiller.a(() -> {
|
||||
return String.valueOf(TileEntityTypes.a(tileentity.getTileType()));
|
||||
@@ -828,8 +828,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
this.tileEntityListTick.remove(tileTickPosition--);
|
||||
// Spigot end
|
||||
//this.tileEntityList.remove(tileentity); // Paper - remove unused list
|
||||
- if (this.isLoaded(tileentity.getPosition())) {
|
||||
- this.getChunkAtWorldCoords(tileentity.getPosition()).removeTileEntity(tileentity.getPosition());
|
||||
+ // Paper start - use local chunk reference
|
||||
+ Chunk chunk = tileentity.getCurrentChunk();
|
||||
+ if (chunk != null) {
|
||||
+ chunk.removeTileEntity(tileentity.getPosition());
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -849,8 +852,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
}
|
||||
// CraftBukkit end */
|
||||
|
||||
- if (this.isLoaded(tileentity1.getPosition())) {
|
||||
- Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition());
|
||||
+ Chunk chunk = tileentity1.getCurrentChunk(); // Paper
|
||||
+ if (chunk != null) { // Paper
|
||||
IBlockData iblockdata = chunk.getType(tileentity1.getPosition());
|
||||
|
||||
chunk.setTileEntity(tileentity1.getPosition(), tileentity1);
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index 3739a95c5a..1e00908671 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -1390,9 +1390,12 @@ public class WorldServer extends World {
|
||||
}
|
||||
|
||||
private void removeEntityFromChunk(Entity entity) {
|
||||
- IChunkAccess ichunkaccess = this.getChunkAt(entity.chunkX, entity.chunkZ, ChunkStatus.FULL, false);
|
||||
+ // Paper start
|
||||
+ if (!entity.inChunk) return;
|
||||
+ IChunkAccess ichunkaccess = this.getChunkIfLoaded(entity.chunkX, entity.chunkZ);
|
||||
+ // Paper start
|
||||
|
||||
- if (ichunkaccess instanceof Chunk) {
|
||||
+ if (ichunkaccess != null) { // Paper
|
||||
((Chunk) ichunkaccess).b(entity);
|
||||
}
|
||||
|
||||
--
|
||||
2.24.1
|
||||
|
@ -1,159 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 Jul 2018 15:22:06 -0400
|
||||
Subject: [PATCH] Configurable Bed Search Radius
|
||||
|
||||
Allows you to increase how far to check for a safe place to respawn
|
||||
a player near their bed, allowing a better chance to respawn the
|
||||
player at their bed should it of became obstructed.
|
||||
|
||||
Defaults to vanilla 1.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 6352051ab937d4d365e823a7112e76dc3ec34225..d6a3d882e375ac5a2b6ec8920532db615f4fe4ef 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -372,4 +372,15 @@ public class PaperWorldConfig {
|
||||
private void scanForLegacyEnderDragon() {
|
||||
scanForLegacyEnderDragon = getBoolean("game-mechanics.scan-for-legacy-ender-dragon", true);
|
||||
}
|
||||
+
|
||||
+ public int bedSearchRadius = 1;
|
||||
+ private void bedSearchRadius() {
|
||||
+ bedSearchRadius = getInt("bed-search-radius", 1);
|
||||
+ if (bedSearchRadius < 1) {
|
||||
+ bedSearchRadius = 1;
|
||||
+ }
|
||||
+ if (bedSearchRadius > 1) {
|
||||
+ log("Bed Search Radius: " + bedSearchRadius);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockBed.java b/src/main/java/net/minecraft/server/BlockBed.java
|
||||
index 7604d79468ce8d7d1a4f45872a5db0c700419029..e7bd9061cceba284443b75cc5506e1b9f2ef42e8 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockBed.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockBed.java
|
||||
@@ -199,6 +199,8 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity {
|
||||
|
||||
public static Optional<Vec3D> a(EntityTypes<?> entitytypes, IWorldReader iworldreader, BlockPosition blockposition, int i) {
|
||||
EnumDirection enumdirection = (EnumDirection) iworldreader.getType(blockposition).get(BlockBed.FACING);
|
||||
+ // Paper start - configurable bed search radius
|
||||
+ if (entitytypes == EntityTypes.PLAYER) return findSafePosition(entitytypes, (World) iworldreader, enumdirection, blockposition);
|
||||
int j = blockposition.getX();
|
||||
int k = blockposition.getY();
|
||||
int l = blockposition.getZ();
|
||||
@@ -228,7 +230,104 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
- public static Optional<Vec3D> a(EntityTypes<?> entitytypes, IWorldReader iworldreader, BlockPosition blockposition) {
|
||||
+ private static Optional<Vec3D> findSafePosition(EntityTypes<?> entitytypes, World world, EnumDirection updirection, BlockPosition blockposition){
|
||||
+ int radius = world.paperConfig.bedSearchRadius;
|
||||
+ double angle = Math.PI / 2;
|
||||
+ int tmpX = (int)(updirection.getAdjacentX() * Math.cos(angle) - updirection.getAdjacentZ() * Math.sin(angle));
|
||||
+ int tmpZ = (int)(updirection.getAdjacentX() * Math.sin(angle) + updirection.getAdjacentZ() * Math.cos(angle));
|
||||
+
|
||||
+ EnumDirection rightDirection = EnumDirection.a(tmpX, 0, tmpZ);
|
||||
+ EnumDirection downDirection = updirection.opposite();
|
||||
+ EnumDirection leftDirection = rightDirection.opposite();
|
||||
+
|
||||
+ EnumDirection[] corePositionOutDirection = new EnumDirection[6];
|
||||
+ corePositionOutDirection[0] = updirection;
|
||||
+ corePositionOutDirection[1] = leftDirection;
|
||||
+ corePositionOutDirection[2] = leftDirection;
|
||||
+ corePositionOutDirection[3] = downDirection;
|
||||
+ corePositionOutDirection[4] = rightDirection;
|
||||
+ corePositionOutDirection[5] = rightDirection;
|
||||
+
|
||||
+ BlockPosition[] corePosition = new BlockPosition[6];
|
||||
+ corePosition[0] = blockposition.add(updirection.getAdjacentX(), 0, updirection.getAdjacentZ());
|
||||
+ corePosition[1] = blockposition.add(leftDirection.getAdjacentX(), 0, leftDirection.getAdjacentZ());
|
||||
+ corePosition[2] = corePosition[1].add(downDirection.getAdjacentX(), 0, downDirection.getAdjacentZ());
|
||||
+ corePosition[3] = blockposition.add(2 * downDirection.getAdjacentX(), 0, 2 * downDirection.getAdjacentZ());
|
||||
+ corePosition[5] = blockposition.add(rightDirection.getAdjacentX(), 0, rightDirection.getAdjacentZ());
|
||||
+ corePosition[4] = corePosition[5].add(downDirection.getAdjacentX(), 0, downDirection.getAdjacentZ());
|
||||
+
|
||||
+ BlockPosition[] tmpPosition = new BlockPosition[8];
|
||||
+ EnumDirection[] tmpPositionDirection = new EnumDirection[8];
|
||||
+ tmpPositionDirection[0] = rightDirection;
|
||||
+ tmpPositionDirection[1] = leftDirection;
|
||||
+ tmpPositionDirection[2] = updirection;
|
||||
+ tmpPositionDirection[3] = downDirection;
|
||||
+ tmpPositionDirection[4] = leftDirection;
|
||||
+ tmpPositionDirection[5] = rightDirection;
|
||||
+ tmpPositionDirection[6] = downDirection;
|
||||
+ tmpPositionDirection[7] = updirection;
|
||||
+
|
||||
+ BlockPosition pos;
|
||||
+ Optional<Vec3D> vector;
|
||||
+ for (int r = 1; r <= radius; r++) {
|
||||
+ int h = 0;
|
||||
+ while (h <= 1) {
|
||||
+ int numIterated = 0;
|
||||
+ for (int index = (int)(Math.random() * corePosition.length); numIterated < corePosition.length; index = (index+1) % corePosition.length) {
|
||||
+ numIterated++;
|
||||
+
|
||||
+ pos = corePosition[index].add(0, h, 0);
|
||||
+ vector = isSafeRespawn(entitytypes, world, pos, 0);
|
||||
+ if (vector.isPresent()) {
|
||||
+ return vector;
|
||||
+ }
|
||||
+ }
|
||||
+ tmpPosition[0] = corePosition[0].add(0, h, 0);
|
||||
+ tmpPosition[1] = corePosition[0].add(0, h, 0);
|
||||
+ tmpPosition[2] = corePosition[1].add(0, h, 0);
|
||||
+ tmpPosition[3] = corePosition[2].add(0, h, 0);
|
||||
+ tmpPosition[4] = corePosition[3].add(0, h, 0);
|
||||
+ tmpPosition[5] = corePosition[3].add(0, h, 0);
|
||||
+ tmpPosition[6] = corePosition[4].add(0, h, 0);
|
||||
+ tmpPosition[7] = corePosition[5].add(0, h, 0);
|
||||
+ for (int rr = 1; rr <= r; rr++){
|
||||
+ numIterated = 0;
|
||||
+ for (int index = (int)(Math.random() * tmpPosition.length); numIterated < tmpPosition.length; index = (index+1) % tmpPosition.length) {
|
||||
+ numIterated++;
|
||||
+ tmpPosition[index] = tmpPosition[index].add(tmpPositionDirection[index].getAdjacentX(), 0, tmpPositionDirection[index].getAdjacentZ());
|
||||
+ pos = tmpPosition[index];
|
||||
+
|
||||
+ vector = isSafeRespawn(entitytypes, world, pos, 0);
|
||||
+ if (vector.isPresent()) {
|
||||
+ return vector;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ switch (h) {
|
||||
+ case 0:
|
||||
+ h = -1;
|
||||
+ break;
|
||||
+ case -1:
|
||||
+ h = -2;
|
||||
+ break;
|
||||
+ case -2:
|
||||
+ h = Integer.MAX_VALUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ for (int index = 0; index < corePosition.length; index++) {
|
||||
+ EnumDirection tmp = corePositionOutDirection[index];
|
||||
+ corePosition[index] = corePosition[index].add(tmp.getAdjacentX(), 0, tmp.getAdjacentZ());
|
||||
+ }
|
||||
+ }
|
||||
+ return Optional.empty();
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
+ // Paper start -- add maxBelow param
|
||||
+ public static Optional<Vec3D> a(EntityTypes<?> entitytypes, IWorldReader iworldreader, BlockPosition blockposition) { return isSafeRespawn(entitytypes, iworldreader, blockposition, 2); }
|
||||
+ public static Optional<Vec3D> isSafeRespawn(EntityTypes<?> entitytypes, IWorldReader iworldreader, BlockPosition blockposition, int maxBelow) {
|
||||
+ // Paper end
|
||||
VoxelShape voxelshape = iworldreader.getType(blockposition).getCollisionShape(iworldreader, blockposition);
|
||||
|
||||
if (voxelshape.c(EnumDirection.EnumAxis.Y) > 0.4375D) {
|
||||
@@ -236,7 +335,7 @@ public class BlockBed extends BlockFacingHorizontal implements ITileEntity {
|
||||
} else {
|
||||
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = blockposition.i();
|
||||
|
||||
- while (blockposition_mutableblockposition.getY() >= 0 && blockposition.getY() - blockposition_mutableblockposition.getY() <= 2 && iworldreader.getType(blockposition_mutableblockposition).getCollisionShape(iworldreader, blockposition_mutableblockposition).isEmpty()) {
|
||||
+ while (blockposition_mutableblockposition.getY() >= 0 && blockposition.getY() - blockposition_mutableblockposition.getY() <= maxBelow && iworldreader.getType(blockposition_mutableblockposition).getCollisionShape(iworldreader, blockposition_mutableblockposition).isEmpty()) { // Paper -- configurable max distance to search below
|
||||
blockposition_mutableblockposition.c(EnumDirection.DOWN);
|
||||
}
|
||||
|
@ -1,99 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 17 Sep 2018 23:05:31 -0400
|
||||
Subject: [PATCH] Support Overriding World Seeds
|
||||
|
||||
Allows you to add to paper.yml
|
||||
|
||||
seed-overrides:
|
||||
world_name: some seed value
|
||||
|
||||
This will ignore every where a seed is set/created/loaded and force
|
||||
a world to use the specified seed.
|
||||
|
||||
This seed will end up being saved to the world data file, so it is
|
||||
a permanent change in that it won't go back if you remove it from paper.yml
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
index 214b577b326bc794fa3721deb6171228dd4f25e6..559e6b42ba5bf0ea92cccbabd2ef1d4c27b03064 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
||||
@@ -11,6 +11,7 @@ import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
+import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -19,6 +20,7 @@ import com.google.common.collect.Lists;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
+import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import co.aikar.timings.Timings;
|
||||
@@ -310,4 +312,23 @@ public class PaperConfig {
|
||||
}
|
||||
tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit);
|
||||
}
|
||||
+
|
||||
+ public static Map<String, Long> seedOverride = new java.util.HashMap<>();
|
||||
+ private static void worldSeedOverrides() {
|
||||
+ ConfigurationSection seeds = config.getConfigurationSection("seed-overrides");
|
||||
+ if (seeds != null) {
|
||||
+ TimingsManager.hiddenConfigs.add("seed-overrides");
|
||||
+ for (String key : seeds.getKeys(false)) {
|
||||
+ String seedString = seeds.getString(key);
|
||||
+ long seed;
|
||||
+ try {
|
||||
+ seed = Long.parseLong(seedString);
|
||||
+ } catch (Exception e) {
|
||||
+ seed = (long) seedString.hashCode();
|
||||
+ }
|
||||
+ log("Seed Override: " + key + " => " + seed);
|
||||
+ seedOverride.put(key, seed);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 3b89f62ab0522d23f47fd59c2f06fa7d0eacb7af..85f989829b5ad1d7681b57cf68519a4806b26ea1 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -378,7 +378,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
||||
this.convertWorld(name); // Run conversion now
|
||||
|
||||
org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name);
|
||||
- WorldSettings worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype);
|
||||
+ WorldSettings worldsettings = new WorldSettings(com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(name, i), this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); // Paper
|
||||
worldsettings.setGeneratorSettings(jsonelement);
|
||||
|
||||
if (j == 0) {
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldData.java b/src/main/java/net/minecraft/server/WorldData.java
|
||||
index 561b6d94696eebc255279f45d2ca6b88b2490f78..95518e54d1fd7ada51df1cdc3562affccd48bfcb 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldData.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldData.java
|
||||
@@ -127,7 +127,7 @@ public class WorldData {
|
||||
this.d = nbttagcompound2.getBoolean("Snapshot");
|
||||
}
|
||||
|
||||
- this.e = nbttagcompound.getLong("RandomSeed");
|
||||
+ this.e = com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(nbttagcompound.getString("LevelName"), nbttagcompound.getLong("RandomSeed")); // Paper
|
||||
if (nbttagcompound.hasKeyOfType("generatorName", 8)) {
|
||||
String s = nbttagcompound.getString("generatorName");
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index d15a857b30511bda9bbeddf651b4633e4bea473d..011d0927da7a2a67dcd6d75e3af07d38f30acf81 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1016,7 +1016,7 @@ public final class CraftServer implements Server {
|
||||
WorldSettings worldSettings;
|
||||
// See MinecraftServer.a(String, String, long, WorldType, JsonElement)
|
||||
if (worlddata == null) {
|
||||
- worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type);
|
||||
+ worldSettings = new WorldSettings(com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(name, creator.seed()), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type); // Paper
|
||||
JsonElement parsedSettings = new JsonParser().parse(creator.generatorSettings());
|
||||
if (parsedSettings.isJsonObject()) {
|
||||
worldSettings.setGeneratorSettings(parsedSettings.getAsJsonObject());
|
@ -1,101 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: JellySquid <jellysquid+atwork@protonmail.com>
|
||||
Date: Sat, 9 May 2020 16:25:21 -0400
|
||||
Subject: [PATCH] Implement JellySquid's Entity Collision optimisations patch
|
||||
|
||||
Optimizes Full Block voxel collisions, and removes streams from Entity collisions
|
||||
|
||||
Original code by JellySquid, licensed under GNU Lesser General Public License v3.0
|
||||
you can find the original code on https://github.com/jellysquid3/lithium-fabric/tree/1.15.x/fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
index 3eefbf4d5f10b53f930759a0afa5661253b92c60..5e20dba0d011d20b714d784cb4a545a05bbf6f9c 100644
|
||||
--- a/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
+++ b/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
@@ -115,11 +115,24 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
|
||||
if ((j2 != 1 || iblockdata.f()) && (j2 != 2 || iblockdata.getBlock() == Blocks.MOVING_PISTON)) {
|
||||
VoxelShape voxelshape2 = iblockdata.b((IBlockAccess) ICollisionAccess.this, blockposition_mutableblockposition, voxelshapecollision);
|
||||
- VoxelShape voxelshape3 = voxelshape2.a((double) k1, (double) l1, (double) i2);
|
||||
|
||||
- if (VoxelShapes.c(voxelshape, voxelshape3, OperatorBoolean.AND)) {
|
||||
- consumer.accept(voxelshape3);
|
||||
- return true;
|
||||
+ // Paper start - Lithium Collision Optimizations
|
||||
+ if (voxelshape2 == VoxelShapes.empty()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (voxelshape2 == VoxelShapes.fullCube()) {
|
||||
+ if (axisalignedbb.intersects(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D)) {
|
||||
+ consumer.accept(voxelshape2.offset(x, y, z));
|
||||
+ return true;
|
||||
+ }
|
||||
+ } else {
|
||||
+ VoxelShape shape = voxelshape2.offset(x, y, z);
|
||||
+ if (VoxelShapes.applyOperation(shape, voxelshape, OperatorBoolean.AND)) {
|
||||
+ consumer.accept(shape);
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
index 5135308fb6137a34ed6fd061f0a210de6de4e81c..d434aaaaf0ab6a18ab0fe5ad0bf8ed4662f49120 100644
|
||||
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
@@ -52,20 +52,41 @@ public interface IEntityAccess {
|
||||
// Paper end - optimise hard collision
|
||||
|
||||
default Stream<VoxelShape> b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set) {
|
||||
- if (axisalignedbb.a() < 1.0E-7D) {
|
||||
+ // Paper start - remove streams from entity collision
|
||||
+ if (axisalignedbb.getAverageSideLength() < 1.0E-7D) {
|
||||
return Stream.empty();
|
||||
- } else {
|
||||
- AxisAlignedBB axisalignedbb1 = axisalignedbb.g(1.0E-7D);
|
||||
- Stream<AxisAlignedBB> stream = ((entity != null && entity.hardCollides()) ? this.getEntities(entity, axisalignedbb) : this.getHardCollidingEntities(entity, axisalignedbb1)).stream().filter((entity1) -> { // Paper - decompile fix // Paper - optimise hard collision
|
||||
- return !set.contains(entity1);
|
||||
- }).filter((entity1) -> {
|
||||
- return entity == null || !entity.isSameVehicle(entity1);
|
||||
- }).flatMap((entity1) -> {
|
||||
- return Stream.of(entity1.au(), entity == null ? null : entity.j(entity1)); // Paper - optimise hard collision - diff on change, these are the methods that only hard colliding entities override
|
||||
- }).filter(Objects::nonNull);
|
||||
-
|
||||
- return stream.filter(axisalignedbb1::c).map(VoxelShapes::a);
|
||||
+
|
||||
}
|
||||
+ AxisAlignedBB selection = axisalignedbb.grow(1.0E-7D);
|
||||
+ List<Entity> entities = entity != null && entity.hardCollides() ? getEntities(entity, selection) : getHardCollidingEntities(entity, selection);
|
||||
+ List<VoxelShape> shapes = new java.util.ArrayList<>();
|
||||
+
|
||||
+ for (Entity otherEntity : entities) {
|
||||
+ if (!set.isEmpty() && set.contains(otherEntity)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (entity != null && entity.isSameVehicle(otherEntity)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ AxisAlignedBB otherEntityBox = otherEntity.getCollisionBox();
|
||||
+
|
||||
+ if (otherEntityBox != null && selection.intersects(otherEntityBox)) {
|
||||
+ shapes.add(VoxelShapes.of(otherEntityBox));
|
||||
+ }
|
||||
+
|
||||
+ if (entity != null) {
|
||||
+ AxisAlignedBB otherEntityHardBox = entity.getHardCollisionBox(otherEntity);
|
||||
+
|
||||
+ if (otherEntityHardBox != null && selection.intersects(otherEntityHardBox)) {
|
||||
+ shapes.add(VoxelShapes.of(otherEntityHardBox));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return shapes.stream();
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
@Nullable
|
@ -1,178 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 9 May 2020 18:36:27 -0400
|
||||
Subject: [PATCH] Remove some Streams usage in Entity Collision
|
||||
|
||||
While there is more down the collision system, remove some of the wrapping
|
||||
Spliterator stuff as even this wrapper stream has shown up in profiling.
|
||||
|
||||
With other collision optimizations, we might also even avoid inner streams too.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/GeneratorAccess.java b/src/main/java/net/minecraft/server/GeneratorAccess.java
|
||||
index e865a5694f78fb9273a0625ab2c30b87d0711a90..5648ba73c533f622c35c808decdb305f8a1cf6b0 100644
|
||||
--- a/src/main/java/net/minecraft/server/GeneratorAccess.java
|
||||
+++ b/src/main/java/net/minecraft/server/GeneratorAccess.java
|
||||
@@ -52,6 +52,7 @@ public interface GeneratorAccess extends IEntityAccess, IWorldReader, VirtualLev
|
||||
this.a((EntityHuman) null, i, blockposition, j);
|
||||
}
|
||||
|
||||
+ @Override default java.util.List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set, boolean returnFast) {return IEntityAccess.super.getEntityCollisions(entity, axisalignedbb, set, returnFast); } // Paper
|
||||
@Override
|
||||
default Stream<VoxelShape> b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set) {
|
||||
return IEntityAccess.super.b(entity, axisalignedbb, set);
|
||||
diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
index 5e20dba0d011d20b714d784cb4a545a05bbf6f9c..5a21205a49606b294de4cd27b60438c6a5b3c526 100644
|
||||
--- a/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
+++ b/src/main/java/net/minecraft/server/ICollisionAccess.java
|
||||
@@ -44,19 +44,40 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
|
||||
default boolean a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set) {
|
||||
try { if (entity != null) entity.collisionLoadChunks = true; // Paper
|
||||
- return this.c(entity, axisalignedbb, set).allMatch(VoxelShape::isEmpty);
|
||||
+ // Paper start - reduce stream usage
|
||||
+ java.util.List<VoxelShape> blockCollisions = getBlockCollision(entity, axisalignedbb, true);
|
||||
+ for (int i = 0; i < blockCollisions.size(); i++) {
|
||||
+ VoxelShape blockCollision = blockCollisions.get(i);
|
||||
+ if (!blockCollision.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return getEntityCollisions(entity, axisalignedbb, set, true).isEmpty();
|
||||
+ // Paper end
|
||||
} finally { if (entity != null) entity.collisionLoadChunks = false; } // Paper
|
||||
}
|
||||
|
||||
+ default java.util.List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set, boolean returnFast) { return java.util.Collections.emptyList(); } // Paper
|
||||
default Stream<VoxelShape> b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
default Stream<VoxelShape> c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set) {
|
||||
- return Streams.concat(new Stream[]{this.b(entity, axisalignedbb), this.b(entity, axisalignedbb, set)});
|
||||
+ // Paper start - reduce stream usage
|
||||
+ java.util.List<VoxelShape> blockCollisions = getBlockCollision(entity, axisalignedbb, false);
|
||||
+ java.util.List<VoxelShape> entityCollisions = getEntityCollisions(entity, axisalignedbb, set, false);
|
||||
+ return Stream.concat(blockCollisions.stream(), entityCollisions.stream());
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
default Stream<VoxelShape> b(@Nullable final Entity entity, AxisAlignedBB axisalignedbb) {
|
||||
+ // Paper start - reduce stream usage
|
||||
+ java.util.List<VoxelShape> collision = getBlockCollision(entity, axisalignedbb, false);
|
||||
+ return !collision.isEmpty() ? collision.stream() : Stream.empty();
|
||||
+ }
|
||||
+
|
||||
+ default java.util.List<VoxelShape> getBlockCollision(@Nullable final Entity entity, AxisAlignedBB axisalignedbb, boolean returnFast) {
|
||||
+ // Paper end
|
||||
int i = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 1;
|
||||
int j = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 1;
|
||||
int k = MathHelper.floor(axisalignedbb.minY - 1.0E-7D) - 1;
|
||||
@@ -68,19 +89,19 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
final BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
|
||||
final VoxelShape voxelshape = VoxelShapes.a(axisalignedbb);
|
||||
|
||||
- return StreamSupport.stream(new AbstractSpliterator<VoxelShape>(Long.MAX_VALUE, 1280) {
|
||||
- boolean a = entity == null;
|
||||
-
|
||||
- public boolean tryAdvance(Consumer<? super VoxelShape> consumer) {
|
||||
- if (!this.a) {
|
||||
- this.a = true;
|
||||
+ // Paper start - reduce stream usage (this part done by Aikar)
|
||||
+ java.util.List<VoxelShape> collisions = new java.util.ArrayList<>();
|
||||
+ if (true) {//return StreamSupport.stream(new AbstractSpliterator<VoxelShape>(Long.MAX_VALUE, 1280) {
|
||||
+ if (true) { //public boolean tryAdvance(Consumer<? super VoxelShape> consumer) {*/ // Paper
|
||||
+ if (entity != null) {
|
||||
+ // Paper end
|
||||
VoxelShape voxelshape1 = ICollisionAccess.this.getWorldBorder().a();
|
||||
boolean flag = VoxelShapes.c(voxelshape1, VoxelShapes.a(entity.getBoundingBox().shrink(1.0E-7D)), OperatorBoolean.AND);
|
||||
boolean flag1 = VoxelShapes.c(voxelshape1, VoxelShapes.a(entity.getBoundingBox().g(1.0E-7D)), OperatorBoolean.AND);
|
||||
|
||||
if (!flag && flag1) {
|
||||
- consumer.accept(voxelshape1);
|
||||
- return true;
|
||||
+ collisions.add(voxelshape1); // Paper
|
||||
+ if (returnFast) return collisions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,9 +125,8 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
);
|
||||
if (iblockdata == null) {
|
||||
if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) {
|
||||
- VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z)));
|
||||
- consumer.accept(voxelshape3);
|
||||
- return true;
|
||||
+ collisions.add(VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))));
|
||||
+ if (returnFast) return collisions;
|
||||
}
|
||||
} else {
|
||||
//blockposition_mutableblockposition.d(k1, l1, i2); // moved up
|
||||
@@ -123,14 +143,14 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
|
||||
if (voxelshape2 == VoxelShapes.fullCube()) {
|
||||
if (axisalignedbb.intersects(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D)) {
|
||||
- consumer.accept(voxelshape2.offset(x, y, z));
|
||||
- return true;
|
||||
+ collisions.add(voxelshape2.offset(x, y, z));
|
||||
+ if (returnFast) return collisions;
|
||||
}
|
||||
} else {
|
||||
VoxelShape shape = voxelshape2.offset(x, y, z);
|
||||
if (VoxelShapes.applyOperation(shape, voxelshape, OperatorBoolean.AND)) {
|
||||
- consumer.accept(shape);
|
||||
- return true;
|
||||
+ collisions.add(shape);
|
||||
+ if (returnFast) return collisions;
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
@@ -139,8 +159,9 @@ public interface ICollisionAccess extends IBlockAccess {
|
||||
}
|
||||
}
|
||||
|
||||
- return false;
|
||||
+ //return false; // Paper
|
||||
}
|
||||
- }, false);
|
||||
+ } //}, false);
|
||||
+ return collisions; // Paper
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
index d434aaaaf0ab6a18ab0fe5ad0bf8ed4662f49120..3bc57ef91d557383178533b0cc87a71a521d6b3e 100644
|
||||
--- a/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
+++ b/src/main/java/net/minecraft/server/IEntityAccess.java
|
||||
@@ -55,8 +55,10 @@ public interface IEntityAccess {
|
||||
// Paper start - remove streams from entity collision
|
||||
if (axisalignedbb.getAverageSideLength() < 1.0E-7D) {
|
||||
return Stream.empty();
|
||||
-
|
||||
}
|
||||
+ return getEntityCollisions(entity, axisalignedbb, set, false).stream();
|
||||
+ }
|
||||
+ default List<VoxelShape> getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set<Entity> set, boolean returnFast) {
|
||||
AxisAlignedBB selection = axisalignedbb.grow(1.0E-7D);
|
||||
List<Entity> entities = entity != null && entity.hardCollides() ? getEntities(entity, selection) : getHardCollidingEntities(entity, selection);
|
||||
List<VoxelShape> shapes = new java.util.ArrayList<>();
|
||||
@@ -74,6 +76,7 @@ public interface IEntityAccess {
|
||||
|
||||
if (otherEntityBox != null && selection.intersects(otherEntityBox)) {
|
||||
shapes.add(VoxelShapes.of(otherEntityBox));
|
||||
+ if (returnFast) return shapes;
|
||||
}
|
||||
|
||||
if (entity != null) {
|
||||
@@ -81,11 +84,12 @@ public interface IEntityAccess {
|
||||
|
||||
if (otherEntityHardBox != null && selection.intersects(otherEntityHardBox)) {
|
||||
shapes.add(VoxelShapes.of(otherEntityHardBox));
|
||||
+ if (returnFast) return shapes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- return shapes.stream();
|
||||
+ return shapes;
|
||||
// Paper end
|
||||
}
|
||||
|
@ -1,273 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 26 May 2020 21:32:05 -0400
|
||||
Subject: [PATCH] Optimize Villagers
|
||||
|
||||
This change reimplements the entire BehaviorFindPosition method to
|
||||
get rid of all of the streams, and implement the logic in a more sane way.
|
||||
|
||||
We keep vanilla behavior 100% the same with this change, just wrote more
|
||||
optimal, as we can abort iterating POI's as soon as we find a match....
|
||||
|
||||
One slight change is that Minecraft adds a random delay before a POI is
|
||||
attempted again. I've increased the amount of that delay based on the distance
|
||||
to said POI, so farther POI's will not be attempted as often.
|
||||
|
||||
Additionally, we spiral out, so we favor local POI's before we ever favor farther POI's.
|
||||
|
||||
We also try to pathfind 1 POI at a time instead of collecting multiple POI's then tossing them
|
||||
all to the pathfinder, so that once we get a match we can return before even looking at other
|
||||
POI's.
|
||||
|
||||
This benefits us in that ideally, a villager will constantly find the near POI's and
|
||||
not even try to pathfind to the farther POI. Trying to pathfind to distant POI's is
|
||||
what causes significant lag.
|
||||
|
||||
Other improvements here is to stop spamming the POI manager with empty nullables.
|
||||
Vanilla used them to represent if they needed to load POI data off disk or not.
|
||||
|
||||
Well, we load POI data async on chunk load, so we have it, and we surely do not ever
|
||||
want to load POI data sync either for unloaded chunks!
|
||||
|
||||
So this massively reduces object count in the POI hashmaps, resulting in less hash collions,
|
||||
and also less memory use.
|
||||
|
||||
Additionally, unemployed villagers were using significant time due to major ineffeciency in
|
||||
the code rebuilding data that is static every single invocation for every POI type...
|
||||
|
||||
So we cache that and only rebuild it if professions change, which should be never unless
|
||||
a plugin manipulates and adds custom professions, which it will handle by rebuilding.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BehaviorFindPosition.java b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
|
||||
index 35eb3a5a61145e94d5b0c77c0eb13bfa46fac23b..6861b1a345496a83900b0ef702ba34315a030ef6 100644
|
||||
--- a/src/main/java/net/minecraft/server/BehaviorFindPosition.java
|
||||
+++ b/src/main/java/net/minecraft/server/BehaviorFindPosition.java
|
||||
@@ -29,8 +29,55 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
||||
|
||||
protected void a(WorldServer worldserver, EntityCreature entitycreature, long i) {
|
||||
this.f = 0;
|
||||
- this.d = worldserver.getTime() + (long) worldserver.getRandom().nextInt(20);
|
||||
+ this.d = worldserver.getTime() + (long) java.util.concurrent.ThreadLocalRandom.current().nextInt(20); // Paper
|
||||
VillagePlace villageplace = worldserver.B();
|
||||
+
|
||||
+ // Paper start - replace implementation completely
|
||||
+ BlockPosition blockposition2 = new BlockPosition(entitycreature);
|
||||
+ int dist = 48;
|
||||
+ int requiredDist = dist * dist;
|
||||
+ int cdist = Math.floorDiv(dist, 16);
|
||||
+ Predicate<VillagePlaceType> predicate = this.a.c();
|
||||
+ int maxPoiAttempts = 4;
|
||||
+ int poiAttempts = 0;
|
||||
+ OUT:
|
||||
+ for (ChunkCoordIntPair chunkcoordintpair : MCUtil.getSpiralOutChunks(blockposition2, cdist)) {
|
||||
+ for (int i1 = 0; i1 < 16; i1++) {
|
||||
+ java.util.Optional<VillagePlaceSection> section = villageplace.getSection(SectionPosition.a(chunkcoordintpair, i1).v());
|
||||
+ if (section == null || !section.isPresent()) continue;
|
||||
+ for (java.util.Map.Entry<VillagePlaceType, java.util.Set<VillagePlaceRecord>> e : section.get().getRecords().entrySet()) {
|
||||
+ if (!predicate.test(e.getKey())) continue;
|
||||
+ for (VillagePlaceRecord record : e.getValue()) {
|
||||
+ if (!record.hasVacancy()) continue;
|
||||
+
|
||||
+ BlockPosition pos = record.getPosition();
|
||||
+ long key = pos.asLong();
|
||||
+ if (this.e.containsKey(key)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ double poiDist = pos.distanceSquared(blockposition2);
|
||||
+ if (poiDist <= (double) requiredDist) {
|
||||
+ this.e.put(key, (long) (this.d + Math.sqrt(poiDist) * 4)); // use dist instead of 40 to blacklist longer if farther distance
|
||||
+ ++poiAttempts;
|
||||
+ PathEntity pathentity = entitycreature.getNavigation().a(com.google.common.collect.ImmutableSet.of(pos), 8, false, this.a.d());
|
||||
+
|
||||
+ if (pathentity != null && pathentity.h()) {
|
||||
+ record.decreaseVacancy();
|
||||
+ GlobalPos globalPos = GlobalPos.create(worldserver.getWorldProvider().getDimensionManager(), pos);
|
||||
+ entitycreature.getBehaviorController().setMemory(this.b, globalPos);
|
||||
+ break OUT;
|
||||
+ }
|
||||
+ if (poiAttempts >= maxPoiAttempts) {
|
||||
+ break OUT;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Clean up - vanilla does this only when it runs out, but that would push it to try farther POI's...
|
||||
+ this.e.long2LongEntrySet().removeIf((entry) -> entry.getLongValue() < this.d);
|
||||
+ /*
|
||||
Predicate<BlockPosition> predicate = (blockposition) -> {
|
||||
long j = blockposition.asLong();
|
||||
|
||||
@@ -61,6 +108,6 @@ public class BehaviorFindPosition extends Behavior<EntityCreature> {
|
||||
return entry.getLongValue() < this.d;
|
||||
});
|
||||
}
|
||||
-
|
||||
+ */ // Paper end
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/RegionFileSection.java b/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||
index a6d8ef5eb44f3f851a3a1be4032ca21ab1d7f2b2..c3e8a0145d63843736d2060f978cdf38df359563 100644
|
||||
--- a/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||
+++ b/src/main/java/net/minecraft/server/RegionFileSection.java
|
||||
@@ -51,29 +51,15 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
|
||||
|
||||
@Nullable
|
||||
protected Optional<R> c(long i) {
|
||||
- return (Optional) this.c.get(i);
|
||||
+ return this.c.getOrDefault(i, Optional.empty()); // Paper
|
||||
}
|
||||
|
||||
+ protected final Optional<R> getSection(long i) { return d(i); } // Paper - OBFHELPER
|
||||
protected Optional<R> d(long i) {
|
||||
- SectionPosition sectionposition = SectionPosition.a(i);
|
||||
-
|
||||
- if (this.b(sectionposition)) {
|
||||
- return Optional.empty();
|
||||
- } else {
|
||||
- Optional<R> optional = this.c(i);
|
||||
-
|
||||
- if (optional != null) {
|
||||
- return optional;
|
||||
- } else {
|
||||
- this.b(sectionposition.u());
|
||||
- optional = this.c(i);
|
||||
- if (optional == null) {
|
||||
- throw (IllegalStateException) SystemUtils.c(new IllegalStateException());
|
||||
- } else {
|
||||
- return optional;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ // Paper start - replace method - never load POI data sync, we load this in chunk load already, reduce ops
|
||||
+ // If it's an unloaded chunk, well too bad.
|
||||
+ return this.c(i);
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
protected boolean b(SectionPosition sectionposition) {
|
||||
@@ -117,7 +103,7 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
|
||||
private <T> void a(ChunkCoordIntPair chunkcoordintpair, DynamicOps<T> dynamicops, @Nullable T t0) {
|
||||
if (t0 == null) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
- this.c.put(SectionPosition.a(chunkcoordintpair, i).v(), Optional.empty());
|
||||
+ //this.c.put(SectionPosition.a(chunkcoordintpair, i).v(), Optional.empty()); // Paper - NO!!!
|
||||
}
|
||||
} else {
|
||||
Dynamic<T> dynamic = new Dynamic(dynamicops, t0);
|
||||
@@ -135,7 +121,7 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
|
||||
}, dynamic2);
|
||||
});
|
||||
|
||||
- this.c.put(i1, optional);
|
||||
+ if (optional.isPresent()) this.c.put(i1, optional); // Paper - NO!!!
|
||||
optional.ifPresent((minecraftserializable) -> {
|
||||
this.b(i1);
|
||||
if (flag) {
|
||||
@@ -199,7 +185,7 @@ public class RegionFileSection<R extends MinecraftSerializable> extends RegionFi
|
||||
if (optional != null && optional.isPresent()) {
|
||||
this.d.add(i);
|
||||
} else {
|
||||
- RegionFileSection.LOGGER.warn("No data for position: {}", SectionPosition.a(i));
|
||||
+ //RegionFileSection.LOGGER.warn("No data for position: {}", SectionPosition.a(i)); // Paper - hush
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/VillagePlaceRecord.java b/src/main/java/net/minecraft/server/VillagePlaceRecord.java
|
||||
index 1e9d7a3f902eb4571b93bb0e58cba966365f07b8..44535a3e2c3320aac472c5a7ee557fac7bab2530 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillagePlaceRecord.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillagePlaceRecord.java
|
||||
@@ -32,6 +32,7 @@ public class VillagePlaceRecord implements MinecraftSerializable {
|
||||
return dynamicops.createMap(ImmutableMap.of(dynamicops.createString("pos"), this.a.a(dynamicops), dynamicops.createString("type"), dynamicops.createString(IRegistry.POINT_OF_INTEREST_TYPE.getKey(this.b).toString()), dynamicops.createString("free_tickets"), dynamicops.createInt(this.c)));
|
||||
}
|
||||
|
||||
+ protected final boolean decreaseVacancy() { return b(); } // Paper - OBFHELPER
|
||||
protected boolean b() {
|
||||
if (this.c <= 0) {
|
||||
return false;
|
||||
@@ -42,6 +43,7 @@ public class VillagePlaceRecord implements MinecraftSerializable {
|
||||
}
|
||||
}
|
||||
|
||||
+ protected final boolean increaseVacancy() { return c(); } // Paper - OBFHELPER
|
||||
protected boolean c() {
|
||||
if (this.c >= this.b.b()) {
|
||||
return false;
|
||||
@@ -52,14 +54,17 @@ public class VillagePlaceRecord implements MinecraftSerializable {
|
||||
}
|
||||
}
|
||||
|
||||
+ public final boolean hasVacancy() { return d(); } // Paper - OBFHELPER
|
||||
public boolean d() {
|
||||
return this.c > 0;
|
||||
}
|
||||
|
||||
+ public final boolean isOccupied() { return e(); } // Paper - OBFHELPER
|
||||
public boolean e() {
|
||||
return this.c != this.b.b();
|
||||
}
|
||||
|
||||
+ public final BlockPosition getPosition() { return f(); } // Paper
|
||||
public BlockPosition f() {
|
||||
return this.a;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/VillagePlaceSection.java b/src/main/java/net/minecraft/server/VillagePlaceSection.java
|
||||
index 3f2602dbe0995f8d01d4a1428d919405d711a205..436b064c3b277143075386fc9a71027fb5962681 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillagePlaceSection.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillagePlaceSection.java
|
||||
@@ -23,7 +23,7 @@ public class VillagePlaceSection implements MinecraftSerializable {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final Short2ObjectMap<VillagePlaceRecord> b = new Short2ObjectOpenHashMap();
|
||||
- private final Map<VillagePlaceType, Set<VillagePlaceRecord>> c = Maps.newHashMap();
|
||||
+ private final Map<VillagePlaceType, Set<VillagePlaceRecord>> c = Maps.newHashMap(); public final Map<VillagePlaceType, Set<VillagePlaceRecord>> getRecords() { return c; } // Paper - OBFHELPER
|
||||
private final Runnable d;
|
||||
private boolean e;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/VillagePlaceType.java b/src/main/java/net/minecraft/server/VillagePlaceType.java
|
||||
index ab3e054cd2f38756a5d802d4d981022318ab047d..c1f293fc98d3efb4665cfb9036f208b842fc8e36 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillagePlaceType.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillagePlaceType.java
|
||||
@@ -12,8 +12,14 @@ import java.util.stream.Stream;
|
||||
|
||||
public class VillagePlaceType {
|
||||
|
||||
+ static Set<VillagePlaceType> professionCache; // Paper
|
||||
private static final Predicate<VillagePlaceType> v = (villageplacetype) -> {
|
||||
- return ((Set) IRegistry.VILLAGER_PROFESSION.d().map(VillagerProfession::b).collect(Collectors.toSet())).contains(villageplacetype);
|
||||
+ // Paper start
|
||||
+ if (professionCache == null) {
|
||||
+ professionCache = IRegistry.VILLAGER_PROFESSION.d().map(VillagerProfession::b).collect(Collectors.toSet());
|
||||
+ }
|
||||
+ return professionCache.contains(villageplacetype);
|
||||
+ // Paper end
|
||||
};
|
||||
public static final Predicate<VillagePlaceType> a = (villageplacetype) -> {
|
||||
return true;
|
||||
@@ -89,11 +95,11 @@ public class VillagePlaceType {
|
||||
}
|
||||
|
||||
private static VillagePlaceType a(String s, Set<IBlockData> set, int i, int j) {
|
||||
- return a((VillagePlaceType) IRegistry.POINT_OF_INTEREST_TYPE.a(new MinecraftKey(s), (Object) (new VillagePlaceType(s, set, i, j))));
|
||||
+ return a((VillagePlaceType) IRegistry.POINT_OF_INTEREST_TYPE.a(new MinecraftKey(s), (new VillagePlaceType(s, set, i, j)))); // Paper - decompile error
|
||||
}
|
||||
|
||||
private static VillagePlaceType a(String s, Set<IBlockData> set, int i, Predicate<VillagePlaceType> predicate, int j) {
|
||||
- return a((VillagePlaceType) IRegistry.POINT_OF_INTEREST_TYPE.a(new MinecraftKey(s), (Object) (new VillagePlaceType(s, set, i, predicate, j))));
|
||||
+ return a((VillagePlaceType) IRegistry.POINT_OF_INTEREST_TYPE.a(new MinecraftKey(s), (new VillagePlaceType(s, set, i, predicate, j)))); // Paper - decompile error
|
||||
}
|
||||
|
||||
private static VillagePlaceType a(VillagePlaceType villageplacetype) {
|
||||
diff --git a/src/main/java/net/minecraft/server/VillagerProfession.java b/src/main/java/net/minecraft/server/VillagerProfession.java
|
||||
index c38296165b33698bc15fe49a2de0d0d19cfb910a..f9d7a16c79a4e3ffe8b6e7ed469236a93892f01d 100644
|
||||
--- a/src/main/java/net/minecraft/server/VillagerProfession.java
|
||||
+++ b/src/main/java/net/minecraft/server/VillagerProfession.java
|
||||
@@ -61,6 +61,7 @@ public class VillagerProfession {
|
||||
}
|
||||
|
||||
static VillagerProfession a(String s, VillagePlaceType villageplacetype, ImmutableSet<Item> immutableset, ImmutableSet<Block> immutableset1, @Nullable SoundEffect soundeffect) {
|
||||
+ VillagePlaceType.professionCache = null; // Paper
|
||||
return (VillagerProfession) IRegistry.a((IRegistry) IRegistry.VILLAGER_PROFESSION, new MinecraftKey(s), (Object) (new VillagerProfession(s, villageplacetype, immutableset, immutableset1, soundeffect)));
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mystiflow <mystiflow@gmail.com>
|
||||
Date: Fri, 6 Jul 2018 13:21:30 +0100
|
||||
Subject: [PATCH] Send nearby packets from world player list not server list
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
|
||||
index 939cec9121c051c5459084e4078740a7607803f3..917ea676d9ce2ea0b10e3a75b7f35f011c3599f6 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerList.java
|
||||
@@ -910,8 +910,25 @@ public abstract class PlayerList {
|
||||
}
|
||||
|
||||
public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, DimensionManager dimensionmanager, Packet<?> packet) {
|
||||
- for (int i = 0; i < this.players.size(); ++i) {
|
||||
- EntityPlayer entityplayer = (EntityPlayer) this.players.get(i);
|
||||
+ // Paper start - Use world list instead of server list where preferable
|
||||
+ sendPacketNearby(entityhuman, d0, d1, d2, d3, dimensionmanager, null, packet); // Retained for compatibility
|
||||
+ }
|
||||
+
|
||||
+ public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, WorldServer world, Packet<?> packet) {
|
||||
+ sendPacketNearby(entityhuman, d0, d1, d2, d3, world.worldProvider.getDimensionManager(), world, packet);
|
||||
+ }
|
||||
+
|
||||
+ public void sendPacketNearby(@Nullable EntityHuman entityhuman, double d0, double d1, double d2, double d3, DimensionManager dimensionmanager, @Nullable WorldServer world, Packet<?> packet) {
|
||||
+ if (world == null && entityhuman != null && entityhuman.world instanceof WorldServer) {
|
||||
+ world = (WorldServer) entityhuman.world;
|
||||
+ }
|
||||
+
|
||||
+ List<? extends EntityHuman> players1 = world == null ? players : world.players;
|
||||
+ for (int j = 0; j < players1.size(); ++j) {
|
||||
+ EntityHuman entity = players1.get(j);
|
||||
+ if (!(entity instanceof EntityPlayer)) continue;
|
||||
+ EntityPlayer entityplayer = (EntityPlayer) entity;
|
||||
+ // Paper end
|
||||
|
||||
// CraftBukkit start - Test if player receiving packet can see the source of the packet
|
||||
if (entityhuman != null && entityhuman instanceof EntityPlayer && !entityplayer.getBukkitEntity().canSee(((EntityPlayer) entityhuman).getBukkitEntity())) {
|
||||
@@ -919,7 +936,7 @@ public abstract class PlayerList {
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
- if (entityplayer != entityhuman && entityplayer.dimension == dimensionmanager) {
|
||||
+ if (entityplayer != entityhuman && (world != null || entityplayer.dimension == dimensionmanager)) { // Paper
|
||||
double d4 = d0 - entityplayer.locX();
|
||||
double d5 = d1 - entityplayer.locY();
|
||||
double d6 = d2 - entityplayer.locZ();
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index 3067ab76d94c58fbfd52fac6754bf6d6d7f01d09..6e878c9b9dee511812df5ea2491d953f677c3f58 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -1276,7 +1276,7 @@ public class WorldServer extends World {
|
||||
}
|
||||
// CraftBukkit end
|
||||
this.globalEntityList.add(entitylightning);
|
||||
- this.server.getPlayerList().sendPacketNearby((EntityHuman) null, entitylightning.locX(), entitylightning.locY(), entitylightning.locZ(), 512.0D, this.worldProvider.getDimensionManager(), new PacketPlayOutSpawnEntityWeather(entitylightning));
|
||||
+ this.server.getPlayerList().sendPacketNearby((EntityHuman) null, entitylightning.locX(), entitylightning.locY(), entitylightning.locZ(), 512.0D, this, new PacketPlayOutSpawnEntityWeather(entitylightning)); // Paper - use world instead of dimension
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1408,7 +1408,7 @@ public class WorldServer extends World {
|
||||
BlockActionData blockactiondata = (BlockActionData) this.I.removeFirst();
|
||||
|
||||
if (this.a(blockactiondata)) {
|
||||
- this.server.getPlayerList().sendPacketNearby((EntityHuman) null, (double) blockactiondata.a().getX(), (double) blockactiondata.a().getY(), (double) blockactiondata.a().getZ(), 64.0D, this.worldProvider.getDimensionManager(), new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.b(), blockactiondata.c(), blockactiondata.d()));
|
||||
+ this.server.getPlayerList().sendPacketNearby((EntityHuman) null, (double) blockactiondata.a().getX(), (double) blockactiondata.a().getY(), (double) blockactiondata.a().getZ(), 64.0D, this, new PacketPlayOutBlockAction(blockactiondata.a(), blockactiondata.b(), blockactiondata.c(), blockactiondata.d()));
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 6c3cd51d92d2271cd216c42c18733d549fbe668d..ad951812835b1fa786e964c533efc4547c57b7a2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -2122,7 +2122,7 @@ public class CraftWorld implements World {
|
||||
double z = loc.getZ();
|
||||
|
||||
PacketPlayOutCustomSoundEffect packet = new PacketPlayOutCustomSoundEffect(new MinecraftKey(sound), SoundCategory.valueOf(category.name()), new Vec3D(x, y, z), volume, pitch);
|
||||
- world.getMinecraftServer().getPlayerList().sendPacketNearby(null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, this.world.getWorldProvider().getDimensionManager(), packet);
|
||||
+ world.getMinecraftServer().getPlayerList().sendPacketNearby(null, x, y, z, volume > 1.0F ? 16.0F * volume : 16.0D, this.world, packet); // Paper - this.world.dimension -> this.world
|
||||
}
|
||||
|
||||
private static Map<String, GameRules.GameRuleKey<?>> gamerules;
|
@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brokkonaut <hannos17@gmx.de>
|
||||
Date: Tue, 25 Sep 2018 06:53:43 +0200
|
||||
Subject: [PATCH] Avoid dimension id collisions
|
||||
|
||||
getDimensionId() returns the dimension id - 1. So without this patch
|
||||
we would reuse an existing dimension id, if some other dimension was
|
||||
unloaded before.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
index 011d0927da7a2a67dcd6d75e3af07d38f30acf81..3c43f318c4cff914128e2f7060516ce7ebb6e1c9 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
||||
@@ -1002,7 +1002,7 @@ public final class CraftServer implements Server {
|
||||
boolean used = false;
|
||||
do {
|
||||
for (WorldServer server : console.getWorlds()) {
|
||||
- used = server.getWorldProvider().getDimensionManager().getDimensionID() == dimension;
|
||||
+ used = server.getWorldProvider().getDimensionManager().getDimensionID() + 1 == dimension; // Paper - getDimensionID returns the dimension - 1, so we have to add 1
|
||||
if (used) {
|
||||
dimension++;
|
||||
break;
|
@ -1,19 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: BillyGalbreath <Blake.Galbreath@GMail.com>
|
||||
Date: Fri, 19 Oct 2018 19:38:45 -0500
|
||||
Subject: [PATCH] Fix MC-93764
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldProviderTheEnd.java b/src/main/java/net/minecraft/server/WorldProviderTheEnd.java
|
||||
index 9d4fcf8bcfdc5c09fe0a7ba18a229be3b0e7115c..4b9760709df89ab8378184cb643a9079685b6230 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldProviderTheEnd.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldProviderTheEnd.java
|
||||
@@ -27,7 +27,7 @@ public class WorldProviderTheEnd extends WorldProvider {
|
||||
|
||||
@Override
|
||||
public float a(long i, float f) {
|
||||
- return 0.0F;
|
||||
+ return 0.5F; // Paper - fix MC-93764
|
||||
}
|
||||
|
||||
@Override
|
@ -1,223 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Fri, 24 May 2019 07:53:16 +0100
|
||||
Subject: [PATCH] Fix some generation concurrency issues
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index a59a965104a2c2977fa3b3d0a199913df268bbd3..69db339c29c8f06026f05b0b5bb8019099af3fdf 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -86,6 +86,23 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
private int tileTickPosition;
|
||||
public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
||||
public java.util.ArrayDeque<BlockRedstoneTorch.RedstoneUpdateInfo> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
|
||||
+ // Paper start - yes this is hacky as shit
|
||||
+ RegionLimitedWorldAccess regionLimited;
|
||||
+ World originalWorld;
|
||||
+ public World regionLimited(RegionLimitedWorldAccess limitedWorldAccess) {
|
||||
+ try {
|
||||
+ World clone = (World) super.clone();
|
||||
+ clone.regionLimited = limitedWorldAccess;
|
||||
+ clone.originalWorld = this;
|
||||
+ return clone;
|
||||
+ } catch (CloneNotSupportedException e1) {
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+ ChunkCoordIntPair[] strongholdCoords;
|
||||
+ List<StructureStart> strongholdStuctures = Lists.newArrayList();
|
||||
+ final java.lang.Object stuctureLock = new Object();
|
||||
+ // Paper end
|
||||
|
||||
public CraftWorld getWorld() {
|
||||
return this.world;
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java b/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java
|
||||
index 22e14fe1e98c8439f8db74c9464137a497fdaf7c..e2af6d43b2eafeecad8fd070fc70195c7b0bb93f 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenFeatureStateProviderWeighted.java
|
||||
@@ -23,18 +23,18 @@ public class WorldGenFeatureStateProviderWeighted extends WorldGenFeatureStatePr
|
||||
this(new WeightedList<>(dynamic.get("entries").orElseEmptyList(), IBlockData::a));
|
||||
}
|
||||
|
||||
- public WorldGenFeatureStateProviderWeighted a(IBlockData iblockdata, int i) {
|
||||
+ public synchronized WorldGenFeatureStateProviderWeighted a(IBlockData iblockdata, int i) { // Paper
|
||||
this.b.a(iblockdata, i);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
- public IBlockData a(Random random, BlockPosition blockposition) {
|
||||
+ public synchronized IBlockData a(Random random, BlockPosition blockposition) { // Paper
|
||||
return (IBlockData) this.b.b(random);
|
||||
}
|
||||
|
||||
@Override
|
||||
- public <T> T a(DynamicOps<T> dynamicops) {
|
||||
+ public synchronized <T> T a(DynamicOps<T> dynamicops) { // Paper
|
||||
Builder<T, T> builder = ImmutableMap.builder();
|
||||
|
||||
builder.put(dynamicops.createString("type"), dynamicops.createString(IRegistry.t.getKey(this.a).toString())).put(dynamicops.createString("entries"), this.b.a(dynamicops, (iblockdata) -> {
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldGenStronghold.java b/src/main/java/net/minecraft/server/WorldGenStronghold.java
|
||||
index fc4348b60242e4a9d8612c3b8ce01711c32f4b1c..44be7169ffd5961df28d21a319d2cc7569662baf 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldGenStronghold.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldGenStronghold.java
|
||||
@@ -10,10 +10,12 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyConfiguration> {
|
||||
|
||||
+ /* // Paper start - no shared state
|
||||
private boolean a;
|
||||
private ChunkCoordIntPair[] aq;
|
||||
private final List<StructureStart> ar = Lists.newArrayList();
|
||||
private long as;
|
||||
+ */
|
||||
|
||||
public WorldGenStronghold(Function<Dynamic<?>, ? extends WorldGenFeatureEmptyConfiguration> function) {
|
||||
super(function);
|
||||
@@ -21,16 +23,22 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
|
||||
@Override
|
||||
public boolean a(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int i, int j, BiomeBase biomebase) {
|
||||
+ // Paper start
|
||||
+ /*
|
||||
if (this.as != chunkgenerator.getSeed()) {
|
||||
this.d();
|
||||
}
|
||||
+ */
|
||||
+ final World world = chunkgenerator.getWorld();
|
||||
|
||||
- if (!this.a) {
|
||||
+ synchronized (world.stuctureLock) {
|
||||
+ if ( world.strongholdCoords == null) {
|
||||
this.a(chunkgenerator);
|
||||
- this.a = true;
|
||||
- }
|
||||
+ // this.a = true;
|
||||
+ }}
|
||||
+ // Paper end
|
||||
|
||||
- ChunkCoordIntPair[] achunkcoordintpair = this.aq;
|
||||
+ ChunkCoordIntPair[] achunkcoordintpair = world.strongholdCoords; // Paper
|
||||
int k = achunkcoordintpair.length;
|
||||
|
||||
for (int l = 0; l < k; ++l) {
|
||||
@@ -45,9 +53,11 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
}
|
||||
|
||||
private void d() {
|
||||
+ /* // Paper
|
||||
this.a = false;
|
||||
this.aq = null;
|
||||
this.ar.clear();
|
||||
+ */ // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,25 +75,32 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
return 8;
|
||||
}
|
||||
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public synchronized BlockPosition getNearestGeneratedFeature(World world, ChunkGenerator<? extends GeneratorSettingsDefault> chunkgenerator, BlockPosition blockposition, int i, boolean flag) {
|
||||
if (!chunkgenerator.getWorldChunkManager().a(this)) {
|
||||
return null;
|
||||
} else {
|
||||
+ // Paper start - no shared state
|
||||
+ /*
|
||||
if (this.as != world.getSeed()) {
|
||||
this.d();
|
||||
}
|
||||
+ */
|
||||
|
||||
- if (!this.a) {
|
||||
- this.a(chunkgenerator);
|
||||
- this.a = true;
|
||||
+ synchronized (world.stuctureLock) {
|
||||
+ if ( world.strongholdCoords == null) {
|
||||
+ this.a(chunkgenerator);
|
||||
+ //this.a = true;
|
||||
+ }
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
BlockPosition blockposition1 = null;
|
||||
BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition();
|
||||
double d0 = Double.MAX_VALUE;
|
||||
- ChunkCoordIntPair[] achunkcoordintpair = this.aq;
|
||||
+ ChunkCoordIntPair[] achunkcoordintpair = world.strongholdCoords; // Paper
|
||||
int j = achunkcoordintpair.length;
|
||||
|
||||
for (int k = 0; k < j; ++k) {
|
||||
@@ -106,7 +123,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
}
|
||||
|
||||
private void a(ChunkGenerator<?> chunkgenerator) {
|
||||
- this.as = chunkgenerator.getSeed();
|
||||
+ //this.as = chunkgenerator.getSeed(); // Paper
|
||||
List<BiomeBase> list = Lists.newArrayList();
|
||||
Iterator iterator = IRegistry.BIOME.iterator();
|
||||
|
||||
@@ -122,15 +139,15 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
int j = chunkgenerator.getSettings().f();
|
||||
int k = chunkgenerator.getSettings().g();
|
||||
|
||||
- this.aq = new ChunkCoordIntPair[j];
|
||||
+ ChunkCoordIntPair[] strongholdCoords = chunkgenerator.getWorld().strongholdCoords = new ChunkCoordIntPair[j]; // Paper
|
||||
int l = 0;
|
||||
- Iterator iterator1 = this.ar.iterator();
|
||||
+ Iterator iterator1 = chunkgenerator.getWorld().strongholdStuctures.iterator(); // Paper
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
StructureStart structurestart = (StructureStart) iterator1.next();
|
||||
|
||||
- if (l < this.aq.length) {
|
||||
- this.aq[l++] = new ChunkCoordIntPair(structurestart.f(), structurestart.g());
|
||||
+ if (l < strongholdCoords.length) { // Paper
|
||||
+ strongholdCoords[l++] = new ChunkCoordIntPair(structurestart.f(), structurestart.g()); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,11 +157,11 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
double d0 = random.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
int i1 = l;
|
||||
|
||||
- if (l < this.aq.length) {
|
||||
+ if (l < strongholdCoords.length) { // Paper
|
||||
int j1 = 0;
|
||||
int k1 = 0;
|
||||
|
||||
- for (int l1 = 0; l1 < this.aq.length; ++l1) {
|
||||
+ for (int l1 = 0; l1 < strongholdCoords.length; ++l1) { // Paper
|
||||
double d1 = (double) (4 * i + i * k1 * 6) + (random.nextDouble() - 0.5D) * (double) i * 2.5D;
|
||||
int i2 = (int) Math.round(Math.cos(d0) * d1);
|
||||
int j2 = (int) Math.round(Math.sin(d0) * d1);
|
||||
@@ -156,7 +173,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
}
|
||||
|
||||
if (l1 >= i1) {
|
||||
- this.aq[l1] = new ChunkCoordIntPair(i2, j2);
|
||||
+ strongholdCoords[l1] = new ChunkCoordIntPair(i2, j2); // Paper
|
||||
}
|
||||
|
||||
d0 += 6.283185307179586D / (double) k;
|
||||
@@ -165,7 +182,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
++k1;
|
||||
j1 = 0;
|
||||
k += 2 * k / (k1 + 1);
|
||||
- k = Math.min(k, this.aq.length - l1);
|
||||
+ k = Math.min(k, strongholdCoords.length - l1); // Paper
|
||||
d0 += random.nextDouble() * 3.141592653589793D * 2.0D;
|
||||
}
|
||||
}
|
||||
@@ -207,7 +224,7 @@ public class WorldGenStronghold extends StructureGenerator<WorldGenFeatureEmptyC
|
||||
this.a(chunkgenerator.getSeaLevel(), this.d, 10);
|
||||
} while (this.b.isEmpty() || worldgenstrongholdpieces_worldgenstrongholdstart.b == null);
|
||||
|
||||
- ((WorldGenStronghold) this.l()).ar.add(this);
|
||||
+ chunkgenerator.getWorld().strongholdStuctures.add(this); // Paper - this worries me, this is never cleared, even in vanilla (world seed never changes "world", and that appears to be the only relevant world)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Sun, 15 Sep 2019 11:32:32 -0500
|
||||
Subject: [PATCH] Fix zero-tick instant grow farms MC-113809
|
||||
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 62fe175dc4f00cc9cab6cbd828b57e25740b3793..f6f5f9dea6284582e9a175c0875273ee1db76076 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -552,6 +552,11 @@ public class PaperWorldConfig {
|
||||
disableRelativeProjectileVelocity = getBoolean("game-mechanics.disable-relative-projectile-velocity", false);
|
||||
}
|
||||
|
||||
+ public boolean fixZeroTickInstantGrowFarms = true;
|
||||
+ private void fixZeroTickInstantGrowFarms() {
|
||||
+ fixZeroTickInstantGrowFarms = getBoolean("fix-zero-tick-instant-grow-farms", fixZeroTickInstantGrowFarms);
|
||||
+ }
|
||||
+
|
||||
public boolean altItemDespawnRateEnabled;
|
||||
public Map<Material, Integer> altItemDespawnRateMap;
|
||||
private void altItemDespawnRate() {
|
||||
diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
|
||||
index 540fcce1dd4d64dee51e2594f2199fac5299c6a0..e29ec958b3519d92cda215a50e97e6852d71c684 100644
|
||||
--- a/src/main/java/net/minecraft/server/Block.java
|
||||
+++ b/src/main/java/net/minecraft/server/Block.java
|
||||
@@ -46,6 +46,7 @@ public class Block implements IMaterial {
|
||||
private final float g;
|
||||
protected final BlockStateList<Block, IBlockData> blockStateList;
|
||||
private IBlockData blockData;
|
||||
+ public boolean randomTick = false; // Paper - fix MC-113809
|
||||
protected final boolean v;
|
||||
private final boolean i;
|
||||
private final boolean j;
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockBamboo.java b/src/main/java/net/minecraft/server/BlockBamboo.java
|
||||
index c482aad3e3e255dfe13b622859ed61b780a9e08e..02c548dd9c9a97bfb55d39ba2f6d4ab85ada0573 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockBamboo.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockBamboo.java
|
||||
@@ -85,6 +85,7 @@ public class BlockBamboo extends Block implements IBlockFragilePlantElement {
|
||||
if (!iblockdata.canPlace(worldserver, blockposition)) {
|
||||
worldserver.b(blockposition, true);
|
||||
} else if ((Integer) iblockdata.get(BlockBamboo.f) == 0) {
|
||||
+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809
|
||||
if (random.nextInt(Math.max(1, (int) (100.0F / worldserver.spigotConfig.bambooModifier) * 3)) == 0 && worldserver.isEmpty(blockposition.up()) && worldserver.getLightLevel(blockposition.up(), 0) >= 9) { // Spigot
|
||||
int i = this.b(worldserver, blockposition) + 1;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockCactus.java b/src/main/java/net/minecraft/server/BlockCactus.java
|
||||
index e0974e256f0f10e047b9eb8e362982c6578d2d98..3524fcb927865d7b8754d9fbf85b853f09b94bb8 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockCactus.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockCactus.java
|
||||
@@ -21,6 +21,7 @@ public class BlockCactus extends Block {
|
||||
if (!iblockdata.canPlace(worldserver, blockposition)) {
|
||||
worldserver.b(blockposition, true);
|
||||
} else {
|
||||
+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809
|
||||
BlockPosition blockposition1 = blockposition.up();
|
||||
|
||||
if (worldserver.isEmpty(blockposition1)) {
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockChorusFlower.java b/src/main/java/net/minecraft/server/BlockChorusFlower.java
|
||||
index d70b52cadf1b76eff7984127837b0a3aa36f6a0e..b624cf38047e242569d30ee4e3ad971455b5ff0a 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockChorusFlower.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockChorusFlower.java
|
||||
@@ -22,6 +22,7 @@ public class BlockChorusFlower extends Block {
|
||||
if (!iblockdata.canPlace(worldserver, blockposition)) {
|
||||
worldserver.b(blockposition, true);
|
||||
} else {
|
||||
+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809
|
||||
BlockPosition blockposition1 = blockposition.up();
|
||||
|
||||
if (worldserver.isEmpty(blockposition1) && blockposition1.getY() < 256) {
|
||||
diff --git a/src/main/java/net/minecraft/server/BlockReed.java b/src/main/java/net/minecraft/server/BlockReed.java
|
||||
index 55b07444e1d769952f2a411b1b5d1032565af8a1..3bc3c5aa29f45cd2ee1c0401b1ee1b1d49e81926 100644
|
||||
--- a/src/main/java/net/minecraft/server/BlockReed.java
|
||||
+++ b/src/main/java/net/minecraft/server/BlockReed.java
|
||||
@@ -23,6 +23,7 @@ public class BlockReed extends Block {
|
||||
if (!iblockdata.canPlace(worldserver, blockposition)) {
|
||||
worldserver.b(blockposition, true);
|
||||
} else if (worldserver.isEmpty(blockposition.up())) {
|
||||
+ if (worldserver.paperConfig.fixZeroTickInstantGrowFarms && !randomTick) return; // Paper - fix MC-113809
|
||||
int i;
|
||||
|
||||
for (i = 1; worldserver.getType(blockposition.down(i)).getBlock() == this; ++i) {
|
||||
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
index 80e2a15bebe93939dc7b43b17b8116965438c062..3ecc73d021c09fbcad74dd62aced460771f86038 100644
|
||||
--- a/src/main/java/net/minecraft/server/WorldServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/WorldServer.java
|
||||
@@ -589,7 +589,9 @@ public class WorldServer extends World {
|
||||
IBlockData iblockdata = chunksection.getType(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
|
||||
|
||||
if (iblockdata.q()) {
|
||||
+ iblockdata.getBlock().randomTick = true; // Paper - fix MC-113809
|
||||
iblockdata.b(this, blockposition2, this.random);
|
||||
+ iblockdata.getBlock().randomTick = false; // Paper - fix MC-113809
|
||||
}
|
||||
|
||||
Fluid fluid = iblockdata.getFluid();
|
@ -1,21 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 15 Dec 2019 19:41:28 +0000
|
||||
Subject: [PATCH] Fix spawn radius being treated as 0
|
||||
|
||||
|
||||
Not needed anymore?
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
index 81f00141776a1767b907d14ef04f60b576110128..86bbbbaefca9ace5327d8bc2456939eb9ae8966a 100644
|
||||
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
||||
@@ -129,7 +129,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
||||
public final BlockPosition getSpawnPoint(WorldServer worldserver) {
|
||||
BlockPosition blockposition = worldserver.getSpawn();
|
||||
|
||||
- if (worldserver.worldProvider.g() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) {
|
||||
+ if (worldserver.worldProvider.f() && worldserver.getWorldData().getGameType() != EnumGamemode.ADVENTURE) { // Paper
|
||||
int i = Math.max(0, this.server.a(worldserver));
|
||||
int j = MathHelper.floor(worldserver.getWorldBorder().b((double) blockposition.getX(), (double) blockposition.getZ()));
|
||||
|
@ -1,110 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Phoenix616 <mail@moep.tv>
|
||||
Date: Mon, 13 Jan 2020 15:40:32 +0100
|
||||
Subject: [PATCH] Seed based feature search
|
||||
|
||||
This fixes the issue where the server will load surrounding chunks up to
|
||||
a radius of 100 chunks in order to search for features e.g. when running
|
||||
the /locate command or for treasure maps (issue #2312).
|
||||
This is done by using the same seed checking functionality that is used
|
||||
by the server when generating these features before actually attempting
|
||||
to load the chunk to check if a feature is available in it.
|
||||
|
||||
The only downside of this is that it breaks once the seed or generator
|
||||
changes but this should usually not happen. A config option to disable
|
||||
this improvement is added though in case that should ever be necessary.
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index cab503bd5c34d12b38a2f5deed6d3feb9287b370..2ab810f71beaa608af2194165696817a2cde4b92 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -357,6 +357,12 @@ public class PaperWorldConfig {
|
||||
}
|
||||
}
|
||||
|
||||
+ public boolean seedBasedFeatureSearch = true;
|
||||
+ private void seedBasedFeatureSearch() {
|
||||
+ seedBasedFeatureSearch = getBoolean("seed-based-feature-search", seedBasedFeatureSearch);
|
||||
+ log("Feature search is based on seed: " + seedBasedFeatureSearch);
|
||||
+ }
|
||||
+
|
||||
public int maxCollisionsPerEntity;
|
||||
private void maxEntityCollision() {
|
||||
maxCollisionsPerEntity = getInt( "max-entity-collisions", this.spigotConfig.getInt("max-entity-collisions", 8) );
|
||||
diff --git a/src/main/java/net/minecraft/server/BiomeManager.java b/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
index e96f544f126371f6f629a20ba3c99ba42d31e04a..68423645df3aa08d4c5126ff068d5e566927f744 100644
|
||||
--- a/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
+++ b/src/main/java/net/minecraft/server/BiomeManager.java
|
||||
@@ -12,10 +12,12 @@ public class BiomeManager {
|
||||
this.c = genlayerzoomer;
|
||||
}
|
||||
|
||||
+ public BiomeManager withProvider(WorldChunkManager worldchunkmanager) { return a(worldchunkmanager); } // Paper - OBFHELPER
|
||||
public BiomeManager a(WorldChunkManager worldchunkmanager) {
|
||||
return new BiomeManager(worldchunkmanager, this.b, this.c);
|
||||
}
|
||||
|
||||
+ public BiomeBase getBiome(BlockPosition blockposition) { return a(blockposition); } // Paper - OBFHELPER
|
||||
public BiomeBase a(BlockPosition blockposition) {
|
||||
return this.c.a(this.b, blockposition.getX(), blockposition.getY(), blockposition.getZ(), this.a);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
index 5a975f6bc60922ac872ec9c00c9150ce7dcad046..f617636a22167b06ac8073aa25efd8c7099155f0 100644
|
||||
--- a/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
+++ b/src/main/java/net/minecraft/server/ChunkCoordIntPair.java
|
||||
@@ -68,10 +68,12 @@ public class ChunkCoordIntPair {
|
||||
}
|
||||
}
|
||||
|
||||
+ public int getBlockX() { return d(); } // Paper - OBFHELPER
|
||||
public int d() {
|
||||
return this.x << 4;
|
||||
}
|
||||
|
||||
+ public int getBlockZ() { return e(); } // Paper - OBFHELPER
|
||||
public int e() {
|
||||
return this.z << 4;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/StructureGenerator.java b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
index e8ce2ecf23e58d82febf6b9441e0004e69cdc858..acfe732af5b9f63fc2f6b78499defabe2e73ee45 100644
|
||||
--- a/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/server/StructureGenerator.java
|
||||
@@ -109,6 +109,15 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
if (flag1 || flag2) {
|
||||
ChunkCoordIntPair chunkcoordintpair = this.a(chunkgenerator, seededrandom, j, k, i1, j1);
|
||||
if (!world.getWorldBorder().isChunkInBounds(chunkcoordintpair.x, chunkcoordintpair.z)) { continue; } // Paper
|
||||
+ // Paper start - seed based feature search
|
||||
+ if (world.paperConfig.seedBasedFeatureSearch) {
|
||||
+ BiomeManager biomeManager = world.getBiomeManager().withProvider(chunkgenerator.getWorldChunkManager());
|
||||
+ BiomeBase biomeBase = biomeManager.getBiome(new BlockPosition(chunkcoordintpair.getBlockX() + 9, 0, chunkcoordintpair.getBlockZ() + 9));
|
||||
+ if (!shouldGenerate(biomeManager, chunkgenerator, seededrandom, chunkcoordintpair.x, chunkcoordintpair.z, biomeBase)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
StructureStart structurestart = world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z, ChunkStatus.STRUCTURE_STARTS).a(this.b());
|
||||
|
||||
if (structurestart != null && structurestart.e()) {
|
||||
@@ -165,6 +174,7 @@ public abstract class StructureGenerator<C extends WorldGenFeatureConfiguration>
|
||||
return new ChunkCoordIntPair(i + k, j + l);
|
||||
}
|
||||
|
||||
+ public boolean shouldGenerate(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int chunkX, int chunkZ, BiomeBase biomebase) { return a(biomemanager, chunkgenerator, random, chunkX, chunkZ, biomebase); } // Paper - OBFHELPER
|
||||
public abstract boolean a(BiomeManager biomemanager, ChunkGenerator<?> chunkgenerator, Random random, int i, int j, BiomeBase biomebase);
|
||||
|
||||
public abstract StructureGenerator.a a();
|
||||
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
||||
index 0fa2b335db297c6270090d3dd24ced92eab12825..d7ac4c86d170a8d7d816f86ac691c3b5129a20ba 100644
|
||||
--- a/src/main/java/net/minecraft/server/World.java
|
||||
+++ b/src/main/java/net/minecraft/server/World.java
|
||||
@@ -1570,8 +1570,8 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
||||
return this.methodProfiler;
|
||||
}
|
||||
|
||||
- @Override
|
||||
- public BiomeManager d() {
|
||||
+ public BiomeManager getBiomeManager() { return d(); } // Paper - OBFHELPER
|
||||
+ @Override public BiomeManager d() {
|
||||
return this.biomeManager;
|
||||
}
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Callahan <mr.callahhh@gmail.com>
|
||||
Date: Wed, 8 Apr 2020 18:00:17 -0500
|
||||
Subject: [PATCH] Port 20w15a Villager AI optimizations - DROP 1.16
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/BehaviorController.java b/src/main/java/net/minecraft/server/BehaviorController.java
|
||||
index 7c6e687707cdf32638eee41e549818a494cd45ab..396b64ea0fc8a04d9e0aac289033d3d82385b86e 100644
|
||||
--- a/src/main/java/net/minecraft/server/BehaviorController.java
|
||||
+++ b/src/main/java/net/minecraft/server/BehaviorController.java
|
||||
@@ -38,30 +38,22 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
this.g = Sets.newHashSet();
|
||||
this.h = Activity.IDLE;
|
||||
this.i = -9999L;
|
||||
- collection.forEach((memorymoduletype) -> {
|
||||
- Optional optional = (Optional) this.memories.put(memorymoduletype, Optional.empty());
|
||||
- });
|
||||
- collection1.forEach((sensortype) -> {
|
||||
- Sensor sensor = (Sensor) this.sensors.put(sensortype, sensortype.a());
|
||||
- });
|
||||
- this.sensors.values().forEach((sensor) -> {
|
||||
- Iterator iterator = sensor.a().iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- MemoryModuleType<?> memorymoduletype = (MemoryModuleType) iterator.next();
|
||||
-
|
||||
- this.memories.put(memorymoduletype, Optional.empty());
|
||||
+ // Paper start - Port 20w15a pathfinder optimizations
|
||||
+ for (final MemoryModuleType<?> memoryModuleType : collection) {
|
||||
+ this.memories.put(memoryModuleType, Optional.empty());
|
||||
+ }
|
||||
+ for (final SensorType<? extends Sensor<? super E>> sensorType : collection1) {
|
||||
+ this.sensors.put(sensorType, sensorType.a());
|
||||
+ }
|
||||
+ for (final Sensor<? super E> sensor : this.sensors.values()) {
|
||||
+ for (final MemoryModuleType<?> memoryModuleType : sensor.a()) {
|
||||
+ this.memories.put(memoryModuleType, Optional.empty());
|
||||
}
|
||||
-
|
||||
- });
|
||||
- Iterator iterator = dynamic.get("memories").asMap(Function.identity(), Function.identity()).entrySet().iterator();
|
||||
-
|
||||
- while (iterator.hasNext()) {
|
||||
- Entry<Dynamic<T>, Dynamic<T>> entry = (Entry) iterator.next();
|
||||
-
|
||||
- this.a((MemoryModuleType) IRegistry.MEMORY_MODULE_TYPE.get(new MinecraftKey(((Dynamic) entry.getKey()).asString(""))), (Dynamic) entry.getValue());
|
||||
}
|
||||
-
|
||||
+ for (final Map.Entry<Dynamic<T>, Dynamic<T>> entry : dynamic.get("memories").asMap(Function.identity(), Function.identity()).entrySet()) {
|
||||
+ this.a((MemoryModuleType) IRegistry.MEMORY_MODULE_TYPE.get(new MinecraftKey((entry.getKey()).asString(""))), entry.getValue());
|
||||
+ }
|
||||
+ // Paper end - Port 20w15a pathfinder optimizations
|
||||
}
|
||||
|
||||
public boolean hasMemory(MemoryModuleType<?> memorymoduletype) {
|
||||
@@ -69,7 +61,7 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
}
|
||||
|
||||
private <T, U> void a(MemoryModuleType<U> memorymoduletype, Dynamic<T> dynamic) {
|
||||
- this.setMemory(memorymoduletype, ((Function) memorymoduletype.getSerializer().orElseThrow(RuntimeException::new)).apply(dynamic));
|
||||
+ this.setMemory(memorymoduletype, (memorymoduletype.getSerializer().orElseThrow(RuntimeException::new)).apply(dynamic)); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public <U> void removeMemory(MemoryModuleType<U> memorymoduletype) {
|
||||
@@ -113,13 +105,21 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
this.f = set;
|
||||
}
|
||||
|
||||
+ // Paper start - Port 20w15a pathfinder optimizations
|
||||
@Deprecated
|
||||
- public Stream<Behavior<? super E>> d() {
|
||||
- return this.c.values().stream().flatMap((map) -> {
|
||||
- return map.values().stream();
|
||||
- }).flatMap(Collection::stream).filter((behavior) -> {
|
||||
- return behavior.a() == Behavior.Status.RUNNING;
|
||||
- });
|
||||
+ public java.util.List<Behavior<? super E>> d() {
|
||||
+ final java.util.List<Behavior<? super E>> behaviorList = (java.util.List<Behavior<? super E>>) new it.unimi.dsi.fastutil.objects.ObjectArrayList();
|
||||
+ for (final Map<Activity, Set<Behavior<? super E>>> map : this.c.values()) {
|
||||
+ for (final Set<Behavior<? super E>> set : map.values()) {
|
||||
+ for (final Behavior<? super E> behavior : set) {
|
||||
+ if (behavior.a() == Behavior.Status.RUNNING) {
|
||||
+ behaviorList.add(behavior);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return behaviorList;
|
||||
+ // Paper end - Port 20w15a pathfinder optimizations
|
||||
}
|
||||
|
||||
public void a(Activity activity) {
|
||||
@@ -168,12 +168,14 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
|
||||
public BehaviorController<E> f() {
|
||||
BehaviorController<E> behaviorcontroller = new BehaviorController<>(this.memories.keySet(), this.sensors.keySet(), new Dynamic(DynamicOpsNBT.a, new NBTTagCompound()));
|
||||
-
|
||||
- this.memories.forEach((memorymoduletype, optional) -> {
|
||||
- optional.ifPresent((object) -> {
|
||||
- Optional optional1 = (Optional) behaviorcontroller.memories.put(memorymoduletype, Optional.of(object));
|
||||
- });
|
||||
- });
|
||||
+ // Paper start - Port 20w15a pathfinder optimizations
|
||||
+ for (final Entry<MemoryModuleType<?>, Optional<?>> entry : this.memories.entrySet()) {
|
||||
+ final MemoryModuleType<?> memoryModuleType = entry.getKey();
|
||||
+ if (entry.getValue().isPresent()) {
|
||||
+ behaviorcontroller.memories.put(memoryModuleType, entry.getValue());
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Port 20w15a pathfinder optimizations
|
||||
return behaviorcontroller;
|
||||
}
|
||||
|
||||
@@ -186,14 +188,14 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
public void b(WorldServer worldserver, E e0) {
|
||||
long i = e0.world.getTime();
|
||||
|
||||
- this.d().forEach((behavior) -> {
|
||||
+ for(Behavior<? super E> behavior : this.d()) { // Paper - Port 20w15a pathfinder optimizations
|
||||
behavior.e(worldserver, e0, i);
|
||||
- });
|
||||
+ }
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T a(DynamicOps<T> dynamicops) {
|
||||
- T t0 = dynamicops.createMap((Map) this.memories.entrySet().stream().filter((entry) -> {
|
||||
+ T t0 = dynamicops.createMap(this.memories.entrySet().stream().filter((entry) -> { // Paper - decompile fix
|
||||
return ((MemoryModuleType) entry.getKey()).getSerializer().isPresent() && ((Optional) entry.getValue()).isPresent();
|
||||
}).map((entry) -> {
|
||||
return Pair.of(dynamicops.createString(IRegistry.MEMORY_MODULE_TYPE.getKey(entry.getKey()).toString()), ((MinecraftSerializable) ((Optional) entry.getValue()).get()).a(dynamicops));
|
||||
@@ -210,33 +212,45 @@ public class BehaviorController<E extends EntityLiving> implements MinecraftSeri
|
||||
|
||||
private void d(WorldServer worldserver, E e0) {
|
||||
long i = worldserver.getTime();
|
||||
-
|
||||
- this.c.values().stream().flatMap((map) -> {
|
||||
- return map.entrySet().stream();
|
||||
- }).filter((entry) -> {
|
||||
- return this.g.contains(entry.getKey());
|
||||
- }).map(Entry::getValue).flatMap(Collection::stream).filter((behavior) -> {
|
||||
- return behavior.a() == Behavior.Status.STOPPED;
|
||||
- }).forEach((behavior) -> {
|
||||
- behavior.b(worldserver, e0, i);
|
||||
- });
|
||||
+ // Paper start - Port 20w15a pathfinder optimizations
|
||||
+ for (final Map<Activity, Set<Behavior<? super E>>> map : this.c.values()) {
|
||||
+ for (final Map.Entry<Activity, Set<Behavior<? super E>>> entry : map.entrySet()) {
|
||||
+ final Activity activity = entry.getKey();
|
||||
+ if (this.g.contains(activity)) {
|
||||
+ final Set<Behavior<? super E>> set = entry.getValue();
|
||||
+ for (final Behavior<? super E> behavior : set) {
|
||||
+ if (behavior.a() == Behavior.Status.STOPPED) {
|
||||
+ behavior.b(worldserver, e0, i);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - Port 20w15a pathfinder optimizations
|
||||
}
|
||||
|
||||
private void e(WorldServer worldserver, E e0) {
|
||||
long i = worldserver.getTime();
|
||||
|
||||
- this.d().forEach((behavior) -> {
|
||||
+ for (final Behavior<? super E> behavior : this.d()) { // Paper - Port 20w15a pathfinder optimizations
|
||||
behavior.c(worldserver, e0, i);
|
||||
- });
|
||||
+ }
|
||||
}
|
||||
|
||||
private boolean d(Activity activity) {
|
||||
- return ((Set) this.e.get(activity)).stream().allMatch((pair) -> {
|
||||
- MemoryModuleType<?> memorymoduletype = (MemoryModuleType) pair.getFirst();
|
||||
- MemoryStatus memorystatus = (MemoryStatus) pair.getSecond();
|
||||
-
|
||||
- return this.a(memorymoduletype, memorystatus);
|
||||
- });
|
||||
+ // Paper start - Port 20w15a pathfinder optimizations
|
||||
+ if (!this.e.containsKey(activity)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ for (final Pair<MemoryModuleType<?>, MemoryStatus> pair : this.e.get(activity)) {
|
||||
+ MemoryModuleType<?> memorymoduletype = pair.getFirst();
|
||||
+ MemoryStatus memorystatus = pair.getSecond();
|
||||
+ if (!this.a(memorymoduletype, memorystatus)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ // Paper end - Port 20w15a pathfinder optimizations
|
||||
}
|
||||
|
||||
private boolean a(Object object) {
|
@ -1,171 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 Jul 2018 02:10:36 -0400
|
||||
Subject: [PATCH] Store reference to current Chunk for Entity and Block
|
||||
Entities
|
||||
|
||||
This enables us a fast reference to the entities current chunk instead
|
||||
of having to look it up by hashmap lookups.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 48c9d2b7d56832ebd13749a394b8b715f0b1704d..b633f6b3a36b793e6dbc1b8b554bfba74c719570 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -260,7 +260,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
}
|
||||
|
||||
public boolean isChunkLoaded() {
|
||||
- return level.hasChunk((int) Math.floor(this.getX()) >> 4, (int) Math.floor(this.getZ()) >> 4);
|
||||
+ return getCurrentChunk() != null;
|
||||
}
|
||||
// CraftBukkit end
|
||||
|
||||
@@ -1762,6 +1762,23 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ public java.lang.ref.WeakReference<net.minecraft.world.level.chunk.LevelChunk> currentChunk = null;
|
||||
+
|
||||
+ public void setCurrentChunk(net.minecraft.world.level.chunk.LevelChunk chunk) {
|
||||
+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null;
|
||||
+ }
|
||||
+ /**
|
||||
+ * Returns the entities current registered chunk. If the entity is not added to a chunk yet, it will return null
|
||||
+ */
|
||||
+ public net.minecraft.world.level.chunk.LevelChunk getCurrentChunk() {
|
||||
+ final net.minecraft.world.level.chunk.LevelChunk chunk = currentChunk != null ? currentChunk.get() : null;
|
||||
+ if (chunk != null && chunk.loaded) {
|
||||
+ return chunk;
|
||||
+ }
|
||||
+
|
||||
+ return !inChunk ? null : ((ServerLevel)level).getChunkSource().getChunkAtIfLoadedMainThreadNoCache(xChunk, zChunk);
|
||||
+ }
|
||||
+
|
||||
private ResourceLocation entityKey;
|
||||
private String entityKeyString;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 846fc0f36377337630b2ec2a5f7a5a54c39c2965..bb60c9da9f3ba0d5c5bad22512675ccb841a60e5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
+import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.util.Supplier;
|
||||
@@ -63,6 +64,15 @@ public abstract class BlockEntity implements net.minecraft.server.KeyedObject {
|
||||
getMinecraftKey(); // Try to load if it doesn't exists.
|
||||
return tileEntityKeyString;
|
||||
}
|
||||
+
|
||||
+ private java.lang.ref.WeakReference<LevelChunk> currentChunk = null;
|
||||
+ public LevelChunk getCurrentChunk() {
|
||||
+ final LevelChunk chunk = currentChunk != null ? currentChunk.get() : null;
|
||||
+ return chunk != null && chunk.loaded ? chunk : null;
|
||||
+ }
|
||||
+ public void setCurrentChunk(LevelChunk chunk) {
|
||||
+ this.currentChunk = chunk != null ? new java.lang.ref.WeakReference<>(chunk) : null;
|
||||
+ }
|
||||
// Paper end
|
||||
|
||||
@Nullable
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index e2c5a17aa72d1a5412d76881187d4d9ad1763297..ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -89,11 +89,36 @@ public class LevelChunk implements ChunkAccess {
|
||||
this(world, pos, biomes, UpgradeData.EMPTY, EmptyTickList.empty(), EmptyTickList.empty(), 0L, (LevelChunkSection[]) null, (Consumer) null);
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ private class TileEntityHashMap extends java.util.HashMap<BlockPos, BlockEntity> {
|
||||
+ @Override
|
||||
+ public BlockEntity put(BlockPos key, BlockEntity value) {
|
||||
+ BlockEntity replaced = super.put(key, value);
|
||||
+ if (replaced != null) {
|
||||
+ replaced.setCurrentChunk(null);
|
||||
+ }
|
||||
+ if (value != null) {
|
||||
+ value.setCurrentChunk(LevelChunk.this);
|
||||
+ }
|
||||
+ return replaced;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public BlockEntity remove(Object key) {
|
||||
+ BlockEntity removed = super.remove(key);
|
||||
+ if (removed != null) {
|
||||
+ removed.setCurrentChunk(null);
|
||||
+ }
|
||||
+ return removed;
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public LevelChunk(Level world, ChunkPos pos, ChunkBiomeContainer biomes, UpgradeData upgradeData, TickList<Block> blockTickScheduler, TickList<Fluid> fluidTickScheduler, long inhabitedTime, @Nullable LevelChunkSection[] sections, @Nullable Consumer<LevelChunk> loadToWorldConsumer) {
|
||||
this.sections = new LevelChunkSection[16];
|
||||
this.pendingBlockEntities = Maps.newHashMap();
|
||||
this.heightmaps = Maps.newEnumMap(Heightmap.Types.class);
|
||||
- this.blockEntities = Maps.newHashMap();
|
||||
+ this.blockEntities = new TileEntityHashMap(); // Paper
|
||||
this.structureStarts = Maps.newHashMap();
|
||||
this.structuresRefences = Maps.newHashMap();
|
||||
this.postProcessing = new ShortList[16];
|
||||
@@ -504,6 +529,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
}
|
||||
|
||||
entity.inChunk = true;
|
||||
+ entity.setCurrentChunk(this); // Paper
|
||||
entity.xChunk = this.chunkPos.x;
|
||||
entity.yChunk = k;
|
||||
entity.zChunk = this.chunkPos.z;
|
||||
@@ -516,6 +542,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
((Heightmap) this.heightmaps.get(type)).setRawData(heightmap);
|
||||
}
|
||||
|
||||
+ public final void removeEntity(Entity entity) { this.removeEntity(entity); } // Paper - OBFHELPER
|
||||
public void removeEntity(Entity entity) {
|
||||
this.removeEntity(entity, entity.yChunk);
|
||||
}
|
||||
@@ -530,7 +557,12 @@ public class LevelChunk implements ChunkAccess {
|
||||
section = this.entitySlices.length - 1;
|
||||
}
|
||||
|
||||
- this.entitySlices[section].remove(entity);
|
||||
+ // Paper start
|
||||
+ if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null);
|
||||
+ if (!this.entitySlices[section].remove(entity)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.entities.remove(entity); // Paper
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 080d3292e03c5a179b9eb89da1550718d263f817..eb61c803cf74c5ca2c51d5027a02ed3db6b53096 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -145,6 +145,7 @@ import net.minecraft.world.entity.vehicle.MinecartHopper;
|
||||
import net.minecraft.world.entity.vehicle.MinecartSpawner;
|
||||
import net.minecraft.world.entity.vehicle.MinecartTNT;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
+import org.bukkit.Chunk; // Paper
|
||||
import org.bukkit.EntityEffect;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
@@ -186,6 +187,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ public Chunk getChunk() {
|
||||
+ net.minecraft.world.level.chunk.LevelChunk currentChunk = entity.getCurrentChunk();
|
||||
+ return currentChunk != null ? currentChunk.bukkitChunk : getLocation().getChunk();
|
||||
+ }
|
||||
+
|
||||
public static CraftEntity getEntity(CraftServer server, Entity entity) {
|
||||
/*
|
||||
* Order is *EXTREMELY* important -- keep it right! =D
|
@ -1,55 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 4 Jul 2018 02:13:59 -0400
|
||||
Subject: [PATCH] Store counts for each Entity/Block Entity Type
|
||||
|
||||
Opens door for future patches to optimize performance
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index ae08fcce66d50d7f61bc3bd4a0e2547d56f53e82..00ce55c17980da87a3834f952475a766543506b0 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -90,15 +90,19 @@ public class LevelChunk implements ChunkAccess {
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ public final co.aikar.util.Counter<String> entityCounts = new co.aikar.util.Counter<>();
|
||||
+ public final co.aikar.util.Counter<String> tileEntityCounts = new co.aikar.util.Counter<>();
|
||||
private class TileEntityHashMap extends java.util.HashMap<BlockPos, BlockEntity> {
|
||||
@Override
|
||||
public BlockEntity put(BlockPos key, BlockEntity value) {
|
||||
BlockEntity replaced = super.put(key, value);
|
||||
if (replaced != null) {
|
||||
replaced.setCurrentChunk(null);
|
||||
+ tileEntityCounts.decrement(replaced.getMinecraftKeyString());
|
||||
}
|
||||
if (value != null) {
|
||||
value.setCurrentChunk(LevelChunk.this);
|
||||
+ tileEntityCounts.increment(value.getMinecraftKeyString());
|
||||
}
|
||||
return replaced;
|
||||
}
|
||||
@@ -108,6 +112,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
BlockEntity removed = super.remove(key);
|
||||
if (removed != null) {
|
||||
removed.setCurrentChunk(null);
|
||||
+ tileEntityCounts.decrement(removed.getMinecraftKeyString());
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
@@ -528,6 +533,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
k = this.entitySlices.length - 1;
|
||||
}
|
||||
|
||||
+ if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper
|
||||
entity.inChunk = true;
|
||||
entity.setCurrentChunk(this); // Paper
|
||||
entity.xChunk = this.chunkPos.x;
|
||||
@@ -562,6 +568,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
if (!this.entitySlices[section].remove(entity)) {
|
||||
return;
|
||||
}
|
||||
+ entityCounts.decrement(entity.getMinecraftKeyString());
|
||||
// Paper end
|
||||
this.entities.remove(entity); // Paper
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 28 Sep 2018 21:49:53 -0400
|
||||
Subject: [PATCH] Fix issues with entity loss due to unloaded chunks
|
||||
|
||||
Vanilla has risk of losing entities by causing them to be
|
||||
removed from all chunks if they try to move into an unloaded chunk.
|
||||
|
||||
This pretty much means high chance this entity will be lost in this
|
||||
scenario.
|
||||
|
||||
There is another case that adding an entity to the world can fail if
|
||||
the chunk isn't loaded.
|
||||
|
||||
Lots of the server is designed around addEntity never expecting to fail
|
||||
for these reasons, nor is it really logical.
|
||||
|
||||
This change ensures the chunks are always loaded when entities are
|
||||
added to the world, or a valid entity moves between chunks.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index d03b4f97102dfb88927a94ee5a5d397ac493eaa1..99883c83c126405fc93becefed8a1d0727b94aa7 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -848,11 +848,18 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
int k = Mth.floor(entity.getZ() / 16.0D);
|
||||
|
||||
if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) {
|
||||
+ // Paper start - remove entity if its in a chunk more correctly.
|
||||
+ LevelChunk currentChunk = entity.getCurrentChunk();
|
||||
+ if (currentChunk != null) {
|
||||
+ currentChunk.removeEntity(entity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
if (entity.inChunk && this.hasChunk(entity.xChunk, entity.zChunk)) {
|
||||
this.getChunk(entity.xChunk, entity.zChunk).removeEntity(entity, entity.yChunk);
|
||||
}
|
||||
|
||||
- if (!entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) {
|
||||
+ if (!entity.valid && !entity.checkAndResetForcedChunkAdditionFlag() && !this.hasChunk(i, k)) { // Paper - always load chunks to register valid entities location
|
||||
if (entity.inChunk) {
|
||||
ServerLevel.LOGGER.warn("Entity {} left loaded chunk area", entity);
|
||||
}
|
||||
@@ -1067,7 +1074,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
return false;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, entity.forcedLoading);
|
||||
+ ChunkAccess ichunkaccess = this.getChunk(Mth.floor(entity.getX() / 16.0D), Mth.floor(entity.getZ() / 16.0D), ChunkStatus.FULL, true); // Paper - always load chunks for entity adds
|
||||
|
||||
if (!(ichunkaccess instanceof LevelChunk)) {
|
||||
return false;
|
@ -1,33 +0,0 @@
|
||||
These hunks are for getEntities, which Mojang rewrote in 1.17.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 3a1b9f1ba19b28cebdafeb3b2476217d47213862..3e2cd6c7a34c1a792d7346019a8b039d1f4a7c04 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -1130,7 +1130,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
for (int i1 = i; i1 <= j; ++i1) {
|
||||
for (int j1 = k; j1 <= l; ++j1) {
|
||||
- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false);
|
||||
+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
|
||||
|
||||
if (chunk != null) {
|
||||
chunk.getEntities(except, box, list, predicate);
|
||||
@@ -1151,7 +1151,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
for (int i1 = i; i1 < j; ++i1) {
|
||||
for (int j1 = k; j1 < l; ++j1) {
|
||||
- LevelChunk chunk = this.getChunkSource().getChunk(i1, j1, false);
|
||||
+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
|
||||
|
||||
if (chunk != null) {
|
||||
chunk.getEntities(type, box, list, predicate);
|
||||
@@ -1174,7 +1174,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
for (int i1 = i; i1 < j; ++i1) {
|
||||
for (int j1 = k; j1 < l; ++j1) {
|
||||
- LevelChunk chunk = ichunkprovider.getChunk(i1, j1, false);
|
||||
+ LevelChunk chunk = (LevelChunk)this.getChunkIfLoadedImmediately(i1, j1); // Paper
|
||||
|
||||
if (chunk != null) {
|
||||
chunk.getEntitiesOfClass(entityClass, box, list, predicate);
|
@ -1,397 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 27 Jan 2020 21:28:00 -0800
|
||||
Subject: [PATCH] Optimise random block ticking
|
||||
|
||||
Massive performance improvement for random block ticking.
|
||||
The performance increase comes from the fact that the vast
|
||||
majority of attempted block ticks (~95% in my testing) fail
|
||||
because the randomly selected block is not tickable.
|
||||
|
||||
Now only tickable blocks are targeted, however this means that
|
||||
the maximum number of block ticks occurs per chunk. However,
|
||||
not all chunks are going to be targeted. The percent chance
|
||||
of a chunk being targeted is based on how many tickable blocks
|
||||
are in the chunk.
|
||||
This means that while block ticks are spread out less, the
|
||||
total number of blocks ticked per world tick remains the same.
|
||||
Therefore, the chance of a random tickable block being ticked
|
||||
remains the same.
|
||||
|
||||
1.17: The IBlockDataList util class needs to be redone to support variable height limits
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..3edc8e52e06a62ce9f8cc734fd7458b37cfaad91
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/util/math/ThreadUnsafeRandom.java
|
||||
@@ -0,0 +1,46 @@
|
||||
+package com.destroystokyo.paper.util.math;
|
||||
+
|
||||
+import java.util.Random;
|
||||
+
|
||||
+public final class ThreadUnsafeRandom extends Random {
|
||||
+
|
||||
+ // See javadoc and internal comments for java.util.Random where these values come from, how they are used, and the author for them.
|
||||
+ private static final long multiplier = 0x5DEECE66DL;
|
||||
+ private static final long addend = 0xBL;
|
||||
+ private static final long mask = (1L << 48) - 1;
|
||||
+
|
||||
+ private static long initialScramble(long seed) {
|
||||
+ return (seed ^ multiplier) & mask;
|
||||
+ }
|
||||
+
|
||||
+ private long seed;
|
||||
+
|
||||
+ @Override
|
||||
+ public void setSeed(long seed) {
|
||||
+ // note: called by Random constructor
|
||||
+ this.seed = initialScramble(seed);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ protected int next(int bits) {
|
||||
+ // avoid the expensive CAS logic used by superclass
|
||||
+ return (int) (((this.seed = this.seed * multiplier + addend) & mask) >>> (48 - bits));
|
||||
+ }
|
||||
+
|
||||
+ // Taken from
|
||||
+ // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
||||
+ // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2016/06/25/fastrange.c
|
||||
+ // Original license is public domain
|
||||
+ public static int fastRandomBounded(final long randomInteger, final long limit) {
|
||||
+ // randomInteger must be [0, pow(2, 32))
|
||||
+ // limit must be [0, pow(2, 32))
|
||||
+ return (int)((randomInteger * limit) >>> 32);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int nextInt(int bound) {
|
||||
+ // yes this breaks random's spec
|
||||
+ // however there's nothing that uses this class that relies on it
|
||||
+ return fastRandomBounded(this.next(32) & 0xFFFFFFFFL, bound);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 3b7585760483b077783a28de8d04ba438eb25c16..5f499f2d8e62fc6f28c180c857582bd6c895c98c 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -673,7 +673,12 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
});
|
||||
}
|
||||
|
||||
- public void tickChunk(LevelChunk chunk, int randomTickSpeed) {
|
||||
+ // Paper start - optimise random block ticking
|
||||
+ private final BlockPos.MutableBlockPos chunkTickMutablePosition = new BlockPos.MutableBlockPos();
|
||||
+ private final com.destroystokyo.paper.util.math.ThreadUnsafeRandom randomTickRandom = new com.destroystokyo.paper.util.math.ThreadUnsafeRandom();
|
||||
+ // Paper end
|
||||
+
|
||||
+ public void tickChunk(LevelChunk chunk, int randomTickSpeed) { final int randomTickSpeed1 = randomTickSpeed; // Paper
|
||||
ChunkPos chunkcoordintpair = chunk.getPos();
|
||||
boolean flag = this.isRaining();
|
||||
int j = chunkcoordintpair.getMinBlockX();
|
||||
@@ -681,10 +686,10 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
ProfilerFiller gameprofilerfiller = this.getProfiler();
|
||||
|
||||
gameprofilerfiller.push("thunder");
|
||||
- BlockPos blockposition;
|
||||
+ final BlockPos.MutableBlockPos blockposition = this.chunkTickMutablePosition; // Paper - use mutable to reduce allocation rate, final to force compile fail on change
|
||||
|
||||
if (!this.paperConfig.disableThunder && flag && this.isThundering() && this.random.nextInt(100000) == 0) { // Paper - Disable thunder
|
||||
- blockposition = this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15));
|
||||
+ blockposition.set(this.findLightningTargetAround(this.getBlockRandomPos(j, 0, k, 15))); // Paper
|
||||
if (this.isRainingAt(blockposition)) {
|
||||
DifficultyInstance difficultydamagescaler = this.getCurrentDifficultyAt(blockposition);
|
||||
boolean flag1 = this.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && this.random.nextDouble() < (double) difficultydamagescaler.getEffectiveDifficulty() * paperConfig.skeleHorseSpawnChance && !this.getBlockState(blockposition.below()).is(Blocks.LIGHTNING_ROD); // Paper
|
||||
@@ -707,66 +712,81 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
}
|
||||
|
||||
gameprofilerfiller.popPush("iceandsnow");
|
||||
- if (!this.paperConfig.disableIceAndSnow && this.random.nextInt(16) == 0) { // Paper - Disable ice and snow
|
||||
- blockposition = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, this.getBlockRandomPos(j, 0, k, 15));
|
||||
- BlockPos blockposition1 = blockposition.below();
|
||||
+ if (!this.paperConfig.disableIceAndSnow && this.randomTickRandom.nextInt(16) == 0) { // Paper - Disable ice and snow // Paper - optimise random ticking
|
||||
+ // Paper start - optimise chunk ticking
|
||||
+ this.getRandomBlockPosition(j, 0, k, 15, blockposition);
|
||||
+ int normalY = chunk.getHighestBlockY(Heightmap.Types.MOTION_BLOCKING, blockposition.getX() & 15, blockposition.getZ() & 15);
|
||||
+ int downY = normalY - 1;
|
||||
+ blockposition.setY(normalY);
|
||||
+ // Paper end
|
||||
Biome biomebase = this.getBiome(blockposition);
|
||||
|
||||
- if (biomebase.shouldFreeze((LevelReader) this, blockposition1)) {
|
||||
- org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition1, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
|
||||
+ // Paper start - optimise chunk ticking
|
||||
+ blockposition.setY(downY);
|
||||
+ if (biomebase.shouldFreeze(this, blockposition)) {
|
||||
+ org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.ICE.defaultBlockState(), null); // CraftBukkit
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
+ blockposition.setY(normalY); // Paper
|
||||
if (biomebase.shouldSnow(this, blockposition)) {
|
||||
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, blockposition, Blocks.SNOW.defaultBlockState(), null); // CraftBukkit
|
||||
}
|
||||
|
||||
- BlockState iblockdata = this.getBlockState(blockposition1);
|
||||
+ blockposition.setY(downY); // Paper
|
||||
+ BlockState iblockdata = this.getBlockState(blockposition); // Paper
|
||||
Biome.Precipitation biomebase_precipitation = this.getBiome(blockposition).getPrecipitation();
|
||||
|
||||
- if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition1)) {
|
||||
+ if (biomebase_precipitation == Biome.Precipitation.RAIN && biomebase.isColdEnoughToSnow(blockposition)) { // Paper
|
||||
biomebase_precipitation = Biome.Precipitation.SNOW;
|
||||
}
|
||||
|
||||
- iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition1, biomebase_precipitation);
|
||||
+ iblockdata.getBlock().handlePrecipitation(iblockdata, (net.minecraft.world.level.Level) this, blockposition, biomebase_precipitation); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
- gameprofilerfiller.popPush("tickBlocks");
|
||||
- timings.chunkTicksBlocks.startTiming(); // Paper
|
||||
+ // Paper start - optimise random block ticking
|
||||
+ gameprofilerfiller.pop();
|
||||
if (randomTickSpeed > 0) {
|
||||
- LevelChunkSection[] achunksection = chunk.getSections();
|
||||
- int l = achunksection.length;
|
||||
-
|
||||
- for (int i1 = 0; i1 < l; ++i1) {
|
||||
- LevelChunkSection chunksection = achunksection[i1];
|
||||
+ gameprofilerfiller.push("randomTick");
|
||||
+ timings.chunkTicksBlocks.startTiming(); // Paper
|
||||
|
||||
- if (chunksection != LevelChunk.EMPTY_SECTION && chunksection.isRandomlyTicking()) {
|
||||
- int j1 = chunksection.bottomBlockY();
|
||||
+ LevelChunkSection[] sections = chunk.getSections();
|
||||
|
||||
- for (int k1 = 0; k1 < randomTickSpeed; ++k1) {
|
||||
- BlockPos blockposition2 = this.getBlockRandomPos(j, j1, k, 15);
|
||||
+ for (int sectionIndex = 0; sectionIndex < 16; ++sectionIndex) {
|
||||
+ LevelChunkSection section = sections[sectionIndex];
|
||||
+ if (section == null || section.tickingList.size() == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- gameprofilerfiller.push("randomTick");
|
||||
- BlockState iblockdata1 = chunksection.getBlockState(blockposition2.getX() - j, blockposition2.getY() - j1, blockposition2.getZ() - k);
|
||||
+ int yPos = sectionIndex << 4;
|
||||
+ for (int a = 0; a < randomTickSpeed1; ++a) {
|
||||
+ int tickingBlocks = section.tickingList.size();
|
||||
+ int index = this.randomTickRandom.nextInt(16 * 16 * 16);
|
||||
+ if (index >= tickingBlocks) {
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
- if (iblockdata1.isRandomlyTicking()) {
|
||||
- iblockdata1.randomTick(this, blockposition2, this.random);
|
||||
- }
|
||||
+ long raw = section.tickingList.getRaw(index);
|
||||
+ int location = com.destroystokyo.paper.util.maplist.IBlockDataList.getLocationFromRaw(raw);
|
||||
+ int randomX = location & 15;
|
||||
+ int randomY = ((location >>> (4 + 4)) & 255) | yPos;
|
||||
+ int randomZ = (location >>> 4) & 15;
|
||||
|
||||
- FluidState fluid = iblockdata1.getFluidState();
|
||||
+ BlockPos blockposition2 = blockposition.setValues(j + randomX, randomY, k + randomZ);
|
||||
+ BlockState iblockdata = com.destroystokyo.paper.util.maplist.IBlockDataList.getBlockDataFromRaw(raw);
|
||||
|
||||
- if (fluid.isRandomlyTicking()) {
|
||||
- fluid.randomTick(this, blockposition2, this.random);
|
||||
- }
|
||||
+ iblockdata.randomTick(this, blockposition2, this.randomTickRandom);
|
||||
|
||||
- gameprofilerfiller.pop();
|
||||
- }
|
||||
+ // We drop the fluid tick since LAVA is ALREADY TICKED by the above method.
|
||||
+ // TODO CHECK ON UPDATE
|
||||
}
|
||||
}
|
||||
+ gameprofilerfiller.pop();
|
||||
+ timings.chunkTicksBlocks.stopTiming(); // Paper
|
||||
+ // Paper end
|
||||
}
|
||||
- timings.chunkTicksBlocks.stopTiming(); // Paper
|
||||
- gameprofilerfiller.pop();
|
||||
}
|
||||
|
||||
private Optional<BlockPos> findLightningRod(BlockPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java
|
||||
index 9b955a027bd2c3cbcfa659a41a6687221c5fea63..6c036335b28258cd8c268173d73707af00d12bf9 100644
|
||||
--- a/src/main/java/net/minecraft/util/BitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/BitStorage.java
|
||||
@@ -105,4 +105,32 @@ public class BitStorage {
|
||||
}
|
||||
|
||||
}
|
||||
+
|
||||
+ // Paper start
|
||||
+ public final void forEach(DataBitConsumer consumer) {
|
||||
+ int i = 0;
|
||||
+ long[] along = this.data;
|
||||
+ int j = along.length;
|
||||
+
|
||||
+ for (int k = 0; k < j; ++k) {
|
||||
+ long l = along[k];
|
||||
+
|
||||
+ for (int i1 = 0; i1 < this.valuesPerLong; ++i1) {
|
||||
+ consumer.accept(i, (int) (l & this.mask));
|
||||
+ l >>= this.bits;
|
||||
+ ++i;
|
||||
+ if (i >= this.size) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @FunctionalInterface
|
||||
+ public static interface DataBitConsumer {
|
||||
+
|
||||
+ void accept(int location, int data);
|
||||
+
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Turtle.java b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
index 925f16d5eb092518ef774f69a8d99689feb0f5d7..01d8af06f19427354cac95d691e65d31253fef94 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -91,7 +91,7 @@ public class Turtle extends Animal {
|
||||
}
|
||||
|
||||
public void setHomePos(BlockPos pos) {
|
||||
- this.entityData.set(Turtle.HOME_POS, pos);
|
||||
+ this.entityData.set(Turtle.HOME_POS, pos.immutable()); // Paper - called with mutablepos...
|
||||
}
|
||||
|
||||
public BlockPos getHomePos() { // Paper - public
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 02c4396f3f42c1ec387eae9b2f7815f6e9f9e1c4..1e373db7080bd4fa5c62188e3ddb3e5206e9b5b1 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -1307,10 +1307,18 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public abstract TagContainer getTagManager();
|
||||
|
||||
public BlockPos getBlockRandomPos(int x, int y, int z, int l) {
|
||||
+ // Paper start - allow use of mutable pos
|
||||
+ BlockPos.MutableBlockPos ret = new BlockPos.MutableBlockPos();
|
||||
+ this.getRandomBlockPosition(x, y, z, l, ret);
|
||||
+ return ret.immutable();
|
||||
+ }
|
||||
+ public final BlockPos.MutableBlockPos getRandomBlockPosition(int i, int j, int k, int l, BlockPos.MutableBlockPos out) {
|
||||
+ // Paper end
|
||||
this.randValue = this.randValue * 3 + 1013904223;
|
||||
int i1 = this.randValue >> 2;
|
||||
|
||||
- return new BlockPos(x + (i1 & 15), y + (i1 >> 16 & l), z + (i1 >> 8 & 15));
|
||||
+ out.setValues(i + (i1 & 15), j + (i1 >> 16 & l), k + (i1 >> 8 & 15)); // Paper - change to setValues call
|
||||
+ return out; // Paper
|
||||
}
|
||||
|
||||
public boolean noSave() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a088cb005525fda2c9d5521ab3bac43cfa38a393..1782be43f1dbe2776abe5087d305e271c62285dd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -568,6 +568,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
@Override
|
||||
public void addEntity(Entity entity) {}
|
||||
|
||||
+ public final int getHighestBlockY(Heightmap.Types heightmap_type, int i, int j) { return this.getHeight(heightmap_type, i, j) + 1; } // Paper - sort of an obfhelper, but without -1
|
||||
@Override
|
||||
public int getHeight(Heightmap.Types type, int x, int z) {
|
||||
return ((Heightmap) this.heightmaps.get(type)).getFirstAvailable(x & 15, z & 15) - 1;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index ec8b67c1b024df38d5e1ad81acff33537ae25626..739abc73020e8a41a99fa52907843efe07af9b4e 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -14,11 +14,12 @@ public class LevelChunkSection {
|
||||
public static final int SECTION_HEIGHT = 16;
|
||||
public static final int SECTION_SIZE = 4096;
|
||||
public static final Palette<BlockState> GLOBAL_BLOCKSTATE_PALETTE = new GlobalPalette<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState());
|
||||
- private final int bottomBlockY;
|
||||
+ final int bottomBlockY; // Paper - private -> package-private
|
||||
short nonEmptyBlockCount; // Paper - package-private
|
||||
- private short tickingBlockCount;
|
||||
+ short tickingBlockCount; // Paper - private -> package-private
|
||||
private short tickingFluidCount;
|
||||
final PalettedContainer<BlockState> states; // Paper - package-private
|
||||
+ public final com.destroystokyo.paper.util.maplist.IBlockDataList tickingList = new com.destroystokyo.paper.util.maplist.IBlockDataList(); // Paper
|
||||
|
||||
// Paper start - Anti-Xray - Add parameters
|
||||
@Deprecated public LevelChunkSection(int yOffset) { this(yOffset, null, null, true); } // Notice for updates: Please make sure this constructor isn't used anywhere
|
||||
@@ -79,6 +80,9 @@ public class LevelChunkSection {
|
||||
--this.nonEmptyBlockCount;
|
||||
if (blockState.isRandomlyTicking()) {
|
||||
--this.tickingBlockCount;
|
||||
+ // Paper start
|
||||
+ this.tickingList.remove(x, y, z);
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +94,9 @@ public class LevelChunkSection {
|
||||
++this.nonEmptyBlockCount;
|
||||
if (state.isRandomlyTicking()) {
|
||||
++this.tickingBlockCount;
|
||||
+ // Paper start
|
||||
+ this.tickingList.add(x, y, z, state);
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,22 +132,28 @@ public class LevelChunkSection {
|
||||
}
|
||||
|
||||
public void recalcBlockCounts() {
|
||||
+ // Paper start
|
||||
+ this.tickingList.clear();
|
||||
+ // Paper end
|
||||
this.nonEmptyBlockCount = 0;
|
||||
this.tickingBlockCount = 0;
|
||||
this.tickingFluidCount = 0;
|
||||
- this.states.count((state, count) -> {
|
||||
+ this.states.forEachLocation((state, location) -> { // Paper
|
||||
FluidState fluidState = state.getFluidState();
|
||||
if (!state.isAir()) {
|
||||
- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count);
|
||||
+ this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + 1); // Paper
|
||||
if (state.isRandomlyTicking()) {
|
||||
- this.tickingBlockCount = (short)(this.tickingBlockCount + count);
|
||||
+ // Paper start
|
||||
+ this.tickingBlockCount = (short)(this.tickingBlockCount + 1);
|
||||
+ this.tickingList.add(location, state);
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
if (!fluidState.isEmpty()) {
|
||||
- this.nonEmptyBlockCount = (short)(this.nonEmptyBlockCount + count);
|
||||
+ this.nonEmptyBlockCount = (short) (this.nonEmptyBlockCount + 1); // Paper
|
||||
if (fluidState.isRandomlyTicking()) {
|
||||
- this.tickingFluidCount = (short)(this.tickingFluidCount + count);
|
||||
+ this.tickingFluidCount = (short) (this.tickingFluidCount + 1); // Paper
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
index b5b0dbbb21f15a61017d8fc936feed30c2b193dc..2bedc0f38ef16e922197a6f8e4c17aeb9cab92fd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
@@ -314,6 +314,14 @@ public class PalettedContainer<T> implements PaletteResize<T> {
|
||||
});
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ public void forEachLocation(PalettedContainer.CountConsumer<T> datapaletteblock_a) {
|
||||
+ this.getDataBits().forEach((int location, int data) -> {
|
||||
+ datapaletteblock_a.accept(this.getDataPalette().getObject(data), location);
|
||||
+ });
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
@FunctionalInterface
|
||||
public interface CountConsumer<T> {
|
||||
void accept(T object, int count);
|
@ -1,81 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 29 Mar 2020 18:26:14 -0400
|
||||
Subject: [PATCH] Ensure Entity is never double registered
|
||||
|
||||
If something calls register twice, and the world is ticking, it could be
|
||||
enqueued to add twice.
|
||||
|
||||
Vs behavior of non ticking of just overwriting state.
|
||||
|
||||
We will now simply log a warning when this happens instead of crashing the server.
|
||||
|
||||
1.17: Probably not needed?
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 9da0d98bc2ed7876a00a734690ed42f01b9a9a9b..9898d5c8fab63c576831bd416ccf1854ed077b0d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -643,6 +643,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
Entity entity2;
|
||||
|
||||
while ((entity2 = (Entity) this.toAddAfterTick.poll()) != null) {
|
||||
+ if (!entity2.isQueuedForRegister) continue; // Paper - ignore cancelled registers
|
||||
this.add(entity2);
|
||||
}
|
||||
|
||||
@@ -1400,6 +1401,19 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
|
||||
public void onEntityRemoved(Entity entity) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
|
||||
+ // Paper start - fix entity registration issues
|
||||
+ if (entity instanceof EnderDragonPart) {
|
||||
+ // Usually this is a no-op for complex parts, and ID's should be removed, but go ahead and remove it anyways
|
||||
+ // Dragon parts are handled special in register. they don't receive a valid = true or register by UUID etc.
|
||||
+ this.entitiesById.remove(entity.getId(), entity);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (!entity.valid) {
|
||||
+ // Someone called remove before we ever got added, cancel the add.
|
||||
+ entity.isQueuedForRegister = false;
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
// Spigot start
|
||||
if ( entity instanceof Player )
|
||||
{
|
||||
@@ -1466,9 +1480,21 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
|
||||
private void add(Entity entity) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
|
||||
+ // Paper start - don't double enqueue entity registration
|
||||
+ //noinspection ObjectEquality
|
||||
+ if (this.entitiesById.get(entity.getId()) == entity) {
|
||||
+ LOGGER.error(entity + " was already registered!");
|
||||
+ new Throwable().printStackTrace();
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (this.tickingEntities) {
|
||||
- this.toAddAfterTick.add(entity);
|
||||
+ if (!entity.isQueuedForRegister) { // Paper
|
||||
+ this.toAddAfterTick.add(entity);
|
||||
+ entity.isQueuedForRegister = true; // Paper
|
||||
+ }
|
||||
} else {
|
||||
+ entity.isQueuedForRegister = false; // Paper
|
||||
this.entitiesById.put(entity.getId(), entity);
|
||||
if (entity instanceof EnderDragon) {
|
||||
EnderDragonPart[] aentitycomplexpart = ((EnderDragon) entity).getSubEntities();
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 43f77d01fceab107d3502d282205aa579d64cc4b..7e198b94f349d4c4d61502f5ad8c60686800d88f 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -147,6 +147,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
}
|
||||
|
||||
// Paper start
|
||||
+ public boolean isQueuedForRegister = false;
|
||||
public static Random SHARED_RANDOM = new Random() {
|
||||
private boolean locked = false;
|
||||
@Override
|
@ -1,47 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 11 Apr 2020 21:23:42 -0400
|
||||
Subject: [PATCH] Delay unsafe actions until after entity ticking is done
|
||||
|
||||
This will help prevent many cases of unregistering entities during entity ticking
|
||||
|
||||
1.17: Not used anywhere in 1.16.5 server, and no more tickingEntities bool on ServerLevel (moved to Level?)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 4e75cc5e52a5295e32ccadb371702a405bb518bb..b9978d296b83e73d3395b8254c0e8ccd9b36d0fa 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -172,6 +172,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
public final List<ServerPlayer> players = Lists.newArrayList(); // Paper - private -> public
|
||||
public final ServerChunkCache chunkSource; // Paper - public
|
||||
boolean tickingEntities;
|
||||
+ // Paper start
|
||||
+ List<java.lang.Runnable> afterEntityTickingTasks = Lists.newArrayList();
|
||||
+ public void doIfNotEntityTicking(java.lang.Runnable run) {
|
||||
+ if (tickingEntities) {
|
||||
+ afterEntityTickingTasks.add(run);
|
||||
+ } else {
|
||||
+ run.run();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
private final MinecraftServer server;
|
||||
public final PrimaryLevelData worldDataServer; // CraftBukkit - type
|
||||
public boolean noSave;
|
||||
@@ -641,6 +651,16 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
timings.entityTick.stopTiming(); // Spigot
|
||||
|
||||
this.tickingEntities = false;
|
||||
+ // Paper start
|
||||
+ for (java.lang.Runnable run : this.afterEntityTickingTasks) {
|
||||
+ try {
|
||||
+ run.run();
|
||||
+ } catch (Exception e) {
|
||||
+ LOGGER.error("Error in After Entity Ticking Task", e);
|
||||
+ }
|
||||
+ }
|
||||
+ this.afterEntityTickingTasks.clear();
|
||||
+ // Paper end
|
||||
this.getServer().midTickLoadChunks(); // Paper
|
||||
|
||||
Entity entity2;
|
@ -1,101 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: MeFisto94 <MeFisto94@users.noreply.github.com>
|
||||
Date: Tue, 12 May 2020 23:02:43 +0200
|
||||
Subject: [PATCH] Workaround for Client Lag Spikes (MC-162253)
|
||||
|
||||
When crossing certain chunk boundaries, the client needlessly
|
||||
calculates light maps for chunk neighbours. In some specific map
|
||||
configurations, these calculations cause a 500ms+ freeze on the Client.
|
||||
|
||||
This patch basically serves as a workaround by sending light maps
|
||||
to the client, so that it doesn't attempt to calculate them.
|
||||
This mitigates the frametime impact to a minimum (but it's still there).
|
||||
|
||||
1.17 UPDATE NOTE: More or less untested, mapped version of the patch: https://paste.gg/p/anonymous/594123c7ce7d4d398d8834af6ba386d1
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index d8f99f7f5ca0e1dbbb9b760af3a4b4f9c52ef6c7..f700ac973ebc3037a5a44eac3c9d505b98adce41 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1906,9 +1906,68 @@ Sections go from 0..16. Now whenever a section is not empty, it can potentially
|
||||
|
||||
public void playerLoadedChunk(ServerPlayer player, Packet<?>[] packets, LevelChunk chunk) { // Paper - private -> public
|
||||
if (packets[0] == null) {
|
||||
+ // Paper start - add 8 for light fix workaround
|
||||
+ if (packets.length != 10) { // in case Plugins call sendChunk, resize
|
||||
+ packets = new Packet[10];
|
||||
+ }
|
||||
+ // Paper end
|
||||
packets[0] = new ClientboundLevelChunkPacket(chunk);
|
||||
packets[1] = new ClientboundLightUpdatePacket(chunk.getPos(), this.lightEngine, (BitSet) null, (BitSet) null, true);
|
||||
+
|
||||
+ // Paper start - Fix MC-162253
|
||||
+ final int lightMask = getLightMask(chunk);
|
||||
+ int i = 1;
|
||||
+ for (int x = -1; x <= 1; x++) {
|
||||
+ for (int z = -1; z <= 1; z++) {
|
||||
+ if (x == 0 && z == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ++i;
|
||||
+
|
||||
+ if (!chunk.isNeighbourLoaded(x, z)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final LevelChunk neighbor = chunk.getRelativeNeighbourIfLoaded(x, z);
|
||||
+ final int updateLightMask = lightMask & ~getCeilingLightMask(neighbor);
|
||||
+
|
||||
+ if (updateLightMask == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ packets[i] = new ClientboundLightUpdatePacket(new ChunkPos(chunk.getPos().x + x, chunk.getPos().z + z), lightEngine, null, null, updateLightMask, 0, true); // TODO: This line needs updating
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ final int viewDistance = playerViewDistanceBroadcastMap.getLastViewDistance(player);
|
||||
+ final long lastPosition = playerViewDistanceBroadcastMap.getLastCoordinate(player);
|
||||
+
|
||||
+ int j = 1;
|
||||
+ for (int x = -1; x <= 1; x++) {
|
||||
+ for (int z = -1; z <= 1; z++) {
|
||||
+ if (x == 0 && z == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ ++j;
|
||||
+
|
||||
+ Packet<?> packet = packets[j];
|
||||
+ if (packet == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ final int distX = Math.abs(MCUtil.getCoordinateX(lastPosition) - (chunk.getPos().x + x));
|
||||
+ final int distZ = Math.abs(MCUtil.getCoordinateZ(lastPosition) - (chunk.getPos().z + z));
|
||||
+
|
||||
+ if (Math.max(distX, distZ) > viewDistance) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ player.connection.send(packet);
|
||||
+ }
|
||||
}
|
||||
+ // Paper end - Fix MC-162253
|
||||
|
||||
player.trackChunk(chunk.getPos(), packets[0], packets[1]);
|
||||
DebugPackets.sendPoiPacketsForChunk(this.level, chunk.getPos());
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index a63dc77db41dab79f03ef7384da55c1cdeca5d98..7cced5d06f296fcdc1209a43e7b3d1d9b47c0b26 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -262,7 +262,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
// broadcast
|
||||
Object[] backingSet = inRange.getBackingSet();
|
||||
- Packet[] chunkPackets = new Packet[2];
|
||||
+ Packet[] chunkPackets = new Packet[10];
|
||||
for (int index = 0, len = backingSet.length; index < len; ++index) {
|
||||
Object temp = backingSet[index];
|
||||
if (!(temp instanceof net.minecraft.server.level.ServerPlayer)) {
|
@ -1,52 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: lukas <lukasalt98@gmail.com>
|
||||
Date: Sun, 27 Dec 2020 17:19:51 +0100
|
||||
Subject: [PATCH] Optimized tick ready check
|
||||
|
||||
1.17: Needs to be reworked or dropped
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 066d5f7ee93351bff67c0d39ee9d940ac51515d8..b89cefc8890774dbc64fd6bddeb038d2ee36d485 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -854,13 +854,13 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
if (!tileentity.isRemoved() && tileentity.hasLevel()) {
|
||||
BlockPos blockposition = tileentity.getBlockPos();
|
||||
|
||||
- if (this.getChunkSource().isTickingChunk(blockposition) && this.getWorldBorder().isWithinBounds(blockposition)) {
|
||||
+ LevelChunk chunk; ChunkHolder playerChunk; if ((chunk = tileentity.getCurrentChunk()) != null && (playerChunk = chunk.playerChunk) != null && playerChunk.isTickingReady() && this.getWorldBorder().isInBounds(blockposition)) { // Paper - optimized tick ready check by inlining ChunkProviderServer.a(BlockPosition). Chunk lookup is no longer required and we can use the PlayerChunk directly available through the tile entity
|
||||
try {
|
||||
gameprofilerfiller.push(() -> {
|
||||
return String.valueOf(BlockEntityType.getKey(tileentity.getType()));
|
||||
});
|
||||
tileentity.tickTimer.startTiming(); // Spigot
|
||||
- if (tileentity.getType().isValid(this.getBlockState(blockposition).getBlock())) {
|
||||
+ if (tileentity.getType().isValid(chunk.getBlockState(blockposition).getBlock())) { // Paper - reuse the chunk from above, do not look it up again
|
||||
((TickableBlockEntity) tileentity).tick();
|
||||
} else {
|
||||
tileentity.logInvalidState();
|
||||
@@ -893,9 +893,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.tickableBlockEntities.remove(tileTickPosition--);
|
||||
// Spigot end
|
||||
//this.tileEntityList.remove(tileentity); // Paper - remove unused list
|
||||
- if (this.hasChunkAt(tileentity.getBlockPos())) {
|
||||
- this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos());
|
||||
+ // Paper - prevent double chunk lookups
|
||||
+ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again
|
||||
+ chunk.removeBlockEntity(tileentity.getBlockPos());
|
||||
}
|
||||
+ // Paper end
|
||||
}
|
||||
}
|
||||
|
||||
@@ -914,8 +916,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
}
|
||||
// CraftBukkit end */
|
||||
|
||||
- if (this.hasChunkAt(tileentity1.getBlockPos())) {
|
||||
- LevelChunk chunk = this.getChunkAt(tileentity1.getBlockPos());
|
||||
+ LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity1.getBlockPos())) != null) { // Paper - inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again
|
||||
+ // Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition()); // Paper - already computed above
|
||||
BlockState iblockdata = chunk.getBlockState(tileentity1.getBlockPos());
|
||||
|
||||
chunk.setBlockEntity(tileentity1.getBlockPos(), tileentity1);
|
@ -1,47 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Mon, 29 Mar 2021 09:07:25 +0200
|
||||
Subject: [PATCH] Make sure to remove correct TE during TE tick
|
||||
|
||||
This looks like it can cause premature TE removal.
|
||||
|
||||
1.17: doesnt apply anymore?
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index b89cefc8890774dbc64fd6bddeb038d2ee36d485..4523bc1f49e7be248a47eeb599fa7b6550dbb08d 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -895,7 +895,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
//this.tileEntityList.remove(tileentity); // Paper - remove unused list
|
||||
// Paper - prevent double chunk lookups
|
||||
LevelChunk chunk; if ((chunk = this.getChunkIfLoaded(tileentity.getBlockPos())) != null) { // inlined contents of this.isLoaded(BlockPosition). Reuse the returned chunk instead of looking it up again
|
||||
- chunk.removeBlockEntity(tileentity.getBlockPos());
|
||||
+ chunk.removeTileEntity(tileentity.getBlockPos(), tileentity); // Paper - remove correct TE
|
||||
}
|
||||
// Paper end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 9b76dc15417eef420804e5184a6d684e1137a746..a15c08be3e1bd0e7934175db6ae0684bbb05e249 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -818,10 +818,18 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
@Override
|
||||
public void removeBlockEntity(BlockPos pos) {
|
||||
+ // Paper start - remove correct TE
|
||||
+ removeTileEntity(pos, null);
|
||||
+ }
|
||||
+ public void removeTileEntity(BlockPos blockposition, BlockEntity match) {
|
||||
+ // Paper end
|
||||
if (this.loaded || this.world.isClientSide()) {
|
||||
- BlockEntity tileentity = (BlockEntity) this.blockEntities.remove(pos);
|
||||
+ // Paper start
|
||||
+ BlockEntity tileentity = (BlockEntity) this.blockEntities.get(blockposition);
|
||||
|
||||
- if (tileentity != null) {
|
||||
+ if (tileentity != null && (match == null || match == tileentity)) {
|
||||
+ this.blockEntities.remove(blockposition);
|
||||
+ // Paper end
|
||||
tileentity.setRemoved();
|
||||
}
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 8 Mar 2015 22:55:25 -0600
|
||||
Subject: [PATCH] Optimize TileEntity Ticking
|
||||
|
||||
ticking logic changes implemented by mojang
|
||||
|
||||
|
||||
diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
index 94adf0275a2e7093c152cc3b8b0a5747b3a13a86..5bcf9cefc29eb20e2cfbfb49e2b2662ec394a87e 100644
|
||||
--- a/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
|
||||
@@ -112,7 +112,7 @@ public class TimingsExport extends Thread {
|
||||
pair("end", System.currentTimeMillis() / 1000),
|
||||
pair("online-mode", Bukkit.getServer().getOnlineMode()),
|
||||
pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000),
|
||||
- pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedIds(), pack -> {
|
||||
+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> {
|
||||
// Don't feel like obf helper'ing these, non fatal if its temp missed.
|
||||
return ChatColor.stripColor(CraftChatMessage.fromComponent(pack.a(true)));
|
||||
}))
|
||||
@@ -151,8 +151,8 @@ public class TimingsExport extends Thread {
|
||||
);
|
||||
|
||||
parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> {
|
||||
- if (world.getWorldData().getName().equals("worldeditregentempworld")) return null;
|
||||
- return pair(world.getWorldData().getName(), createObject(
|
||||
+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null;
|
||||
+ return pair(world.getWorld().getName(), createObject(
|
||||
pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> {
|
||||
return pair(rule, world.getWorld().getGameRuleValue(rule));
|
||||
})),
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/ChestBlock.java b/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
index 56656bf34db07bc717ace8ae9c1b60f9bfd7ff05..1bda9a158eb4372b9ab7cf3097732e64810aefc6 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/ChestBlock.java
|
||||
@@ -54,8 +54,8 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements SimpleWaterloggedBlock {
|
||||
|
||||
public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
|
||||
- public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE;
|
||||
- public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||||
+ public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE; public static final EnumProperty<ChestType> CHEST_TYPE_PROPERTY = TYPE; // Paper - OBFHELPER
|
||||
+ public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; public static final BooleanProperty waterlogged() { return WATERLOGGED; } // Paper OBFHELPER
|
||||
protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D);
|
||||
protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D);
|
||||
protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D);
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
index 7b08ee35d2d8dc3fe783d773bf6686a5197006b8..17289d28b6d0023279a573715ee3d182988dd651 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/ChestBlockEntity.java
|
||||
@@ -8,6 +8,7 @@ import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TranslatableComponent;
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
@@ -32,7 +33,7 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
// CraftBukkit end
|
||||
|
||||
-public class ChestBlockEntity extends RandomizableContainerBlockEntity implements TickableBlockEntity {
|
||||
+public class ChestBlockEntity extends RandomizableContainerBlockEntity { // Paper - Remove ITickable
|
||||
|
||||
private NonNullList<ItemStack> items;
|
||||
protected float openness;
|
||||
@@ -110,14 +111,20 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
return tag;
|
||||
}
|
||||
|
||||
- @Override
|
||||
public void tick() {
|
||||
int i = this.worldPosition.getX();
|
||||
int j = this.worldPosition.getY();
|
||||
int k = this.worldPosition.getZ();
|
||||
|
||||
++this.tickInterval;
|
||||
- this.openCount = getOpenCount(this.level, this, this.tickInterval, i, j, k, this.openCount);
|
||||
+ }
|
||||
+
|
||||
+ public void doOpenLogic() {
|
||||
+ int i = this.worldPosition.getX();
|
||||
+ int j = this.worldPosition.getY();
|
||||
+ int k = this.worldPosition.getZ();
|
||||
+
|
||||
+ //this.viewingCount = a(this.world, this, this.j, i, j, k, this.viewingCount); // Paper - check is faulty given our logic is called before active container set
|
||||
this.oOpenness = this.openness;
|
||||
float f = 0.1F;
|
||||
|
||||
@@ -131,25 +138,31 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
if (this.openCount > 0 && this.openness == 0.0F) {
|
||||
this.playSound(SoundEvents.CHEST_OPEN);
|
||||
}
|
||||
+ }
|
||||
|
||||
- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) {
|
||||
- float f1 = this.openness;
|
||||
+ public void doCloseLogic() {
|
||||
+ if (this.openCount == 0 /* && this.a > 0.0F || this.viewingCount > 0 && this.a < 1.0F */) { // Paper - disable all but player count check
|
||||
+ /* // Paper - disable animation stuff
|
||||
+ float f1 = this.a;
|
||||
|
||||
- if (this.openCount > 0) {
|
||||
- this.openness += 0.1F;
|
||||
+ if (this.viewingCount > 0) {
|
||||
+ this.a += 0.1F;
|
||||
} else {
|
||||
- this.openness -= 0.1F;
|
||||
+ this.a -= 0.1F;
|
||||
}
|
||||
|
||||
- if (this.openness > 1.0F) {
|
||||
- this.openness = 1.0F;
|
||||
+ if (this.a > 1.0F) {
|
||||
+ this.a = 1.0F;
|
||||
}
|
||||
|
||||
float f2 = 0.5F;
|
||||
|
||||
- if (this.openness < 0.5F && f1 >= 0.5F) {
|
||||
+ if (this.a < 0.5F && f1 >= 0.5F) {
|
||||
+ */
|
||||
+ MCUtil.scheduleTask(10, () -> {
|
||||
this.playSound(SoundEvents.CHEST_CLOSE);
|
||||
- }
|
||||
+ }, "Chest Sounds");
|
||||
+ //} // Paper end
|
||||
|
||||
if (this.openness < 0.0F) {
|
||||
this.openness = 0.0F;
|
||||
@@ -188,6 +201,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
}
|
||||
|
||||
public void playSound(SoundEvent soundeffect) {
|
||||
+ if (!this.getBlockState().contains(ChestBlock.CHEST_TYPE_PROPERTY)) { return; } // Paper - this can be delayed, double check exists - Fixes GH-2074
|
||||
ChestType blockpropertychesttype = (ChestType) this.getBlockState().getValue(ChestBlock.TYPE);
|
||||
|
||||
if (blockpropertychesttype != ChestType.LEFT) {
|
||||
@@ -226,6 +240,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
|
||||
++this.openCount;
|
||||
if (this.level == null) return; // CraftBukkit
|
||||
+ doOpenLogic(); // Paper
|
||||
|
||||
// CraftBukkit start - Call redstone event
|
||||
if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) {
|
||||
@@ -248,6 +263,7 @@ public class ChestBlockEntity extends RandomizableContainerBlockEntity implement
|
||||
--this.openCount;
|
||||
|
||||
// CraftBukkit start - Call redstone event
|
||||
+ doCloseLogic(); // Paper
|
||||
if (this.getBlockState().getBlock() == Blocks.TRAPPED_CHEST) {
|
||||
int newPower = Math.max(0, Math.min(15, this.openCount));
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
index b26337770e13c20f57a4e74282710ce697ac0d41..8f0477d9620ef71e10855bbca07f9b6984d5d794 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/EnderChestBlockEntity.java
|
||||
@@ -1,11 +1,12 @@
|
||||
package net.minecraft.world.level.block.entity;
|
||||
|
||||
+import net.minecraft.server.MCUtil;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
-public class EnderChestBlockEntity extends BlockEntity implements TickableBlockEntity {
|
||||
+public class EnderChestBlockEntity extends BlockEntity { // Paper - Remove ITickable
|
||||
|
||||
public float openness;
|
||||
public float oOpenness;
|
||||
@@ -16,18 +17,28 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE
|
||||
super(BlockEntityType.ENDER_CHEST);
|
||||
}
|
||||
|
||||
- @Override
|
||||
public void tick() {
|
||||
if (++this.tickInterval % 20 * 4 == 0) {
|
||||
this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount);
|
||||
}
|
||||
|
||||
this.oOpenness = this.openness;
|
||||
+ /* // Paper
|
||||
+ int i = this.position.getX();
|
||||
+ int j = this.position.getY();
|
||||
+ int k = this.position.getZ();
|
||||
+ float f = 0.1F;
|
||||
+ double d0;
|
||||
+ // Paper start
|
||||
+ */
|
||||
+ }
|
||||
+
|
||||
+ private void doOpenLogic() {
|
||||
int i = this.worldPosition.getX();
|
||||
int j = this.worldPosition.getY();
|
||||
int k = this.worldPosition.getZ();
|
||||
- float f = 0.1F;
|
||||
double d0;
|
||||
+ // Paper end
|
||||
|
||||
if (this.openCount > 0 && this.openness == 0.0F) {
|
||||
double d1 = (double) i + 0.5D;
|
||||
@@ -35,28 +46,40 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE
|
||||
d0 = (double) k + 0.5D;
|
||||
this.level.playSound((Player) null, d1, (double) j + 0.5D, d0, SoundEvents.ENDER_CHEST_OPEN, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F);
|
||||
}
|
||||
+ // Paper start
|
||||
+ }
|
||||
|
||||
- if (this.openCount == 0 && this.openness > 0.0F || this.openCount > 0 && this.openness < 1.0F) {
|
||||
- float f1 = this.openness;
|
||||
+ private void doCloseLogic() {
|
||||
+ int i = this.worldPosition.getX();
|
||||
+ int j = this.worldPosition.getY();
|
||||
+ int k = this.worldPosition.getZ();
|
||||
+ double d0;
|
||||
+
|
||||
+ if (this.openCount == 0) { /* && this.a > 0.0F || this.c > 0 && this.a < 1.0F) {
|
||||
+ // Paper end
|
||||
+ float f1 = this.a;
|
||||
|
||||
- if (this.openCount > 0) {
|
||||
- this.openness += 0.1F;
|
||||
+ if (this.c > 0) {
|
||||
+ this.a += 0.1F;
|
||||
} else {
|
||||
- this.openness -= 0.1F;
|
||||
+ this.a -= 0.1F;
|
||||
}
|
||||
|
||||
- if (this.openness > 1.0F) {
|
||||
- this.openness = 1.0F;
|
||||
+ if (this.a > 1.0F) {
|
||||
+ this.a = 1.0F;
|
||||
}
|
||||
|
||||
float f2 = 0.5F;
|
||||
|
||||
- if (this.openness < 0.5F && f1 >= 0.5F) {
|
||||
+ if (this.a < 0.5F && f1 >= 0.5F) {
|
||||
+ // Paper start
|
||||
+ */
|
||||
d0 = (double) i + 0.5D;
|
||||
double d2 = (double) k + 0.5D;
|
||||
|
||||
+ MCUtil.scheduleTask(10, () -> {
|
||||
this.level.playSound((Player) null, d0, (double) j + 0.5D, d2, SoundEvents.ENDER_CHEST_CLOSE, SoundSource.BLOCKS, 0.5F, this.level.random.nextFloat() * 0.1F + 0.9F);
|
||||
- }
|
||||
+ }, "Chest Sounds");
|
||||
|
||||
if (this.openness < 0.0F) {
|
||||
this.openness = 0.0F;
|
||||
@@ -84,11 +107,13 @@ public class EnderChestBlockEntity extends BlockEntity implements TickableBlockE
|
||||
public void startOpen() {
|
||||
++this.openCount;
|
||||
this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount);
|
||||
+ doOpenLogic(); // Paper
|
||||
}
|
||||
|
||||
public void stopOpen() {
|
||||
--this.openCount;
|
||||
this.level.blockEvent(this.worldPosition, Blocks.ENDER_CHEST, 1, this.openCount);
|
||||
+ doCloseLogic(); // Paper
|
||||
}
|
||||
|
||||
public boolean stillValid(Player entityhuman) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
|
||||
index 60ce75c7f94c995d3753c40bc8d1ec09b4d37b1a..ac10fb9cd4701f0f6477a86bec73cb5ac6496725 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/StateHolder.java
|
||||
@@ -84,6 +84,7 @@ public abstract class StateHolder<O, S> {
|
||||
return Collections.unmodifiableCollection(this.values.keySet());
|
||||
}
|
||||
|
||||
+ public <T extends Comparable<T>> boolean contains(Property<T> iblockstate) { return this.hasProperty(iblockstate); } // Paper - OBFHELPER
|
||||
public <T extends Comparable<T>> boolean hasProperty(Property<T> property) {
|
||||
return this.values.containsKey(property);
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jedediah Smith <jedediah@silencegreys.com>
|
||||
Date: Wed, 2 Mar 2016 23:13:07 -0600
|
||||
Subject: [PATCH] Send absolute position the first time an entity is seen
|
||||
|
||||
Not needed anymore, packet spawn sends full position
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 59a5f82c9f57d760ba4959a040ce8cbf0f49e4aa..d1bc927c8b429f43de2cdad98f8b329ff4c8b4db 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1301,10 +1301,14 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
private final Entity entity;
|
||||
private final int range;
|
||||
private SectionPos lastSectionPos;
|
||||
- public final Set<ServerPlayer> seenBy = Sets.newHashSet();
|
||||
+ // 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<ServerPlayer, Boolean> trackedPlayerMap = new java.util.HashMap<>();
|
||||
+ public Set<ServerPlayer> seenBy = trackedPlayerMap.keySet();
|
||||
|
||||
public TrackedEntity(Entity entity, int i, int j, boolean flag) {
|
||||
- this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, seenBy); // CraftBukkit
|
||||
+ this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, trackedPlayerMap); // CraftBukkit // Paper
|
||||
this.entity = entity;
|
||||
this.range = i;
|
||||
this.lastSectionPos = SectionPos.of(entity);
|
||||
@@ -1386,7 +1390,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId()));
|
||||
// CraftBukkit end
|
||||
|
||||
- if (flag1 && this.seenBy.add(player)) {
|
||||
+ if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper
|
||||
this.serverEntity.addPairing(player);
|
||||
}
|
||||
} else if (this.seenBy.remove(player)) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
index 3d386627b6d3d33da76372e4a14d0c5000eb8ffc..fa6893055fa5617742bfb4b7eff60c8139395cb6 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
|
||||
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
+import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -51,7 +52,7 @@ public class ServerEntity {
|
||||
private final Entity entity;
|
||||
private final int updateInterval;
|
||||
private final boolean trackDelta;
|
||||
- private final Consumer<Packet<?>> broadcast;
|
||||
+ private final Consumer<Packet<?>> broadcast; private Consumer<Packet<?>> getPacketConsumer() { return broadcast; } // Paper - OBFHELPER
|
||||
private long xp;
|
||||
private long yp;
|
||||
private long zp;
|
||||
@@ -66,8 +67,23 @@ public class ServerEntity {
|
||||
private boolean wasOnGround;
|
||||
// CraftBukkit start
|
||||
private final Set<ServerPlayer> trackedPlayers;
|
||||
+ // Paper start
|
||||
+ private java.util.Map<ServerPlayer, Boolean> trackedPlayerMap = null;
|
||||
+
|
||||
+ /**
|
||||
+ * Requested in https://github.com/PaperMC/Paper/issues/1537 to allow intercepting packets
|
||||
+ */
|
||||
+ public void sendPlayerPacket(ServerPlayer player, Packet packet) {
|
||||
+ player.connection.send(packet);
|
||||
+ }
|
||||
+
|
||||
+ public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer<Packet<?>> consumer, java.util.Map<ServerPlayer, Boolean> trackedPlayers) {
|
||||
+ this(worldserver, entity, i, flag, consumer, trackedPlayers.keySet());
|
||||
+ trackedPlayerMap = trackedPlayers;
|
||||
+ }
|
||||
|
||||
public ServerEntity(ServerLevel worldserver, Entity entity, int i, boolean flag, Consumer<Packet<?>> consumer, Set<ServerPlayer> trackedPlayers) {
|
||||
+ // Paper end
|
||||
this.trackedPlayers = trackedPlayers;
|
||||
// CraftBukkit end
|
||||
this.ap = Vec3.ZERO;
|
||||
@@ -188,7 +204,25 @@ public class ServerEntity {
|
||||
}
|
||||
|
||||
if (packet1 != null) {
|
||||
- this.broadcast.accept(packet1);
|
||||
+ // paper start
|
||||
+ if (trackedPlayerMap == null || packet1 instanceof ClientboundTeleportEntityPacket) {
|
||||
+ this.broadcast.accept((packet1));
|
||||
+ } else {
|
||||
+ ClientboundTeleportEntityPacket teleportPacket = null;
|
||||
+
|
||||
+ for (java.util.Map.Entry<ServerPlayer, Boolean> viewer : trackedPlayerMap.entrySet()) {
|
||||
+ if (viewer.getValue()) {
|
||||
+ viewer.setValue(false);
|
||||
+ if (teleportPacket == null) {
|
||||
+ teleportPacket = new ClientboundTeleportEntityPacket(this.entity);
|
||||
+ }
|
||||
+ sendPlayerPacket(viewer.getKey(), teleportPacket);
|
||||
+ } else {
|
||||
+ sendPlayerPacket(viewer.getKey(), packet1);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
this.sendDirtyEntityData();
|
@ -1,50 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Hirschfeld <joe@ibj.io>
|
||||
Date: Thu, 3 Mar 2016 02:39:54 -0600
|
||||
Subject: [PATCH] Change implementation of (tile)entity removal list
|
||||
|
||||
use sets for faster removal
|
||||
|
||||
1.17: no more unload lists
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 6c6098731752d61b5241710b075d4ffe3826daac..89472b6e8f38921db50440d0213e40ac893892f1 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1122,7 +1122,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
}
|
||||
}
|
||||
// Spigot End
|
||||
- this.blockEntitiesToUnload.addAll(chunk.getBlockEntities().values());
|
||||
+ this.tileEntityListUnload.addAll(chunk.getBlockEntities().values());
|
||||
List[] aentityslice = chunk.getEntitySlices(); // Spigot
|
||||
int i = aentityslice.length;
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index e25666328dbf433b8358f2637d93b4128034bbaa..7b4475807cca0e92ea9ae6ea49a82a8634cc0ff5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -89,7 +89,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public final List<BlockEntity> blockEntityList = Lists.newArrayList();
|
||||
public final List<BlockEntity> tickableBlockEntities = Lists.newArrayList();
|
||||
protected final List<BlockEntity> pendingBlockEntities = Lists.newArrayList();
|
||||
- protected final List<BlockEntity> blockEntitiesToUnload = Lists.newArrayList();
|
||||
+ protected final java.util.Set<BlockEntity> tileEntityListUnload = com.google.common.collect.Sets.newHashSet();
|
||||
public final Thread thread;
|
||||
private final boolean isDebug;
|
||||
private int skyDarken;
|
||||
@@ -697,10 +697,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
|
||||
gameprofilerfiller.push("blockEntities");
|
||||
timings.tileEntityTick.startTiming(); // Spigot
|
||||
- if (!this.blockEntitiesToUnload.isEmpty()) {
|
||||
- this.tickableBlockEntities.removeAll(this.blockEntitiesToUnload);
|
||||
- this.blockEntityList.removeAll(this.blockEntitiesToUnload);
|
||||
- this.blockEntitiesToUnload.clear();
|
||||
+ if (!this.tileEntityListUnload.isEmpty()) {
|
||||
+ this.tickableBlockEntities.removeAll(this.tileEntityListUnload);
|
||||
+ this.blockEntityList.removeAll(this.tileEntityListUnload);
|
||||
+ this.tileEntityListUnload.clear();
|
||||
}
|
||||
|
||||
this.updatingBlockEntities = true;
|
@ -1,93 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 13 Apr 2016 00:25:28 -0400
|
||||
Subject: [PATCH] Remove unused World Tile Entity List
|
||||
|
||||
Massive hit to performance and it is completely unnecessary.
|
||||
|
||||
Removed during 1.17 update - no longer logically applies
|
||||
not true? blockEntityTickers and pendingBlockEntityTickers have similar logic applied to them
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index f7eddb39985072afeb79ec0cbfc084d7e84638e6..bb99d9fe5e274318d8480a6de2c45b0a57351f77 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1715,7 +1715,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
}
|
||||
|
||||
bufferedwriter.write(String.format("entities: %d\n", this.entitiesById.size()));
|
||||
- bufferedwriter.write(String.format("block_entities: %d\n", this.blockEntityList.size()));
|
||||
+ bufferedwriter.write(String.format("block_entities: %d\n", this.tickableBlockEntities.size())); // Paper - remove unused list
|
||||
bufferedwriter.write(String.format("block_ticks: %d\n", this.getBlockTicks().size()));
|
||||
bufferedwriter.write(String.format("fluid_ticks: %d\n", this.getLiquidTicks().size()));
|
||||
bufferedwriter.write("distance_manager: " + playerchunkmap.getDistanceManager().getDebugStatus() + "\n");
|
||||
@@ -1854,7 +1854,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
|
||||
private void dumpBlockEntities(Writer writer) throws IOException {
|
||||
CsvOutput csvwriter = CsvOutput.builder().addColumn("x").addColumn("y").addColumn("z").addColumn("type").build(writer);
|
||||
- Iterator iterator = this.blockEntityList.iterator();
|
||||
+ Iterator iterator = this.tickableBlockEntities.iterator(); // Paper - remove unused list
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
BlockEntity tileentity = (BlockEntity) iterator.next();
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 89a6a0b4235cfcc1d3ad68ff59a21fa60df4508f..8f0fec38b482465285057d3fd27d456cf036f2fd 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -91,7 +91,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
public static final ResourceKey<Level> NETHER = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_nether"));
|
||||
public static final ResourceKey<Level> END = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation("the_end"));
|
||||
private static final Direction[] DIRECTIONS = Direction.values();
|
||||
- public final List<BlockEntity> blockEntityList = Lists.newArrayList();
|
||||
+ //public final List<TileEntity> tileEntityList = Lists.newArrayList(); // Paper - remove unused list
|
||||
public final List<BlockEntity> tickableBlockEntities = Lists.newArrayList();
|
||||
protected final List<BlockEntity> pendingBlockEntities = Lists.newArrayList();
|
||||
protected final java.util.Set<BlockEntity> tileEntityListUnload = com.google.common.collect.Sets.newHashSet();
|
||||
@@ -683,9 +683,9 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
}, blockEntity::getBlockPos});
|
||||
}
|
||||
|
||||
- boolean flag = this.blockEntityList.add(blockEntity);
|
||||
+ boolean flag = true; // Paper - remove unused list
|
||||
|
||||
- if (flag && blockEntity instanceof TickableBlockEntity) {
|
||||
+ if (flag && blockEntity instanceof TickableBlockEntity && !this.tickableBlockEntities.contains(blockEntity)) { // Paper
|
||||
this.tickableBlockEntities.add(blockEntity);
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
timings.tileEntityTick.startTiming(); // Spigot
|
||||
if (!this.tileEntityListUnload.isEmpty()) {
|
||||
this.tickableBlockEntities.removeAll(this.tileEntityListUnload);
|
||||
- this.blockEntityList.removeAll(this.tileEntityListUnload);
|
||||
+ //this.tileEntityList.removeAll(this.tileEntityListUnload); // Paper - remove unused list
|
||||
this.tileEntityListUnload.clear();
|
||||
}
|
||||
|
||||
@@ -781,7 +781,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
tilesThisCycle--;
|
||||
this.tickableBlockEntities.remove(tileTickPosition--);
|
||||
// Spigot end
|
||||
- this.blockEntityList.remove(tileentity);
|
||||
+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list
|
||||
if (this.hasChunkAt(tileentity.getBlockPos())) {
|
||||
this.getChunkAt(tileentity.getBlockPos()).removeBlockEntity(tileentity.getBlockPos());
|
||||
}
|
||||
@@ -811,7 +811,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.sendBlockUpdated(tileentity1.getBlockPos(), iblockdata, iblockdata, 3);
|
||||
// CraftBukkit start
|
||||
// From above, don't screw this up - SPIGOT-1746
|
||||
- if (!this.blockEntityList.contains(tileentity1)) {
|
||||
+ if (true) { // Paper - remove unused list
|
||||
this.addBlockEntity(tileentity1);
|
||||
}
|
||||
// CraftBukkit end
|
||||
@@ -957,7 +957,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
} else {
|
||||
if (tileentity != null) {
|
||||
this.pendingBlockEntities.remove(tileentity);
|
||||
- this.blockEntityList.remove(tileentity);
|
||||
+ //this.tileEntityList.remove(tileentity); // Paper - remove unused list
|
||||
this.tickableBlockEntities.remove(tileentity);
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 13 Apr 2016 00:30:10 -0400
|
||||
Subject: [PATCH] Don't tick Skulls - unused code
|
||||
|
||||
No longer needed in 1.17
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
index 6a46517e4026971d8c050c685c710883b5976fa3..eebaeaccc3ba1a9ec089d84b8de6c9d36034868f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
|
||||
@@ -31,7 +31,7 @@ import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.players.GameProfileCache;
|
||||
import net.minecraft.util.StringUtil;
|
||||
|
||||
-public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity {
|
||||
+public class SkullBlockEntity extends BlockEntity /*implements ITickable*/ { // Paper - remove tickable
|
||||
|
||||
@Nullable
|
||||
private static GameProfileCache profileCache;
|
||||
@@ -134,7 +134,7 @@ public class SkullBlockEntity extends BlockEntity implements TickableBlockEntity
|
||||
|
||||
}
|
||||
|
||||
- @Override
|
||||
+ // Paper - remove override
|
||||
public void tick() {
|
||||
BlockState iblockdata = this.getBlockState();
|
||||
|
@ -1,87 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sun, 17 Apr 2016 17:27:09 -0400
|
||||
Subject: [PATCH] Prevent Fire from loading chunks & wrongly spread
|
||||
|
||||
This causes the nether to spam unload/reload chunks, plus overall
|
||||
bad behavior.
|
||||
|
||||
This also stops fire from spreading to illegal locations.
|
||||
|
||||
|
||||
|
||||
This shouldn't need to be included in post 1.14 versions, as blocks no longer tick without at least 1 radius
|
||||
chunk loaded.
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/FireBlock.java b/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
index 700078c2fd536cc22351eadf51503efb9acd9df9..85170008de6e77cfb8e4f55ae440a8428d868af4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/FireBlock.java
|
||||
@@ -134,7 +134,7 @@ public class FireBlock extends BaseFireBlock {
|
||||
BooleanProperty blockstateboolean = (BooleanProperty) FireBlock.PROPERTY_BY_DIRECTION.get(enumdirection);
|
||||
|
||||
if (blockstateboolean != null) {
|
||||
- iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getBlockState(pos.relative(enumdirection))));
|
||||
+ iblockdata1 = (BlockState) iblockdata1.setValue(blockstateboolean, this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))); // Paper - prevent chunk loads
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,6 +214,7 @@ public class FireBlock extends BaseFireBlock {
|
||||
}
|
||||
|
||||
blockposition_mutableblockposition.setWithOffset((Vec3i) pos, l, j1, i1);
|
||||
+ if (blockposition_mutableblockposition.isInvalidYLocation() || !world.hasChunkAt(blockposition_mutableblockposition)) continue; // Paper
|
||||
int l1 = this.getFireOdds((LevelReader) world, (BlockPos) blockposition_mutableblockposition);
|
||||
|
||||
if (l1 > 0) {
|
||||
@@ -259,10 +260,16 @@ public class FireBlock extends BaseFireBlock {
|
||||
}
|
||||
|
||||
private void trySpread(Level world, BlockPos blockposition, int i, Random random, int j, BlockPos sourceposition) { // CraftBukkit add sourceposition
|
||||
- int k = this.getBurnOdd(world.getBlockState(blockposition));
|
||||
+ // Paper start
|
||||
+ final BlockState iblockdata = world.getTypeIfLoaded(blockposition);
|
||||
+ if (iblockdata == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+ int k = this.getBurnOdd(iblockdata);
|
||||
+ // Paper end
|
||||
|
||||
if (random.nextInt(i) < k) {
|
||||
- BlockState iblockdata = world.getBlockState(blockposition);
|
||||
+ //IBlockData iblockdata = world.getType(blockposition); // Paper
|
||||
|
||||
// CraftBukkit start
|
||||
org.bukkit.block.Block theBlock = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
|
||||
@@ -308,7 +315,7 @@ public class FireBlock extends BaseFireBlock {
|
||||
for (int j = 0; j < i; ++j) {
|
||||
Direction enumdirection = aenumdirection[j];
|
||||
|
||||
- if (this.canBurn(world.getBlockState(pos.relative(enumdirection)))) {
|
||||
+ if (this.canBurn(world.getTypeIfLoaded(pos.relative(enumdirection)))) { // Paper - prevent chunk loads
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -326,7 +333,12 @@ public class FireBlock extends BaseFireBlock {
|
||||
|
||||
for (int k = 0; k < j; ++k) {
|
||||
Direction enumdirection = aenumdirection[k];
|
||||
- BlockState iblockdata = iworldreader.getBlockState(pos.relative(enumdirection));
|
||||
+ // Paper start
|
||||
+ BlockState iblockdata = iworldreader.getTypeIfLoaded(pos.relative(enumdirection));
|
||||
+ if (iblockdata == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
i = Math.max(this.getFlameOdds(iblockdata), i);
|
||||
}
|
||||
@@ -337,7 +349,7 @@ public class FireBlock extends BaseFireBlock {
|
||||
|
||||
@Override
|
||||
protected boolean canBurn(BlockState state) {
|
||||
- return this.getFlameOdds(state) > 0;
|
||||
+ return state != null && this.getFlameOdds(state) > 0; // Paper - iblockdata can be nullable if chunk is unloaded now
|
||||
}
|
||||
|
||||
@Override
|
@ -1,26 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 21 Jun 2016 22:54:34 -0400
|
||||
Subject: [PATCH] Fix Double World Add issues
|
||||
|
||||
Vanilla will double add Spider Jockeys to the world, so ignore already added.
|
||||
|
||||
Also add debug if something else tries to, and abort before world gets bad state
|
||||
|
||||
In 1.17 the entire entity state manager was rewritten. no longer applies, needs
|
||||
further information on new state manager
|
||||
|
||||
similar check added by mojang
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 0a613f94d1c796267636e1a343aeee65a49ffed5..335928d60dbfc07644ffeab366900c5e77e99d56 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1032,6 +1032,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
// CraftBukkit start
|
||||
private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
||||
org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
|
||||
+ if (entity.valid) { MinecraftServer.LOGGER.error("Attempted Double World add on " + entity, new Throwable()); return true; } // Paper
|
||||
if (entity.removed) {
|
||||
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit
|
||||
return false;
|
@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 21 Sep 2016 22:54:28 -0400
|
||||
Subject: [PATCH] Chunk registration fixes
|
||||
|
||||
World checks and the Chunk Add logic are inconsistent on how Y > 256, < 0, is treated
|
||||
|
||||
Keep them consistent
|
||||
|
||||
No longer relevant in 1.17
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 335928d60dbfc07644ffeab366900c5e77e99d56..20650bfd10abfa010e71cfeede06c461d50d19a3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -841,7 +841,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
if (entity.checkAndResetUpdateChunkPos()) {
|
||||
this.getProfiler().push("chunkCheck");
|
||||
int i = Mth.floor(entity.getX() / 16.0D);
|
||||
- int j = Mth.floor(entity.getY() / 16.0D);
|
||||
+ int j = Math.min(15, Math.max(0, Mth.floor(entity.getY() / 16.0D))); // Paper - stay consistent with chunk add/remove behavior
|
||||
int k = Mth.floor(entity.getZ() / 16.0D);
|
||||
|
||||
if (!entity.inChunk || entity.xChunk != i || entity.yChunk != j || entity.zChunk != k) {
|
@ -1,107 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: vemacs <d@nkmem.es>
|
||||
Date: Wed, 23 Nov 2016 08:31:45 -0500
|
||||
Subject: [PATCH] Cache user authenticator threads
|
||||
|
||||
|
||||
TODO it looks like someone royally messed this one up, patch name doesn't remotely
|
||||
describe contents. Good thing this patch is no longer relevant at all
|
||||
|
||||
no remove queue anymore
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
index 0597c0c3e881dd43cf91bd3088ed30dfecfe8098..175bf535066afc42de8a3f0d11c46af66f3e3e52 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
||||
@@ -1388,7 +1388,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
||||
}
|
||||
}
|
||||
|
||||
- player.entitiesToRemove.remove(Integer.valueOf(this.entity.getId()));
|
||||
+ player.removeQueue.remove(Integer.valueOf(this.entity.getId()));
|
||||
// CraftBukkit end
|
||||
|
||||
if (flag1 && this.trackedPlayerMap.putIfAbsent(player, true) == null) { // Paper
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index 3a2356b3e00098d100a179a05316f402390d4e9b..3cde25c2479adcc4ce3014e5ac2ec0710bffeea9 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -4,7 +4,9 @@ import com.google.common.collect.Lists;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.DataResult;
|
||||
+import java.util.ArrayDeque; // Paper
|
||||
import java.util.Collection;
|
||||
+import java.util.Deque; // Paper
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -169,7 +171,7 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
public ServerGamePacketListenerImpl connection;
|
||||
public final MinecraftServer server;
|
||||
public final ServerPlayerGameMode gameMode;
|
||||
- public final List<Integer> entitiesToRemove = Lists.newLinkedList();
|
||||
+ public final Deque<Integer> removeQueue = new ArrayDeque<>(); // Paper
|
||||
private final PlayerAdvancements advancements;
|
||||
private final ServerStatsCounter stats;
|
||||
private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE;
|
||||
@@ -544,16 +546,23 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
this.containerMenu = this.inventoryMenu;
|
||||
}
|
||||
|
||||
- while (!this.entitiesToRemove.isEmpty()) {
|
||||
- int i = Math.min(this.entitiesToRemove.size(), Integer.MAX_VALUE);
|
||||
+ while (!this.removeQueue.isEmpty()) {
|
||||
+ int i = Math.min(this.removeQueue.size(), Integer.MAX_VALUE);
|
||||
int[] aint = new int[i];
|
||||
- Iterator<Integer> iterator = this.entitiesToRemove.iterator();
|
||||
+ //Iterator<Integer> iterator = this.removeQueue.iterator(); // Paper
|
||||
int j = 0;
|
||||
|
||||
- while (iterator.hasNext() && j < i) {
|
||||
+ // Paper start
|
||||
+ /* while (iterator.hasNext() && j < i) {
|
||||
aint[j++] = (Integer) iterator.next();
|
||||
iterator.remove();
|
||||
+ } */
|
||||
+
|
||||
+ Integer integer;
|
||||
+ while (j < i && (integer = this.removeQueue.poll()) != null) {
|
||||
+ aint[j++] = integer.intValue();
|
||||
}
|
||||
+ // Paper end
|
||||
|
||||
this.connection.send(new ClientboundRemoveEntitiesPacket(aint));
|
||||
}
|
||||
@@ -1558,7 +1567,14 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
this.lastSentHealth = -1.0F;
|
||||
this.lastSentFood = -1;
|
||||
// this.recipeBook.a((RecipeBook) entityplayer.recipeBook); // CraftBukkit
|
||||
- this.entitiesToRemove.addAll(oldPlayer.entitiesToRemove);
|
||||
+ // Paper start - Optimize remove queue - vanilla copies player objects, but CB doesn't. This method currently only
|
||||
+ // Applies to the same player, so we need to not duplicate our removal queue. The rest of this method does "resetting"
|
||||
+ // type logic so it does need to be called, maybe? This is silly.
|
||||
+ // this.removeQueue.addAll(entityplayer.removeQueue);
|
||||
+ if (this.removeQueue != oldPlayer.removeQueue) {
|
||||
+ this.removeQueue.addAll(oldPlayer.removeQueue);
|
||||
+ }
|
||||
+ // Paper end
|
||||
this.seenCredits = oldPlayer.seenCredits;
|
||||
this.enteredNetherPosition = oldPlayer.enteredNetherPosition;
|
||||
this.setShoulderEntityLeft(oldPlayer.getShoulderEntityLeft());
|
||||
@@ -1748,13 +1764,13 @@ public class ServerPlayer extends Player implements ContainerListener {
|
||||
if (entity instanceof Player) {
|
||||
this.connection.send(new ClientboundRemoveEntitiesPacket(new int[]{entity.getId()}));
|
||||
} else {
|
||||
- this.entitiesToRemove.add((Integer) entity.getId()); // CraftBukkit - decompile error
|
||||
+ this.removeQueue.add((Integer) entity.getId()); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void cancelRemoveEntity(Entity entity) {
|
||||
- this.entitiesToRemove.remove((Integer) entity.getId()); // CraftBukkit - decompile error
|
||||
+ this.removeQueue.remove((Integer) entity.getId()); // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@Override
|
@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Zach Brown <zach.brown@destroystokyo.com>
|
||||
Date: Sat, 13 May 2017 20:11:21 -0500
|
||||
Subject: [PATCH] Add system property to disable book size limits
|
||||
|
||||
If anyone comes in with a watchdog crash related to books after this patch
|
||||
you will not only be publicly shamed but also made an example of.
|
||||
|
||||
Disables the security limits on books entirely, allowing plugins AND players
|
||||
to make books with as much data as they want. Do not use this without
|
||||
limiting incoming data from packets in some other way.
|
||||
|
||||
Removed in 1.17: It was from a different time before books were as jank as they are now. As time has gone on they've only proven to be worse and worse.
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
|
||||
index a33dd184ea51df7e59ed08e5e2b0ea4ed9dadff5..1d94d285951faa98ff1f70c3c5330dfaa77cb691 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBook.java
|
||||
@@ -42,6 +42,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
|
||||
static final int MAX_PAGES = 100;
|
||||
static final int MAX_PAGE_LENGTH = 320; // 256 limit + 64 characters to allow for psuedo colour codes
|
||||
static final int MAX_TITLE_LENGTH = 32;
|
||||
+ private static final boolean OVERRIDE_CHECKS = Boolean.getBoolean("disable.book-limits"); // Paper - Add override
|
||||
|
||||
protected String title;
|
||||
protected String author;
|
||||
@@ -244,7 +245,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
|
||||
if (title == null) {
|
||||
this.title = null;
|
||||
return true;
|
||||
- } else if (title.length() > CraftMetaBook.MAX_TITLE_LENGTH) {
|
||||
+ } else if (title.length() > CraftMetaBook.MAX_TITLE_LENGTH && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -441,7 +442,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
|
||||
String validatePage(String page) {
|
||||
if (page == null) {
|
||||
page = "";
|
||||
- } else if (page.length() > CraftMetaBook.MAX_PAGE_LENGTH) {
|
||||
+ } else if (page.length() > CraftMetaBook.MAX_PAGE_LENGTH && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override
|
||||
page = page.substring(0, MAX_PAGE_LENGTH);
|
||||
}
|
||||
return page;
|
||||
@@ -451,7 +452,7 @@ public class CraftMetaBook extends CraftMetaItem implements BookMeta {
|
||||
// asserted: page != null
|
||||
if (this.pages == null) {
|
||||
this.pages = new ArrayList<String>();
|
||||
- } else if (this.pages.size() >= CraftMetaBook.MAX_PAGES) {
|
||||
+ } else if (this.pages.size() >= CraftMetaBook.MAX_PAGES && !CraftMetaBook.OVERRIDE_CHECKS) { // Paper - Add override
|
||||
return;
|
||||
}
|
||||
this.pages.add(page);
|
@ -1,20 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 29 Nov 2017 22:18:54 -0500
|
||||
Subject: [PATCH] Avoid NPE in PathfinderGoalTempt
|
||||
Not needed anymore
|
||||
similar check added by Mojang
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
index 186025458e923d153e9e47c2be147a9bb53db517..11ca6a752bac4ba4bc683bef844d204b739fab63 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
@@ -63,7 +63,7 @@ public class TemptGoal extends Goal {
|
||||
}
|
||||
this.target = (event.getTarget() == null) ? null : ((CraftLivingEntity) event.getTarget()).getHandle();
|
||||
}
|
||||
- return tempt;
|
||||
+ return tempt && this.target != null; // Paper - must have target - plugin might of cancelled
|
||||
// CraftBukkit end
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Wed, 21 Mar 2018 20:52:07 -0400
|
||||
Subject: [PATCH] Fix Dragon Server Crashes
|
||||
|
||||
If the dragon tries to find "ground" and hits a hole, or off edge,
|
||||
it will infinitely keep looking for non air and eventually crash.
|
||||
|
||||
Fixed in 1.15
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
|
||||
index df44bfce8cc492cd901dfa86331b9be7f1e13837..9eca797b4db96c5f2bb93d260f8e84077d92854a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
|
||||
@@ -64,7 +64,7 @@ public class DragonSittingFlamingPhase extends AbstractDragonSittingPhase {
|
||||
double h = g;
|
||||
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(d, g, e);
|
||||
|
||||
- while(this.dragon.level.isEmptyBlock(mutableBlockPos)) {
|
||||
+ while(this.dragon.level.isEmptyBlock(mutableBlockPos) && g > 0) { // Paper
|
||||
--h;
|
||||
if (h < 0.0D) {
|
||||
h = g;
|
@ -1,20 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 19 Jul 2018 01:05:00 -0400
|
||||
Subject: [PATCH] Don't change the Entity Random seed for squids
|
||||
|
||||
|
||||
Rebased into the patch to add the shared entity random
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Squid.java b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
index 5a7582fd4f8e883d2f08a0227932c17d7576b957..2e5a35565b6b7c4d3f7fdab45095f789c33f8937 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Squid.java
|
||||
@@ -48,7 +48,7 @@ public class Squid extends WaterAnimal {
|
||||
|
||||
public Squid(EntityType<? extends Squid> type, Level world) {
|
||||
super(type, world);
|
||||
- this.random.setSeed((long) this.getId());
|
||||
+ //this.random.setSeed((long) this.getId()); // Paper
|
||||
this.tentacleSpeed = 1.0F / (this.random.nextFloat() + 1.0F) * 0.2F;
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 19 Jul 2018 01:08:05 -0400
|
||||
Subject: [PATCH] Re-add vanilla entity warnings for duplicates
|
||||
|
||||
These are a critical sign that somethin went wrong, and you've lost some data....
|
||||
|
||||
We should kind of know about these things you know.
|
||||
|
||||
Spigot did not remove the warning in 1.17
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index ea1b15495481157912140bf5de9bf4a949c16910..914241a57c304fde220bc546261d6e959445772a 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1071,7 +1071,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
if (entity1 == null) {
|
||||
return false;
|
||||
} else {
|
||||
- // WorldServer.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityTypes.getName(entity1.getEntityType()), entity1.getId(), EntityTypes.getName(entity.getEntityType()), entity.getId()); // CraftBukkit
|
||||
+ ServerLevel.LOGGER.warn("Trying to add entity with duplicated UUID {}. Existing {}#{}, new: {}#{}", uuid, EntityType.getKey(entity1.getType()), entity1.getId(), EntityType.getKey(entity.getType()), entity.getId()); // CraftBukkit // Paper
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 23 Jul 2018 22:18:31 -0400
|
||||
Subject: [PATCH] Mark chunk dirty anytime entities change to guarantee it
|
||||
saves
|
||||
|
||||
Useless in 1.17 - leaf
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index d69ccb1f31f31ebeee477df20ce1410f9e485eb7..bd9b19d988ecf72e099efeff6ec3483a352174ec 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -559,6 +559,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
entity.zChunk = this.chunkPos.z;
|
||||
this.entities.add(entity); // Paper - per chunk entity list
|
||||
this.entitySlices[k].add(entity);
|
||||
+ this.markUnsaved(); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -587,6 +588,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
return;
|
||||
}
|
||||
entityCounts.decrement(entity.getMinecraftKeyString());
|
||||
+ this.markUnsaved(); // Paper
|
||||
// Paper end
|
||||
this.entities.remove(entity); // Paper
|
||||
}
|
@ -1,101 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Mon, 23 Jul 2018 22:44:23 -0400
|
||||
Subject: [PATCH] Add some Debug to Chunk Entity slices
|
||||
|
||||
If we detect unexpected state, log and try to recover
|
||||
|
||||
This should hopefully avoid duplicate entities ever being created
|
||||
if the entity was to end up in 2 different chunk slices
|
||||
|
||||
Useless in 1.17
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index a2cc3e58d59ed3d9f443b77c44d8200cc09b4da9..7847078c54154e28ab066ea8a329f929df1e1a37 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -156,6 +156,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
}
|
||||
}
|
||||
};
|
||||
+ public List<Entity> entitySlice = null;
|
||||
// Paper end
|
||||
|
||||
public com.destroystokyo.paper.loottable.PaperLootableInventoryData lootableData; // Paper
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index bd9b19d988ecf72e099efeff6ec3483a352174ec..09aa608bd303b618ae2c0ebd237bcbdba60a37a8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -26,7 +26,9 @@ import net.minecraft.ReportedException;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ChunkHolder;
|
||||
+import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -550,6 +552,25 @@ public class LevelChunk implements ChunkAccess {
|
||||
if (k >= this.entitySlices.length) {
|
||||
k = this.entitySlices.length - 1;
|
||||
}
|
||||
+ // Paper - remove from any old list if its in one
|
||||
+ List<Entity> nextSlice = this.entitySlices[k]; // the next list to be added to
|
||||
+ List<Entity> currentSlice = entity.entitySlice;
|
||||
+ if (nextSlice == currentSlice) {
|
||||
+ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity was already in this chunk!" + entity, new Throwable());
|
||||
+ return; // ??? silly plugins
|
||||
+ }
|
||||
+ if (currentSlice != null && currentSlice.contains(entity)) {
|
||||
+ // Still in an old chunk...
|
||||
+ if (Level.DEBUG_ENTITIES) MinecraftServer.LOGGER.warn("Entity is still in another chunk!" + entity, new Throwable());
|
||||
+ LevelChunk chunk = entity.getCurrentChunk();
|
||||
+ if (chunk != null) {
|
||||
+ chunk.removeEntity(entity);
|
||||
+ } else {
|
||||
+ removeEntity(entity);
|
||||
+ }
|
||||
+ currentSlice.remove(entity); // Just incase the above did not remove from the previous slice
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (!entity.inChunk || entity.getCurrentChunk() != this) entityCounts.increment(entity.getMinecraftKeyString()); // Paper
|
||||
entity.inChunk = true;
|
||||
@@ -559,6 +580,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
entity.zChunk = this.chunkPos.z;
|
||||
this.entities.add(entity); // Paper - per chunk entity list
|
||||
this.entitySlices[k].add(entity);
|
||||
+ entity.entitySlice = this.entitySlices[k]; // Paper
|
||||
this.markUnsaved(); // Paper
|
||||
}
|
||||
|
||||
@@ -584,6 +606,10 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
// Paper start
|
||||
if (entity.currentChunk != null && entity.currentChunk.get() == this) entity.setCurrentChunk(null);
|
||||
+ if (entitySlices[section] == entity.entitySlice) {
|
||||
+ entity.entitySlice = null;
|
||||
+ entity.inChunk = false;
|
||||
+ }
|
||||
if (!this.entitySlices[section].remove(entity)) {
|
||||
return;
|
||||
}
|
||||
@@ -742,7 +768,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
// Paper start - neighbour cache
|
||||
int chunkX = this.chunkPos.x;
|
||||
int chunkZ = this.chunkPos.z;
|
||||
- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource();
|
||||
+ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource();
|
||||
for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) {
|
||||
for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) {
|
||||
LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz);
|
||||
@@ -802,7 +828,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
// Paper start - neighbour cache
|
||||
int chunkX = this.chunkPos.x;
|
||||
int chunkZ = this.chunkPos.z;
|
||||
- ChunkProviderServer chunkProvider = ((ServerLevel)this.world).getChunkSource();
|
||||
+ ServerChunkCache chunkProvider = ((ServerLevel)this.world).getChunkSource();
|
||||
for (int dx = -NEIGHBOUR_CACHE_RADIUS; dx <= NEIGHBOUR_CACHE_RADIUS; ++dx) {
|
||||
for (int dz = -NEIGHBOUR_CACHE_RADIUS; dz <= NEIGHBOUR_CACHE_RADIUS; ++dz) {
|
||||
LevelChunk neighbour = chunkProvider.getChunkAtIfLoadedMainThreadNoCache(chunkX + dx, chunkZ + dz);
|
@ -1,129 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 26 Jul 2018 00:11:12 -0400
|
||||
Subject: [PATCH] Prevent Saving Bad entities to chunks
|
||||
|
||||
See https://github.com/PaperMC/Paper/issues/1223
|
||||
|
||||
Minecraft is saving invalid entities to the chunk files.
|
||||
|
||||
Avoid saving bad data, and also make improvements to handle
|
||||
loading these chunks. Any invalid entity will be instant killed,
|
||||
so lets avoid adding it to the world...
|
||||
|
||||
This lets us be safer about the dupe UUID resolver too, as now
|
||||
we can ignore instant killed entities and avoid risk of duplicating
|
||||
an invalid entity.
|
||||
|
||||
This should reduce log occurrences of dupe uuid messages.
|
||||
|
||||
1.17, not a concern anymore
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index a5d7781b13a6d61238d026f064512f7162e1e868..8e8e5f30c512ed7d8ee987550c22d3e9df845043 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1151,6 +1151,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
List[] aentityslice = chunk.getEntitySlices(); // Spigot
|
||||
int i = aentityslice.length;
|
||||
|
||||
+ java.util.List<Entity> toMoveChunks = new java.util.ArrayList<>(); // Paper
|
||||
for (int j = 0; j < i; ++j) {
|
||||
List<Entity> entityslice = aentityslice[j]; // Spigot
|
||||
Iterator iterator = entityslice.iterator();
|
||||
@@ -1163,11 +1164,25 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
throw (IllegalStateException) Util.pauseInIde((Throwable) (new IllegalStateException("Removing entity while ticking!")));
|
||||
}
|
||||
|
||||
+ // Paper start - move out entities that shouldn't be in this chunk before it unloads
|
||||
+ if (!entity.removed && (int) Math.floor(entity.getX()) >> 4 != chunk.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk.getPos().z) {
|
||||
+ toMoveChunks.add(entity);
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
this.entitiesById.remove(entity.getId());
|
||||
this.onEntityRemoved(entity);
|
||||
+
|
||||
+ if (entity.removed) iterator.remove(); // Paper - don't save dead entities during unload
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // Paper start - move out entities that shouldn't be in this chunk before it unloads
|
||||
+ for (Entity entity : toMoveChunks) {
|
||||
+ this.updateChunkPos(entity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
index 0efaf4d0f58bcf38b427e76bf09b96e354294159..542d6f322df5f44ad9f504c8e14c88e3fa540657 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkSerializer.java
|
||||
@@ -27,6 +27,7 @@ import net.minecraft.nbt.LongArrayTag;
|
||||
import net.minecraft.nbt.ShortTag;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
@@ -349,6 +350,7 @@ public class ChunkSerializer {
|
||||
nbttagcompound1.put("TileEntities", nbttaglist1);
|
||||
ListTag nbttaglist2 = new ListTag();
|
||||
|
||||
+ java.util.List<Entity> toUpdate = new java.util.ArrayList<>(); // Paper
|
||||
if (chunk.getStatus().getChunkType() == ChunkStatus.ChunkType.LEVELCHUNK) {
|
||||
LevelChunk chunk1 = (LevelChunk) chunk;
|
||||
|
||||
@@ -366,13 +368,28 @@ public class ChunkSerializer {
|
||||
while (iterator1.hasNext()) {
|
||||
Entity entity = (Entity) iterator1.next();
|
||||
CompoundTag nbttagcompound4 = new CompoundTag();
|
||||
-
|
||||
+ // Paper start
|
||||
+ if ((int) Math.floor(entity.getX()) >> 4 != chunk1.getPos().x || (int) Math.floor(entity.getZ()) >> 4 != chunk1.getPos().z) {
|
||||
+ toUpdate.add(entity);
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (entity.removed || hasPlayerPassenger(entity)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (entity.save(nbttagcompound4)) {
|
||||
chunk1.setLastSaveHadEntities(true);
|
||||
nbttaglist2.add(nbttagcompound4);
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Paper start - move entities to the correct chunk
|
||||
+ for (Entity entity : toUpdate) {
|
||||
+ world.updateChunkPos(entity);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
} else {
|
||||
ProtoChunk protochunk = (ProtoChunk) chunk;
|
||||
|
||||
@@ -431,6 +448,19 @@ public class ChunkSerializer {
|
||||
nbttagcompound1.put("Structures", packStructureData(chunkcoordintpair, chunk.getAllStarts(), chunk.getAllReferences()));
|
||||
return nbttagcompound;
|
||||
}
|
||||
+ // Paper start - this is saved with the player
|
||||
+ private static boolean hasPlayerPassenger(Entity entity) {
|
||||
+ for (Entity passenger : entity.passengers) {
|
||||
+ if (passenger instanceof ServerPlayer) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ if (hasPlayerPassenger(passenger)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public static ChunkStatus.ChunkType getChunkTypeFromTag(@Nullable CompoundTag tag) {
|
||||
if (tag != null) {
|
@ -1,122 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 28 Jul 2018 12:18:27 -0400
|
||||
Subject: [PATCH] Ignore Dead Entities in entityList iteration
|
||||
|
||||
A spigot change delays removal of entities from the entity list.
|
||||
This causes a change in behavior from Vanilla where getEntities type
|
||||
methods will return dead entities that they shouldn't otherwise be doing.
|
||||
|
||||
This will ensure that dead entities are skipped from iteration since
|
||||
they shouldn't of been in the list in the first place.
|
||||
|
||||
Not relevant in 1.17
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperCommand.java b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
index e95b91cefb0374bd5bb57cc090f5ecd566d7a618..8fd716bf2e1402694798b8be03fd85821153be44 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperCommand.java
|
||||
@@ -209,6 +209,7 @@ public class PaperCommand extends Command {
|
||||
Collection<Entity> entities = world.entitiesById.values();
|
||||
entities.forEach(e -> {
|
||||
ResourceLocation key = e.getMinecraftKey();
|
||||
+ if (e.shouldBeRemoved) return; // Paper
|
||||
|
||||
MutablePair<Integer, Map<ChunkPos, Integer>> info = list.computeIfAbsent(key, k -> MutablePair.of(0, Maps.newHashMap()));
|
||||
ChunkPos chunk = new ChunkPos(e.xChunk, e.zChunk);
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 8e8e5f30c512ed7d8ee987550c22d3e9df845043..84b2cd661697545186677ab7966556d9288c650b 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1303,6 +1303,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
entity.origin = entity.getBukkitEntity().getLocation();
|
||||
}
|
||||
// Paper end
|
||||
+ entity.shouldBeRemoved = false; // Paper - shouldn't be removed after being re-added
|
||||
new com.destroystokyo.paper.event.entity.EntityAddToWorldEvent(entity.getBukkitEntity()).callEvent(); // Paper - fire while valid
|
||||
}
|
||||
|
||||
@@ -1315,6 +1316,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
this.removeFromChunk(entity);
|
||||
this.entitiesById.remove(entity.getId());
|
||||
this.onEntityRemoved(entity);
|
||||
+ entity.shouldBeRemoved = true; // Paper
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 7847078c54154e28ab066ea8a329f929df1e1a37..5bf6bc6a01ccde8a4d67b49293bb326cb09248d8 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -275,6 +275,7 @@ public abstract class Entity implements Nameable, CommandSource, net.minecraft.s
|
||||
protected int numCollisions = 0; // Paper
|
||||
public void inactiveTick() { }
|
||||
// Spigot end
|
||||
+ public boolean shouldBeRemoved; // Paper
|
||||
|
||||
public float getBukkitYaw() {
|
||||
return this.yRot;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
index 09aa608bd303b618ae2c0ebd237bcbdba60a37a8..db28bfe95c885cdefa855c7aaa3bcf92bc52df26 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
|
||||
@@ -862,6 +862,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
for (int i1 = 0; i1 < l; ++i1) {
|
||||
Entity entity1 = (Entity) list1.get(i1);
|
||||
+ if (entity1.shouldBeRemoved) continue; // Paper
|
||||
|
||||
if (entity1.getBoundingBox().intersects(box) && entity1 != except) {
|
||||
if (predicate == null || predicate.test(entity1)) {
|
||||
@@ -899,6 +900,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
T entity = (T) iterator.next(); // CraftBukkit - decompile error
|
||||
+ if (entity.shouldBeRemoved) continue; // Paper
|
||||
|
||||
if ((type == null || entity.getType() == type) && entity.getBoundingBox().intersects(box) && predicate.test(entity)) {
|
||||
result.add(entity);
|
||||
@@ -921,6 +923,7 @@ public class LevelChunk implements ChunkAccess {
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
T t0 = (T) iterator.next(); // CraftBukkit - decompile error
|
||||
+ if (t0.shouldBeRemoved) continue; // Paper
|
||||
|
||||
if (entityClass.isInstance(t0) && t0.getBoundingBox().intersects(box) && (predicate == null || predicate.test(t0))) { // Spigot - instance check
|
||||
result.add(t0);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
index 3a3466cd9bbd34dbc0b79567f5579e84a81d6009..9807612aed6c4393cbe1f4b6078e45bf1ba3deb2 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
||||
@@ -1022,6 +1022,7 @@ public class CraftWorld implements World {
|
||||
for (Object o : world.entitiesById.values()) {
|
||||
if (o instanceof net.minecraft.world.entity.Entity) {
|
||||
net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o;
|
||||
+ if (mcEnt.shouldBeRemoved) continue; // Paper
|
||||
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
||||
|
||||
// Assuming that bukkitEntity isn't null
|
||||
@@ -1041,6 +1042,7 @@ public class CraftWorld implements World {
|
||||
for (Object o : world.entitiesById.values()) {
|
||||
if (o instanceof net.minecraft.world.entity.Entity) {
|
||||
net.minecraft.world.entity.Entity mcEnt = (net.minecraft.world.entity.Entity) o;
|
||||
+ if (mcEnt.shouldBeRemoved) continue; // Paper
|
||||
Entity bukkitEntity = mcEnt.getBukkitEntity();
|
||||
|
||||
// Assuming that bukkitEntity isn't null
|
||||
@@ -1067,6 +1069,7 @@ public class CraftWorld implements World {
|
||||
|
||||
for (Object entity: world.entitiesById.values()) {
|
||||
if (entity instanceof net.minecraft.world.entity.Entity) {
|
||||
+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper
|
||||
Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity();
|
||||
|
||||
if (bukkitEntity == null) {
|
||||
@@ -1090,6 +1093,7 @@ public class CraftWorld implements World {
|
||||
|
||||
for (Object entity: world.entitiesById.values()) {
|
||||
if (entity instanceof net.minecraft.world.entity.Entity) {
|
||||
+ if (((net.minecraft.world.entity.Entity) entity).shouldBeRemoved) continue; // Paper
|
||||
Entity bukkitEntity = ((net.minecraft.world.entity.Entity) entity).getBukkitEntity();
|
||||
|
||||
if (bukkitEntity == null) {
|
@ -1,46 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Thu, 28 Feb 2019 00:15:28 -0500
|
||||
Subject: [PATCH] Fix sign edit memory leak
|
||||
|
||||
when a player edits a sign, a reference to their Entity is never cleand up.
|
||||
|
||||
removed 1.17 - mojang uses a UUID instead of a player field now
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index b1c505d3fdcc2fb3496f80bee85e4895b9069dcb..276773e17149f57038cd21485fd9d9061670ff2d 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -2850,7 +2850,7 @@ public class ServerGamePacketListenerImpl implements ServerGamePacketListener {
|
||||
|
||||
SignBlockEntity tileentitysign = (SignBlockEntity) tileentity;
|
||||
|
||||
- if (!tileentitysign.isEditable() || tileentitysign.getPlayerWhoMayEdit() != this.player) {
|
||||
+ if (!tileentitysign.isEditable() || tileentitysign.signEditor == null || !tileentitysign.signEditor.equals(this.player.getUUID())) {
|
||||
ServerGamePacketListenerImpl.LOGGER.warn("Player {} just tried to change non-editable sign", this.player.getName().getString());
|
||||
this.send(tileentity.getUpdatePacket()); // CraftBukkit
|
||||
return;
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
index e4eab82855649fec654c60b2e94ba7b71c2ac5a2..0b26d3ab2db66d6baaa95d1d5f6c756595d31495 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/SignBlockEntity.java
|
||||
@@ -30,6 +30,7 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
|
||||
private Player playerWhoMayEdit;
|
||||
private final FormattedCharSequence[] renderMessages;
|
||||
private DyeColor color;
|
||||
+ public java.util.UUID signEditor; // Paper
|
||||
|
||||
public SignBlockEntity() {
|
||||
super(BlockEntityType.SIGN);
|
||||
@@ -131,7 +132,10 @@ public class SignBlockEntity extends BlockEntity implements CommandSource { // C
|
||||
}
|
||||
|
||||
public void setAllowedPlayerEditor(Player player) {
|
||||
- this.playerWhoMayEdit = player;
|
||||
+ // Paper start
|
||||
+ //this.c = entityhuman;
|
||||
+ signEditor = player != null ? player.getUUID() : null;
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
public Player getPlayerWhoMayEdit() {
|
@ -1,27 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: William Blake Galbreath <blake.galbreath@gmail.com>
|
||||
Date: Mon, 27 May 2019 17:35:39 -0500
|
||||
Subject: [PATCH] MC-114618 - Fix EntityAreaEffectCloud from going negative
|
||||
size
|
||||
|
||||
1.17 update note: Likely fixed in 1.17
|
||||
|
||||
fixed https://bugs.mojang.com/browse/MC-114618
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
index 4733f74ff028c03a60b73280caf9e4d1e2f0ca30..882c216b508a8623c2393b668cff6d702fe738b9 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/AreaEffectCloud.java
|
||||
@@ -197,6 +197,12 @@ public class AreaEffectCloud extends Entity {
|
||||
super.tick();
|
||||
boolean flag = this.isWaiting();
|
||||
float f = this.getRadius();
|
||||
+ // Paper start - fix MC-114618
|
||||
+ if (f < 0.0F) {
|
||||
+ this.remove();
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
if (this.level.isClientSide) {
|
||||
if (flag && this.random.nextBoolean()) {
|
@ -1,33 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Mon, 10 Jun 2019 09:36:40 +0100
|
||||
Subject: [PATCH] Catch exceptions from dispenser entity spawns
|
||||
mojang(?) added similar warning
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
index dccf689d17bb5a77abf97779663413d01e840c23..67a894a185a3d4a53b3c7f90174b2604dff18257 100644
|
||||
--- a/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
+++ b/src/main/java/net/minecraft/core/dispenser/DispenseItemBehavior.java
|
||||
@@ -8,6 +8,7 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockSource;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Position;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
@@ -235,7 +236,14 @@ public interface DispenseItemBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
+ try { // Paper
|
||||
entitytypes.spawn(pointer.getLevel(), stack, (Player) null, pointer.getPos().relative(enumdirection), MobSpawnType.DISPENSER, enumdirection != Direction.UP, false);
|
||||
+ // Paper start
|
||||
+ } catch (Exception ex){
|
||||
+ MinecraftServer.LOGGER.warn("An exception occurred dispensing entity at {}[{}]", worldserver.getWorld().getName(), pointer.getPos(), ex);
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
// itemstack.subtract(1); // Handled during event processing
|
||||
// CraftBukkit end
|
||||
return stack;
|
@ -1,26 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shane Freeder <theboyetronic@gmail.com>
|
||||
Date: Sun, 28 Jul 2019 00:51:11 +0100
|
||||
Subject: [PATCH] Mark entities as being ticked when notifying navigation
|
||||
1.17: Check how this is done after rework
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 7a09bc921827958f58290bd3d6f19984bb34a8f6..a811ced17721b70bb51837f47e466c2261db2466 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1469,6 +1469,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
VoxelShape voxelshape1 = newState.getCollisionShape(this, pos);
|
||||
|
||||
if (Shapes.joinIsNotEmpty(voxelshape, voxelshape1, BooleanOp.NOT_SAME)) {
|
||||
+ boolean wasTicking = this.tickingEntities; this.tickingEntities = true; // Paper
|
||||
Iterator iterator = this.navigations.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -1490,6 +1491,7 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
}
|
||||
}
|
||||
|
||||
+ this.tickingEntities = wasTicking; // Paper
|
||||
}
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: wea_ondara <wea_ondara@alpenblock.net>
|
||||
Date: Thu, 10 Oct 2019 11:29:42 +0200
|
||||
Subject: [PATCH] Performance improvement for Chunk.getEntities
|
||||
|
||||
This patch aims to reduce performance cost used by collecting the
|
||||
entities of a chunk. Previously the entitySlices were copied into an
|
||||
extra array with List.toArray() with is a costly and unneccessary
|
||||
operation. This patch will reduce the load of plugins which for example
|
||||
implement custom moblimits and depend on Chunk.getEntities().
|
||||
|
||||
1.17: needs to be reworked, entities not in chunk anymore
|
||||
|
||||
no longer needed as no toArray is called during getEntities due to rewrite of entity system
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
index 74bad15034d9d55fb70931f38868f812160c6305..0f45f4b2486e910d11fd94b260bcd68e49eae31e 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/CraftChunk.java
|
||||
@@ -116,14 +116,14 @@ public class CraftChunk implements Chunk {
|
||||
Entity[] entities = new Entity[count];
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
-
|
||||
- for (Object obj : chunk.entitySlices[i].toArray()) {
|
||||
- if (!(obj instanceof net.minecraft.world.entity.Entity)) {
|
||||
+ // Paper start - speed up (was with chunk.entitySlices[i].toArray() and cast checks which costs a lot of performance if called often)
|
||||
+ for (net.minecraft.world.entity.Entity entity : chunk.entitySlices[i]) {
|
||||
+ if (entity == null) {
|
||||
continue;
|
||||
}
|
||||
-
|
||||
- entities[index++] = ((net.minecraft.world.entity.Entity) obj).getBukkitEntity();
|
||||
+ entities[index++] = entity.getBukkitEntity();
|
||||
}
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
return entities;
|
@ -1,36 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Tue, 31 Mar 2020 03:01:45 -0400
|
||||
Subject: [PATCH] Fix unregistering entities from unloading chunks
|
||||
|
||||
CraftBukkit caused a regression here by making unloading chunks not
|
||||
have a ticket added and returning unloaded future.
|
||||
|
||||
This caused entities who were killed in same tick their chunk is unloading
|
||||
to not be able to be removed from the chunk.
|
||||
|
||||
This then results in dead entities lingering in the Chunk.
|
||||
|
||||
Combine that with a buggy detail of the previous implementation of
|
||||
the Dupe UUID patch, then this was the likely source of the "Ghost entities"
|
||||
|
||||
1.17: Probably not needed?
|
||||
|
||||
no longer applies as entities not stored in chunks
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 9898d5c8fab63c576831bd416ccf1854ed077b0d..c5dc41a3cf499038bd33451a189913cd3978b230 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1559,9 +1559,9 @@ public class ServerLevel extends net.minecraft.world.level.Level implements Worl
|
||||
}
|
||||
|
||||
private void removeFromChunk(Entity entity) {
|
||||
- ChunkAccess ichunkaccess = chunkSource.getChunkUnchecked(entity.xChunk, entity.zChunk); // CraftBukkit - SPIGOT-5228: getChunkAt won't find the entity's chunk if it has already been unloaded (i.e. if it switched to state INACCESSIBLE).
|
||||
+ LevelChunk ichunkaccess = entity.getCurrentChunk(); // Paper - getChunkAt(x,z,full,false) is broken by CraftBukkit as it won't return an unloading chunk. Use our current chunk reference as this points to what chunk they need to be removed from anyways
|
||||
|
||||
- if (ichunkaccess instanceof LevelChunk) {
|
||||
+ if (ichunkaccess != null) { // Paper
|
||||
((LevelChunk) ichunkaccess).removeEntity(entity);
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Fri, 14 Aug 2020 23:41:19 +0200
|
||||
Subject: [PATCH] Don't mark null chunk sections for block updates
|
||||
|
||||
no longer needed as the accessor to get chunksection handles null chunk sections
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
index 1f67c9c5f7161ea687983e7ae0ec7d259da9acd3..32bcc55ce15d832e2182d89acecd715947b1667d 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
|
||||
@@ -315,6 +315,7 @@ public class ChunkHolder {
|
||||
this.a(world, blockposition, iblockdata);
|
||||
} else {
|
||||
LevelChunkSection chunksection = chunk.getSections()[j];
|
||||
+ if (chunksection == null) chunksection = new LevelChunkSection(sectionposition.getY(), chunk, world, true); // Paper - make a new chunk section if none was found
|
||||
ClientboundSectionBlocksUpdatePacket packetplayoutmultiblockchange = new ClientboundSectionBlocksUpdatePacket(sectionposition, shortset, chunksection, this.resendLight);
|
||||
|
||||
this.broadcast(packetplayoutmultiblockchange, false);
|
@ -1,32 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
||||
Date: Fri, 12 Jun 2020 22:25:11 -0700
|
||||
Subject: [PATCH] Fix enderdragon exp dupe
|
||||
|
||||
Properly track death stage when unloading/loading in the
|
||||
dragon
|
||||
|
||||
1.17: Mojang fixed in 1.17(maybe before, idk)
|
||||
|
||||
resolved by Mojang https://bugs.mojang.com/browse/MCPE-64818
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
index ec9436005a3a6fdfb4783d1092bb361224eb6414..b224a630f8adb1fa357c838e6b32c784aed0b15b 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -879,6 +879,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
tag.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId());
|
||||
+ tag.putInt("Paper.DeathTick", this.dragonDeathTime); // Paper
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -887,6 +888,7 @@ public class EnderDragon extends Mob implements Enemy {
|
||||
if (tag.contains("DragonPhase")) {
|
||||
this.phaseManager.setPhase(EnderDragonPhase.getById(tag.getInt("DragonPhase")));
|
||||
}
|
||||
+ this.dragonDeathTime = tag.getInt("Paper.DeathTick"); // Paper
|
||||
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Trigary <trigary0@gmail.com>
|
||||
Date: Fri, 14 Sep 2018 17:42:08 +0200
|
||||
Subject: [PATCH] Limit lightning strike effect distance
|
||||
|
||||
Doesnt seem to apply anymore as spigot isn't using relative distance for lightning
|
||||
|
||||
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
index 1655bca0502e7b871de4addaa163536d86547a02..978062774c1db286bfb9b0ffdef19d880b1f249b 100644
|
||||
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
||||
@@ -646,4 +646,26 @@ public class PaperWorldConfig {
|
||||
delayChunkUnloadsBy *= 20;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ public double sqrMaxThunderDistance;
|
||||
+ public double sqrMaxLightningImpactSoundDistance;
|
||||
+ public double maxLightningFlashDistance;
|
||||
+ private void lightningStrikeDistanceLimit() {
|
||||
+ sqrMaxThunderDistance = getInt("lightning-strike-distance-limit.sound", -1);
|
||||
+ if (sqrMaxThunderDistance > 0) {
|
||||
+ sqrMaxThunderDistance *= sqrMaxThunderDistance;
|
||||
+ }
|
||||
+
|
||||
+ sqrMaxLightningImpactSoundDistance = getInt("lightning-strike-distance-limit.impact-sound", -1);
|
||||
+ if (sqrMaxLightningImpactSoundDistance < 0) {
|
||||
+ sqrMaxLightningImpactSoundDistance = 32 * 32; //Vanilla value
|
||||
+ } else {
|
||||
+ sqrMaxLightningImpactSoundDistance *= sqrMaxLightningImpactSoundDistance;
|
||||
+ }
|
||||
+
|
||||
+ maxLightningFlashDistance = getInt("lightning-strike-distance-limit.flash", -1);
|
||||
+ if (maxLightningFlashDistance < 0) {
|
||||
+ maxLightningFlashDistance = 512; // Vanilla value
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LightningBolt.java b/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
index e030e7f3d8bd9fe6578df0b560a237d494ec8a01..4b0dbeded2b8a475d32f518957909d3495a4b6fc 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LightningBolt.java
|
||||
@@ -15,7 +15,6 @@ import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.Difficulty;
|
||||
-import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.GameRules;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -74,6 +73,17 @@ public class LightningBolt extends Entity {
|
||||
double deltaX = this.getX() - player.getX();
|
||||
double deltaZ = this.getZ() - player.getZ();
|
||||
double distanceSquared = deltaX * deltaX + deltaZ * deltaZ;
|
||||
+ // Paper start - Limit lightning strike effect distance
|
||||
+ if (distanceSquared <= this.level.paperConfig.sqrMaxLightningImpactSoundDistance) {
|
||||
+ player.connection.send(new ClientboundSoundPacket(SoundEvents.LIGHTNING_BOLT_IMPACT,
|
||||
+ SoundSource.WEATHER, this.getX(), this.getY(), this.getZ(), 2.0f, 0.5F + this.random.nextFloat() * 0.2F));
|
||||
+ }
|
||||
+
|
||||
+ if (level.paperConfig.sqrMaxThunderDistance != -1 && distanceSquared >= level.paperConfig.sqrMaxThunderDistance) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // Paper end
|
||||
if (distanceSquared > viewDistance * viewDistance) {
|
||||
double deltaLength = Math.sqrt(distanceSquared);
|
||||
double relativeX = player.getX() + (deltaX / deltaLength) * viewDistance;
|
||||
@@ -84,7 +94,7 @@ public class LightningBolt extends Entity {
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
- this.level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.LIGHTNING_BOLT_IMPACT, SoundSource.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F);
|
||||
+// this.world.playSound((EntityHuman) null, this.locX(), this.locY(), this.locZ(), SoundEffects.ENTITY_LIGHTNING_BOLT_IMPACT, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F); // Paper - Limit lightning strike effect distance (the packet is now sent from inside the loop)
|
||||
}
|
||||
|
||||
--this.life;
|
@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Wed, 12 Aug 2020 11:33:04 +0200
|
||||
Subject: [PATCH] Import fastutil classes
|
||||
1.17: YEET
|
||||
we use real mappings now so a class called 'it' in nms is no longer a concern
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
index 95e166aa63f42c675df645a56e313bdffc2e8663..05f7d4a3835536f26f741d54a0884bd43fc82967 100644
|
||||
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
@@ -16,6 +16,7 @@ import net.minecraft.CrashReport;
|
||||
import net.minecraft.ReportedException;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -25,7 +26,7 @@ public class SynchedEntityData {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Map<Class<? extends Entity>, Integer> ENTITY_ID_POOL = Maps.newHashMap();
|
||||
private final Entity entity;
|
||||
- private final it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<SynchedEntityData.DataItem<?>> entries = new it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL
|
||||
+ private final Int2ObjectOpenHashMap<DataItem<?>> entries = new Int2ObjectOpenHashMap<>(); // Spigot - use better map // PAIL
|
||||
// private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required
|
||||
private boolean isEmpty = true;
|
||||
private boolean isDirty;
|
@ -1,30 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Mariell Hoversholm <proximyst@proximyst.com>
|
||||
Date: Fri, 14 Aug 2020 23:59:26 +0200
|
||||
Subject: [PATCH] Remove armour stand double add to world
|
||||
1.17 Update: YEET (?)
|
||||
|
||||
Applied by Mojang
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ArmorStandItem.java b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
index a2dfcaac8a2a4a69e703de43be76d4fe369fd647..bed063497bb593683ea384605ae1a71a68f4fc1b 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ArmorStandItem.java
|
||||
@@ -53,7 +53,7 @@ public class ArmorStandItem extends Item {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
- worldserver.addFreshEntityWithPassengers(entityarmorstand);
|
||||
+ // Paper - moved down
|
||||
float f = (float) Mth.floor((Mth.wrapDegrees(context.getRotation() - 180.0F) + 22.5F) / 45.0F) * 45.0F;
|
||||
|
||||
entityarmorstand.moveTo(entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), f, 0.0F);
|
||||
@@ -63,7 +63,7 @@ public class ArmorStandItem extends Item {
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
// CraftBukkit end
|
||||
- world.addFreshEntity(entityarmorstand);
|
||||
+ worldserver.addFreshEntityWithPassengers(entityarmorstand); // Paper - moved down
|
||||
world.playSound((Player) null, entityarmorstand.getX(), entityarmorstand.getY(), entityarmorstand.getZ(), SoundEvents.ARMOR_STAND_PLACE, SoundSource.BLOCKS, 0.75F, 0.8F);
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
||||
Date: Thu, 20 Aug 2020 19:24:13 -0700
|
||||
Subject: [PATCH] Fix MC-99259 Wither Boss Bar doesn't update until
|
||||
1.17 Update: This issue is marked as fixed on 1.17 - yeet!
|
||||
invulnerability period is over
|
||||
|
||||
Resolved https://bugs.mojang.com/browse/MC-99259
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
index edd231568b75330d0cffbecb03a7e9dbc55d5f94..1f330d852eb9b3a36570542e10a88ae065798714 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -391,8 +391,9 @@ public class WitherBoss extends Monster implements RangedAttackMob {
|
||||
this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
|
||||
}
|
||||
|
||||
- this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth());
|
||||
+ //this.bossBattle.setProgress(this.getHealth() / this.getMaxHealth()); // Paper - Moved down
|
||||
}
|
||||
+ this.bossEvent.setPercent(this.getHealth() / this.getMaxHealth()); // Paper - Fix MC-99259 (Boss bar does not update until Wither invulnerability period ends)
|
||||
}
|
||||
|
||||
public static boolean canDestroy(BlockState block) {
|
@ -1,53 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Sun, 23 Aug 2020 10:57:44 +0200
|
||||
Subject: [PATCH] Fix MC-197271
|
||||
Update 1.17: Fixed in openj9-0.23.0-m2 release
|
||||
This patch only fixes an issue for servers running OpenJ9.
|
||||
|
||||
resolved https://bugs.mojang.com/browse/MC-197271
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/data/BuiltinRegistries.java b/src/main/java/net/minecraft/data/BuiltinRegistries.java
|
||||
index d64cebb4431664762a14670c7d9d782dd7894ed5..0c403ea85f7ea20f2f978e06313f8675abf204b6 100644
|
||||
--- a/src/main/java/net/minecraft/data/BuiltinRegistries.java
|
||||
+++ b/src/main/java/net/minecraft/data/BuiltinRegistries.java
|
||||
@@ -48,11 +48,11 @@ public class BuiltinRegistries {
|
||||
public static final Registry<StructureProcessorList> PROCESSOR_LIST = registerSimple(Registry.PROCESSOR_LIST_REGISTRY, () -> {
|
||||
return ProcessorLists.b;
|
||||
});
|
||||
- public static final Registry<StructureTemplatePool> TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, Pools::bootstrap);
|
||||
+ public static final Registry<StructureTemplatePool> TEMPLATE_POOL = registerSimple(Registry.TEMPLATE_POOL_REGISTRY, () -> Pools.bootstrap()); // Paper - MC-197271
|
||||
public static final Registry<Biome> BIOME = registerSimple(Registry.BIOME_REGISTRY, () -> {
|
||||
return Biomes.PLAINS;
|
||||
});
|
||||
- public static final Registry<NoiseGeneratorSettings> NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, NoiseGeneratorSettings::bootstrap);
|
||||
+ public static final Registry<NoiseGeneratorSettings> NOISE_GENERATOR_SETTINGS = registerSimple(Registry.NOISE_GENERATOR_SETTINGS_REGISTRY, () -> NoiseGeneratorSettings.bootstrap()); // Paper - MC-197271
|
||||
|
||||
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> registryRef, Supplier<T> defaultValueSupplier) {
|
||||
return registerSimple(registryRef, Lifecycle.stable(), defaultValueSupplier);
|
||||
@@ -66,9 +66,9 @@ public class BuiltinRegistries {
|
||||
ResourceLocation minecraftkey = registryRef.location();
|
||||
|
||||
BuiltinRegistries.LOADERS.put(minecraftkey, defaultValueSupplier);
|
||||
- WritableRegistry<R> iregistrywritable = BuiltinRegistries.WRITABLE_REGISTRY;
|
||||
+ WritableRegistry<R> iregistrywritable = (WritableRegistry<R>) BuiltinRegistries.WRITABLE_REGISTRY; // Paper - decompile fix
|
||||
|
||||
- return (WritableRegistry) iregistrywritable.register(registryRef, (Object) registry, lifecycle);
|
||||
+ return (R) iregistrywritable.register((ResourceKey<R>) registryRef, registry, lifecycle); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public static <T> T register(Registry<? super T> registry, String id, T object) {
|
||||
@@ -76,11 +76,11 @@ public class BuiltinRegistries {
|
||||
}
|
||||
|
||||
public static <V, T extends V> T register(Registry<V> registry, ResourceLocation id, T object) {
|
||||
- return ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable());
|
||||
+ return (T) ((WritableRegistry) registry).register(ResourceKey.create(registry.key(), id), object, Lifecycle.stable()); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public static <V, T extends V> T registerMapping(Registry<V> iregistry, int rawId, ResourceKey<V> resourcekey, T object) {
|
||||
- return ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable());
|
||||
+ return (T) ((WritableRegistry) iregistry).registerMapping(rawId, resourcekey, object, Lifecycle.stable()); // Paper - decompile fix
|
||||
}
|
||||
|
||||
public static void bootstrap() {}
|
@ -1,30 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Fri, 21 Aug 2020 21:05:28 -0400
|
||||
Subject: [PATCH] MC-197883: Bandaid decode issue
|
||||
1.17 Update: Marked as fixed in 1.17 on mojira, yeet
|
||||
Mojang has a mix of type and name in the data sets, but you can only
|
||||
use one.
|
||||
|
||||
This will retry as name if type is asked for and not found.
|
||||
|
||||
resolved https://bugs.mojang.com/browse/MC-197883
|
||||
|
||||
diff --git a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java
|
||||
index de7d1e5e0319c65775d932144c268c2d55bb7dc7..bd6a0e1b5454e880a4f2a16be7dc8da64b73e11d 100644
|
||||
--- a/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java
|
||||
+++ b/src/main/java/com/mojang/serialization/codecs/KeyDispatchCodec.java
|
||||
@@ -48,7 +48,12 @@ public class KeyDispatchCodec<K, V> extends MapCodec<V> {
|
||||
|
||||
@Override
|
||||
public <T> DataResult<V> decode(final DynamicOps<T> ops, final MapLike<T> input) {
|
||||
- final T elementName = input.get(typeKey);
|
||||
+ // Paper start - bandaid MC-197883
|
||||
+ T elementName = input.get(typeKey);
|
||||
+ if (elementName == null && "type".equals(typeKey)) {
|
||||
+ elementName = input.get("name");
|
||||
+ }
|
||||
+ // Paper end
|
||||
if (elementName == null) {
|
||||
return DataResult.error("Input does not contain a key [" + typeKey + "]: " + input);
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Wood <kyle@denwav.dev>
|
||||
Date: Wed, 2 Dec 2020 21:58:45 -0800
|
||||
Subject: [PATCH] Add warning for servers not running on Java 16
|
||||
|
||||
1.17: game requires java 16
|
||||
|
||||
diff --git a/src/main/java/io/papermc/paper/util/PaperJvmChecker.java b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fdf3ff8894e5e202229d1be52fe3c92ea039ef15
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/io/papermc/paper/util/PaperJvmChecker.java
|
||||
@@ -0,0 +1,48 @@
|
||||
+package io.papermc.paper.util;
|
||||
+
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+
|
||||
+import java.util.regex.Matcher;
|
||||
+import java.util.regex.Pattern;
|
||||
+
|
||||
+public class PaperJvmChecker {
|
||||
+
|
||||
+ private static int getJvmVersion() {
|
||||
+ String javaVersion = System.getProperty("java.version");
|
||||
+ final Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion);
|
||||
+ if (!matcher.find()) {
|
||||
+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse: {}", javaVersion);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ final String version = matcher.group(1);
|
||||
+ try {
|
||||
+ return Integer.parseInt(version);
|
||||
+ } catch (final NumberFormatException e) {
|
||||
+ LogManager.getLogger().warn("Failed to determine Java version; Could not parse {} from {}", version, javaVersion, e);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static void checkJvm() {
|
||||
+ if (getJvmVersion() < 16) {
|
||||
+ final Logger logger = LogManager.getLogger();
|
||||
+ logger.warn("************************************************************");
|
||||
+ logger.warn("* WARNING - YOU ARE RUNNING AN OUTDATED VERSION OF JAVA.");
|
||||
+ logger.warn("* PAPER WILL STOP BEING COMPATIBLE WITH THIS VERSION OF");
|
||||
+ logger.warn("* JAVA WHEN MINECRAFT 1.17 IS RELEASED.");
|
||||
+ logger.warn("*");
|
||||
+ logger.warn("* Please update the version of Java you use to run Paper");
|
||||
+ logger.warn("* to at least Java 16. When Paper for Minecraft 1.17 is");
|
||||
+ logger.warn("* released support for versions of Java before 16 will");
|
||||
+ logger.warn("* be dropped.");
|
||||
+ logger.warn("*");
|
||||
+ logger.warn("* Current Java version: {}", System.getProperty("java.version"));
|
||||
+ logger.warn("*");
|
||||
+ logger.warn("* Check this forum post for more information: ");
|
||||
+ logger.warn("* https://papermc.io/java16");
|
||||
+ logger.warn("************************************************************");
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 9bd2255d31bcfd4574f8d1caf598f9141aa9e3c1..c7432ccffc024f171a2868b4eb0dca4860b7f8c4 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1128,6 +1128,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
LOGGER.info("Done ({})! For help, type \"help\"", doneTime);
|
||||
// Paper end
|
||||
|
||||
+ io.papermc.paper.util.PaperJvmChecker.checkJvm(); // Paper jvm version nag
|
||||
org.spigotmc.WatchdogThread.tick(); // Paper
|
||||
org.spigotmc.WatchdogThread.hasStarted = true; // Paper
|
||||
Arrays.fill( recentTps, 20 );
|
@ -1,25 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: chickeneer <emcchickeneer@gmail.com>
|
||||
Date: Wed, 18 Mar 2020 00:07:46 -0500
|
||||
Subject: [PATCH] MC-147729: Drop items that are extra from a crafting recipe
|
||||
|
||||
1.17: Issue seems to be fixed (source: Mojira) https://bugs.mojang.com/browse/MC-147729
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
index a18aa176850bef45afcaf5742e9afbfa39281e22..c6ba6aabf94c26cccbd14689ea32373c17bbccc4 100644
|
||||
--- a/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
+++ b/src/main/java/net/minecraft/recipebook/ServerPlaceRecipe.java
|
||||
@@ -71,7 +71,12 @@ public class ServerPlaceRecipe<C extends Container> implements PlaceRecipe<Integ
|
||||
if (j == -1) {
|
||||
j = this.inventory.getFreeSlot();
|
||||
}
|
||||
-
|
||||
+ // Paper start
|
||||
+ if (j == -1) {
|
||||
+ this.inventory.player.drop(itemstack.copy(), false);
|
||||
+ break;
|
||||
+ }
|
||||
+ // Paper end
|
||||
ItemStack itemstack1 = itemstack.copy();
|
||||
|
||||
itemstack1.setCount(1);
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren