Move patches around
This commit is contained in:
parent
73bcb74f23
commit
4d225813a1
1895 changed files with 212111 additions and 0 deletions
|
@ -0,0 +1,61 @@
|
|||
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
|
||||
|
312
patches/removed/0033-Generator-Settings.patch
Normal file
312
patches/removed/0033-Generator-Settings.patch
Normal file
|
@ -0,0 +1,312 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
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
|
||||
|
113
patches/removed/0036-Fast-draining.patch
Normal file
113
patches/removed/0036-Fast-draining.patch
Normal file
|
@ -0,0 +1,113 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
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
|
||||
|
83
patches/removed/0280-Configurable-Unrestricted-Signs.patch
Normal file
83
patches/removed/0280-Configurable-Unrestricted-Signs.patch
Normal file
|
@ -0,0 +1,83 @@
|
|||
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
|
||||
|
218
patches/removed/0532-Unload-leaked-Cached-Chunks.patch
Normal file
218
patches/removed/0532-Unload-leaked-Cached-Chunks.patch
Normal file
|
@ -0,0 +1,218 @@
|
|||
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);
|
280
patches/removed/1.14/0032-Add-player-view-distance-API.patch
Normal file
280
patches/removed/1.14/0032-Add-player-view-distance-API.patch
Normal file
|
@ -0,0 +1,280 @@
|
|||
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
|
||||
|
206
patches/removed/1.14/0061-Chunk-save-queue-improvements.patch
Normal file
206
patches/removed/1.14/0061-Chunk-save-queue-improvements.patch
Normal file
|
@ -0,0 +1,206 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
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
|
||||
|
125
patches/removed/1.14/0078-Optimize-Chunk-Access.patch
Normal file
125
patches/removed/1.14/0078-Optimize-Chunk-Access.patch
Normal file
|
@ -0,0 +1,125 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
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
|
||||
|
103
patches/removed/1.14/0112-Entity-Tracking-Improvements.patch
Normal file
103
patches/removed/1.14/0112-Entity-Tracking-Improvements.patch
Normal file
|
@ -0,0 +1,103 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
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
|
||||
|
224
patches/removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch
Executable file
224
patches/removed/1.14/0123-Delay-Chunk-Unloads-based-on-Player-Movement.patch
Executable file
|
@ -0,0 +1,224 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
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
|
||||
|
22
patches/removed/1.14/0144-Fix-block-break-desync.patch
Normal file
22
patches/removed/1.14/0144-Fix-block-break-desync.patch
Normal file
|
@ -0,0 +1,22 @@
|
|||
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
|
||||
|
23
patches/removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch
Executable file
23
patches/removed/1.14/0161-ShulkerBox-Dupe-Prevention.patch
Executable file
|
@ -0,0 +1,23 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
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
|
||||
|
2503
patches/removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch
Normal file
2503
patches/removed/1.14/0361-Async-Chunk-Loading-and-Generation.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,52 @@
|
|||
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
|
||||
|
66
patches/removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch
Normal file
66
patches/removed/1.14/0366-Fix-Sending-Chunks-to-Client.patch
Normal file
|
@ -0,0 +1,66 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,872 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
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
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
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
|
||||
|
159
patches/removed/1.16/0238-Configurable-Bed-Search-Radius.patch
Normal file
159
patches/removed/1.16/0238-Configurable-Bed-Search-Radius.patch
Normal file
|
@ -0,0 +1,159 @@
|
|||
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);
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
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());
|
|
@ -0,0 +1,101 @@
|
|||
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
|
|
@ -0,0 +1,178 @@
|
|||
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
|
||||
}
|
||||
|
273
patches/removed/1.16/0530-Optimize-Villagers.patch
Normal file
273
patches/removed/1.16/0530-Optimize-Villagers.patch
Normal file
|
@ -0,0 +1,273 @@
|
|||
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)));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
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;
|
|
@ -0,0 +1,22 @@
|
|||
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;
|
|
@ -0,0 +1,19 @@
|
|||
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
|
|
@ -0,0 +1,223 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
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();
|
|
@ -0,0 +1,21 @@
|
|||
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()));
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
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) {
|
|
@ -0,0 +1,31 @@
|
|||
diff --git a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java
|
||||
index fff22c40ba38575951e8e4821ade22b29d580a89..c397c52e8e24b85d892e4906178720cc70edc143 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/game/PacketPlayOutTitle.java
|
||||
@@ -47,6 +47,17 @@ public class PacketPlayOutTitle implements Packet<PacketListenerPlayOut> {
|
||||
}
|
||||
|
||||
}
|
||||
+ // Paper start
|
||||
+ public net.md_5.bungee.api.chat.BaseComponent[] components;
|
||||
+
|
||||
+ public PacketPlayOutTitle(EnumTitleAction action, net.md_5.bungee.api.chat.BaseComponent[] components, int fadeIn, int stay, int fadeOut) {
|
||||
+ this.a = action;
|
||||
+ this.components = components;
|
||||
+ this.c = fadeIn;
|
||||
+ this.d = stay;
|
||||
+ this.e = fadeOut;
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
@Override
|
||||
public void b(PacketDataSerializer packetdataserializer) throws IOException {
|
||||
@@ -55,6 +66,8 @@ public class PacketPlayOutTitle implements Packet<PacketListenerPlayOut> {
|
||||
// Paper start
|
||||
if (this.adventure$text != null) {
|
||||
packetdataserializer.writeComponent(this.adventure$text);
|
||||
+ } else if (this.components != null) {
|
||||
+ packetdataserializer.writeComponent(this.components);
|
||||
} else
|
||||
// Paper end
|
||||
packetdataserializer.a(this.b);
|
75
patches/removed/Scheduler-decompile-fixes.patch
Normal file
75
patches/removed/Scheduler-decompile-fixes.patch
Normal file
|
@ -0,0 +1,75 @@
|
|||
From 5b7fa8b79798a56e956c7b5011c3298bc0de2a3c Mon Sep 17 00:00:00 2001
|
||||
From: Aikar <aikar@aikar.co>
|
||||
Date: Sat, 1 Sep 2018 12:19:19 -0400
|
||||
Subject: [PATCH 1/2] scheduler decompile fox
|
||||
|
||||
---
|
||||
.../java/net/minecraft/server/Scheduler.java | 20 +++++++++----------
|
||||
1 file changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/Scheduler.java b/src/main/java/net/minecraft/server/Scheduler.java
|
||||
index ed155c8b30..1c327c58e7 100644
|
||||
--- a/src/main/java/net/minecraft/server/Scheduler.java
|
||||
+++ b/src/main/java/net/minecraft/server/Scheduler.java
|
||||
@@ -27,8 +27,8 @@ public abstract class Scheduler<K, T extends SchedulerTask<K, T>, R> {
|
||||
private final ExecutorService c;
|
||||
private final AtomicInteger d = new AtomicInteger(1);
|
||||
private final List<CompletableFuture<R>> e = Lists.newArrayList();
|
||||
- private CompletableFuture<R> f = CompletableFuture.completedFuture((Object)null);
|
||||
- private CompletableFuture<R> g = CompletableFuture.completedFuture((Object)null);
|
||||
+ private CompletableFuture<R> f = CompletableFuture.completedFuture(null); // Paper - decompile fix
|
||||
+ private CompletableFuture<R> g = CompletableFuture.completedFuture(null); // Paper - decompile fix
|
||||
private final Supplier<Map<T, CompletableFuture<R>>> h;
|
||||
private final Supplier<Map<T, CompletableFuture<Void>>> i;
|
||||
private final T j;
|
||||
@@ -121,12 +121,12 @@ public abstract class Scheduler<K, T extends SchedulerTask<K, T>, R> {
|
||||
private final K c;
|
||||
private final R d;
|
||||
|
||||
- public a(Object object, Object object1, SchedulerTask schedulertask) {
|
||||
+ public a(Object object, Object object1, T schedulertask) { // Paper - decompile fix
|
||||
this.b = (Map)Scheduler.this.h.get();
|
||||
this.c = (K)object;
|
||||
|
||||
for(this.d = (R)object1; schedulertask != null; schedulertask = schedulertask.a()) {
|
||||
- this.b.put(schedulertask, CompletableFuture.completedFuture(object1));
|
||||
+ this.b.put(schedulertask, CompletableFuture.completedFuture((R)object1));// Paper - decompile fix
|
||||
}
|
||||
|
||||
}
|
||||
@@ -136,18 +136,18 @@ public abstract class Scheduler<K, T extends SchedulerTask<K, T>, R> {
|
||||
}
|
||||
|
||||
private CompletableFuture<R> a(CompletableFuture<R> completablefuture, T schedulertask) {
|
||||
- ConcurrentHashMap concurrenthashmap = new ConcurrentHashMap();
|
||||
- return (CompletableFuture)this.b.computeIfAbsent(schedulertask, (var4) -> {
|
||||
+ ConcurrentHashMap<K, CompletableFuture<R>> concurrenthashmap = new ConcurrentHashMap(); // Paper - decompile fix
|
||||
+ return (CompletableFuture<R>)this.b.computeIfAbsent(schedulertask, (var4) -> { // Paper - decompile fix
|
||||
if (schedulertask.a() == null) {
|
||||
return CompletableFuture.completedFuture(this.d);
|
||||
} else {
|
||||
schedulertask.a(this.c, (object, schedulertask2) -> {
|
||||
- CompletableFuture completablefuture4 = (CompletableFuture)concurrenthashmap.put(object, Scheduler.this.a(object, Scheduler.this.b(object)).a(completablefuture, schedulertask2));
|
||||
+ CompletableFuture<R> completablefuture4 = (CompletableFuture)concurrenthashmap.put(object, Scheduler.this.a(object, Scheduler.this.b(object)).a(completablefuture, schedulertask2)); // Paper - decompile fix
|
||||
});
|
||||
- CompletableFuture[] acompletablefuture = (CompletableFuture[])Streams.concat(new Stream[]{Stream.of(completablefuture), concurrenthashmap.values().stream()}).toArray((i) -> {
|
||||
+ CompletableFuture<R>[] acompletablefuture = (CompletableFuture[])Streams.concat(new Stream[]{Stream.of(completablefuture), concurrenthashmap.values().stream()}).toArray((i) -> { // Paper - decompile fix
|
||||
return new CompletableFuture[i];
|
||||
});
|
||||
- CompletableFuture completablefuture2 = CompletableFuture.allOf(acompletablefuture).thenApplyAsync((var3) -> {
|
||||
+ CompletableFuture<R> completablefuture2 = CompletableFuture.allOf(acompletablefuture).thenApplyAsync((var3) -> { // Paper - decompile fix
|
||||
return Scheduler.this.a(this.c, schedulertask, Maps.transformValues(concurrenthashmap, (completablefuture3) -> {
|
||||
try {
|
||||
return completablefuture3.get();
|
||||
@@ -156,7 +156,7 @@ public abstract class Scheduler<K, T extends SchedulerTask<K, T>, R> {
|
||||
}
|
||||
}));
|
||||
}, Scheduler.this.c).thenApplyAsync((object) -> {
|
||||
- for(Object object1 : concurrenthashmap.keySet()) {
|
||||
+ for(K object1 : concurrenthashmap.keySet()) { // Paper - decompile fix
|
||||
Scheduler.this.b(object1, Scheduler.this.b(object1));
|
||||
}
|
||||
|
||||
--
|
||||
2.18.0
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue