2015-05-25 12:37:24 +02:00
--- a/net/minecraft/server/ChunkRegionLoader.java
+++ b/net/minecraft/server/ChunkRegionLoader.java
2019-01-03 05:44:06 +01:00
@@ -29,7 +29,8 @@
2018-07-15 02:00:00 +02:00
private final File c;
private final DataFixer d;
private PersistentStructureLegacy e;
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
- private boolean f;
2018-07-15 02:00:00 +02:00
+ // private boolean f; // CraftBukkit
2019-01-03 05:44:06 +01:00
+ public final LongSet blacklist = new LongOpenHashSet();
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
2018-07-15 02:00:00 +02:00
public ChunkRegionLoader(File file, DataFixer datafixer) {
this.c = file;
2019-01-03 05:44:06 +01:00
@@ -38,25 +39,69 @@
2018-07-15 02:00:00 +02:00
2018-08-26 04:00:00 +02:00
@Nullable
private NBTTagCompound a(GeneratorAccess generatoraccess, int i, int j) throws IOException {
- return this.a(generatoraccess.o().getDimensionManager(), generatoraccess.h(), i, j);
+ return this.a(generatoraccess.o().getDimensionManager(), generatoraccess.h(), i, j, generatoraccess); // CraftBukkit
2018-07-22 04:00:00 +02:00
+ }
+
2018-07-19 06:19:12 +02:00
+ // CraftBukkit start
+ private boolean check(ChunkProviderServer cps, int x, int z) throws IOException {
2018-07-22 04:00:00 +02:00
+ if (cps != null) {
+ com.google.common.base.Preconditions.checkState(org.bukkit.Bukkit.isPrimaryThread(), "primary thread");
+ if (cps.isLoaded(x, z)) {
+ return true;
+ }
2018-07-19 06:19:12 +02:00
+ }
+
2018-09-26 09:19:16 +02:00
+ if (this.chunkExists(x, z)) {
2018-07-22 04:00:00 +02:00
+ NBTTagCompound nbt = RegionFileCache.read(this.c, x, z);
2018-07-19 06:19:12 +02:00
+ if (nbt != null) {
+ NBTTagCompound level = nbt.getCompound("Level");
+ if (level.getBoolean("TerrainPopulated")) {
+ return true;
+ }
+
+ ChunkStatus status = ChunkStatus.a(level.getString("Status"));
+ if (status != null && status.a(ChunkStatus.DECORATED)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
2018-09-26 09:19:16 +02:00
+ }
+
+ public boolean chunkExists(int x, int z) {
+ return RegionFileCache.chunkExists(this.c, x, z);
2018-07-22 04:00:00 +02:00
}
2018-07-15 02:00:00 +02:00
@Nullable
2018-07-22 04:00:00 +02:00
- private NBTTagCompound a(DimensionManager dimensionmanager, @Nullable PersistentCollection persistentcollection, int i, int j) throws IOException {
+ private NBTTagCompound a(DimensionManager dimensionmanager, @Nullable PersistentCollection persistentcollection, int i, int j, @Nullable GeneratorAccess generatoraccess) throws IOException {
2019-01-03 05:44:06 +01:00
+ // CraftBukkit start
+ if (blacklist.contains(ChunkCoordIntPair.a(i, j))) {
+ return null;
+ }
+ // CraftBukkit end
2018-08-26 04:00:00 +02:00
NBTTagCompound nbttagcompound = (NBTTagCompound) this.b.get(new ChunkCoordIntPair(i, j));
2018-07-15 02:00:00 +02:00
2018-08-26 04:00:00 +02:00
if (nbttagcompound != null) {
return nbttagcompound;
2018-07-15 02:00:00 +02:00
} else {
2018-08-26 04:00:00 +02:00
- DataInputStream datainputstream = RegionFileCache.read(this.c, i, j);
+ NBTTagCompound nbttagcompound1 = RegionFileCache.read(this.c, i, j);
- if (datainputstream == null) {
+ if (nbttagcompound1 == null) {
return null;
} else {
- NBTTagCompound nbttagcompound1 = NBTCompressedStreamTools.a(datainputstream);
2018-07-22 04:00:00 +02:00
-
2018-08-26 04:00:00 +02:00
- datainputstream.close();
int k = nbttagcompound1.hasKeyOfType("DataVersion", 99) ? nbttagcompound1.getInt("DataVersion") : -1;
+ // CraftBukkit start
+ if (k < 1466) {
+ NBTTagCompound level = nbttagcompound1.getCompound("Level");
+ if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) {
2018-12-13 01:00:00 +01:00
+ ChunkProviderServer cps = (generatoraccess == null) ? null : ((WorldServer) generatoraccess).getChunkProvider();
2018-08-26 04:00:00 +02:00
+ if (check(cps, i - 1, j) && check(cps, i - 1, j - 1) && check(cps, i, j - 1)) {
+ level.setBoolean("LightPopulated", true);
+ }
2018-07-19 06:19:12 +02:00
+ }
+ }
2018-08-26 04:00:00 +02:00
+ // CraftBukkit end
if (k < 1493) {
nbttagcompound1 = GameProfileSerializer.a(this.d, DataFixTypes.CHUNK, nbttagcompound1, k, 1493);
2019-01-03 05:44:06 +01:00
@@ -84,13 +129,29 @@
2018-07-15 02:00:00 +02:00
2014-11-25 22:32:16 +01:00
}
2015-02-26 23:41:06 +01:00
2014-11-25 22:32:16 +01:00
+ // CraftBukkit start - Add async variant, provide compatibility
2016-05-10 13:47:39 +02:00
@Nullable
2018-08-26 04:00:00 +02:00
public Chunk a(GeneratorAccess generatoraccess, int i, int j, Consumer<Chunk> consumer) throws IOException {
2018-07-15 02:00:00 +02:00
+ Object[] data = loadChunk(generatoraccess, i, j, consumer);
2014-11-25 22:32:16 +01:00
+ if (data != null) {
+ Chunk chunk = (Chunk) data[0];
+ NBTTagCompound nbttagcompound = (NBTTagCompound) data[1];
2018-07-15 02:00:00 +02:00
+ consumer.accept(chunk);
+ this.loadEntities(nbttagcompound.getCompound("Level"), chunk);
2014-11-25 22:32:16 +01:00
+ return chunk;
+ }
2015-02-26 23:41:06 +01:00
+
2014-11-25 22:32:16 +01:00
+ return null;
+ }
2015-02-26 23:41:06 +01:00
+
2018-08-26 04:00:00 +02:00
+ public Object[] loadChunk(GeneratorAccess generatoraccess, int i, int j, Consumer<Chunk> consumer) throws IOException {
2014-11-25 22:32:16 +01:00
+ // CraftBukkit end
2018-07-15 02:00:00 +02:00
NBTTagCompound nbttagcompound = this.a(generatoraccess, i, j);
2015-05-05 22:43:47 +02:00
2016-06-12 11:28:27 +02:00
if (nbttagcompound == null) {
2018-07-15 02:00:00 +02:00
return null;
} else {
+ /*
Chunk chunk = this.a(generatoraccess, i, j, nbttagcompound);
2016-06-12 11:28:27 +02:00
2018-07-15 02:00:00 +02:00
if (chunk != null) {
2019-01-03 05:44:06 +01:00
@@ -99,6 +160,9 @@
2016-06-12 11:28:27 +02:00
}
2018-07-15 02:00:00 +02:00
return chunk;
+ */
+
+ return this.a(generatoraccess, i, j, nbttagcompound);
2016-06-12 11:28:27 +02:00
}
2018-07-15 02:00:00 +02:00
}
2016-06-12 11:28:27 +02:00
2019-01-03 05:44:06 +01:00
@@ -130,7 +194,7 @@
2014-11-25 22:32:16 +01:00
}
2016-11-17 02:41:03 +01:00
@Nullable
2018-07-15 02:00:00 +02:00
- protected Chunk a(GeneratorAccess generatoraccess, int i, int j, NBTTagCompound nbttagcompound) {
+ protected Object[] a(GeneratorAccess generatoraccess, int i, int j, NBTTagCompound nbttagcompound) { // CraftBukkit - return Chunk -> Object[]
if (nbttagcompound.hasKeyOfType("Level", 10) && nbttagcompound.getCompound("Level").hasKeyOfType("Status", 8)) {
ChunkStatus.Type chunkstatus_type = this.a(nbttagcompound);
2019-01-03 05:44:06 +01:00
@@ -149,10 +213,28 @@
2018-12-06 00:00:00 +01:00
ChunkRegionLoader.a.error("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", i, j, i, j, chunk.locX, chunk.locZ);
2018-07-15 02:00:00 +02:00
nbttagcompound1.setInt("xPos", i);
nbttagcompound1.setInt("zPos", j);
2015-02-26 23:41:06 +01:00
+
2018-07-15 02:00:00 +02:00
+ // CraftBukkit start - Have to move tile entities since we don't load them at this stage
+ NBTTagList tileEntities = nbttagcompound.getCompound("Level").getList("TileEntities", 10);
+ if (tileEntities != null) {
+ for (int te = 0; te < tileEntities.size(); te++) {
+ NBTTagCompound tileEntity = (NBTTagCompound) tileEntities.get(te);
+ int x = tileEntity.getInt("x") - chunk.locX * 16;
+ int z = tileEntity.getInt("z") - chunk.locZ * 16;
+ tileEntity.setInt("x", i * 16 + x);
+ tileEntity.setInt("z", j * 16 + z);
+ }
2015-02-26 23:41:06 +01:00
+ }
2018-07-15 02:00:00 +02:00
+ // CraftBukkit end
chunk = this.a(generatoraccess, nbttagcompound1);
}
- return chunk;
+ // CraftBukkit start
+ Object[] data = new Object[2];
+ data[0] = chunk;
+ data[1] = nbttagcompound;
+ return data;
2015-02-26 23:41:06 +01:00
+ // CraftBukkit end
}
2014-11-25 22:32:16 +01:00
}
2018-07-15 02:00:00 +02:00
} else {
2019-01-03 05:44:06 +01:00
@@ -167,7 +249,7 @@
2018-07-15 02:00:00 +02:00
ChunkStatus.Type chunkstatus_type = this.a(nbttagcompound);
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
2018-07-15 02:00:00 +02:00
if (chunkstatus_type == ChunkStatus.Type.LEVELCHUNK) {
- return new ProtoChunkExtension(this.a(generatoraccess, i, j, nbttagcompound));
+ return new ProtoChunkExtension((IChunkAccess) this.a(generatoraccess, i, j, nbttagcompound)[0]); // CraftBukkit - fix up access
} else {
NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Level");
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
2019-01-03 05:44:06 +01:00
@@ -215,10 +297,15 @@
2016-08-27 07:51:54 +02:00
}
2018-08-26 04:00:00 +02:00
public boolean a() {
2016-08-27 07:51:54 +02:00
+ // CraftBukkit start
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
+ return this.processSaveQueueEntry(false);
+ }
2018-12-25 22:00:00 +01:00
+
2018-08-26 04:00:00 +02:00
+ private boolean processSaveQueueEntry(boolean logCompletion) {
2018-12-25 22:00:00 +01:00
Iterator<Entry<ChunkCoordIntPair, NBTTagCompound>> iterator = this.b.entrySet().iterator();
2018-08-26 04:00:00 +02:00
if (!iterator.hasNext()) {
- if (this.f) {
+ if (logCompletion) { // CraftBukkit
ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.c.getName());
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
}
2019-01-03 05:44:06 +01:00
@@ -234,10 +321,14 @@
2018-08-26 04:00:00 +02:00
return true;
} else {
try {
- DataOutputStream dataoutputstream = RegionFileCache.write(this.c, chunkcoordintpair.x, chunkcoordintpair.z);
+ // CraftBukkit start
+ RegionFileCache.write(this.c, chunkcoordintpair.x, chunkcoordintpair.z, nbttagcompound);
2016-06-12 11:28:27 +02:00
2018-08-26 04:00:00 +02:00
+ /*
NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) dataoutputstream);
dataoutputstream.close();
+ */
+ // CraftBukkit end
if (this.e != null) {
this.e.a(chunkcoordintpair.a());
}
2019-01-03 05:44:06 +01:00
@@ -264,15 +355,16 @@
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
2018-08-26 04:00:00 +02:00
public void b() {
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
try {
- this.f = true;
+ // this.f = true; // CraftBukkit
while (true) {
- if (this.a()) {
+ if (this.processSaveQueueEntry(true)) { // CraftBukkit
2016-06-18 13:25:50 +02:00
continue;
}
+ break; // CraftBukkit - Fix infinite loop when saving chunks
}
} finally {
Fix a few chunk saving race conditions
* ChunkRegionLoader.c() picks an entry in the save queue, removes that entry from the save queue and then actually writes the entry to the region file. So, between the last two steps, the entry is neither in the save queue nor is it in the region file; if somebody loads the chunk again (with ChunkRegionLoader.loadChunk()) in that gap, they'll get old data. I've delayed the removal until the saving is done.
* ChunkRegionLoader.c() also records the coords of the chunks it's currently saving in this.c. ChunkRegionLoader.a(ChunkCoordIntPair, NBTTagCompound), which adds an entry to the save queue, stops the addition of an entry if its coords are in this.c. Now, I'm guessing that Mojang's intended purpose for this mechanism was to prevent multiple parallel writes for the same chunk. The "stops the addition" bit above should then be something like "block until it's no longer in c"; in fact, the vanilla implementation is "discard the new state of the chunk". I've taken the easy route to solving this, by just making ChunkRegionLoader.c() synchronized (since, in normal use, only the chunk saving thread is in here).
2017-08-11 09:27:33 +02:00
- this.f = false;
+ // this.f = false; // CraftBukkit
}
}
2019-01-03 05:44:06 +01:00
@@ -301,7 +393,7 @@
2018-07-15 02:00:00 +02:00
if (abiomebase != null) {
for (int k = 0; k < abiomebase.length; ++k) {
2018-08-26 04:00:00 +02:00
- aint[k] = IRegistry.BIOME.a((Object) abiomebase[k]);
+ aint[k] = IRegistry.BIOME.a(abiomebase[k]); // CraftBukkit - decompile error
2018-07-15 02:00:00 +02:00
}
2014-11-25 22:32:16 +01:00
}
2015-02-26 23:41:06 +01:00
2019-01-03 05:44:06 +01:00
@@ -383,7 +475,7 @@
2018-07-15 02:00:00 +02:00
int[] aint = new int[abiomebase.length];
2014-11-25 22:32:16 +01:00
2018-07-15 02:00:00 +02:00
for (int i = 0; i < abiomebase.length; ++i) {
2018-08-26 04:00:00 +02:00
- aint[i] = IRegistry.BIOME.a((Object) abiomebase[i]);
+ aint[i] = IRegistry.BIOME.a(abiomebase[i]); // CraftBukkit - decompile error
2014-11-25 22:32:16 +01:00
}
2018-07-15 02:00:00 +02:00
nbttagcompound.setIntArray("Biomes", aint);
2019-01-03 05:44:06 +01:00
@@ -833,17 +925,29 @@
2016-06-09 03:43:49 +02:00
}
@Nullable
+ // CraftBukkit start
public static Entity a(NBTTagCompound nbttagcompound, World world, double d0, double d1, double d2, boolean flag) {
+ return spawnEntity(nbttagcompound, world, d0, d1, d2, flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ public static Entity spawnEntity(NBTTagCompound nbttagcompound, World world, double d0, double d1, double d2, boolean flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ // CraftBukkit end
2018-07-15 02:00:00 +02:00
return a(nbttagcompound, world, (entity) -> {
2016-06-09 03:43:49 +02:00
entity.setPositionRotation(d0, d1, d2, entity.yaw, entity.pitch);
2018-07-15 02:00:00 +02:00
- return flag && !world.addEntity(entity) ? null : entity;
+ return flag && !world.addEntity(entity, spawnReason) ? null : entity;
});
}
@Nullable
+ // CraftBukkit start
public static Entity a(NBTTagCompound nbttagcompound, World world, boolean flag) {
+ return spawnEntity(nbttagcompound, world, flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
+ }
+
+ public static Entity spawnEntity(NBTTagCompound nbttagcompound, World world, boolean flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ // CraftBukkit end
return a(nbttagcompound, world, (entity) -> {
- return flag && !world.addEntity(entity) ? null : entity;
+ return flag && !world.addEntity(entity, spawnReason) ? null : entity; // CraftBukkit
});
}
2019-01-03 05:44:06 +01:00
@@ -857,8 +961,14 @@
2016-02-29 22:32:46 +01:00
}
}
+ // CraftBukkit start
2018-07-15 02:00:00 +02:00
public static void a(Entity entity, GeneratorAccess generatoraccess) {
- if (generatoraccess.addEntity(entity) && entity.isVehicle()) {
+ a(entity, generatoraccess, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
2016-02-29 22:32:46 +01:00
+ }
+
2018-07-15 02:00:00 +02:00
+ public static void a(Entity entity, GeneratorAccess generatoraccess, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ if (generatoraccess.addEntity(entity, reason) && entity.isVehicle()) {
2016-02-29 22:32:46 +01:00
+ // CraftBukkit end
2018-07-15 02:00:00 +02:00
Iterator iterator = entity.bP().iterator();
2016-02-29 22:32:46 +01:00
while (iterator.hasNext()) {
2019-01-03 05:44:06 +01:00
@@ -874,7 +984,7 @@
2018-07-22 04:00:00 +02:00
boolean flag = false;
try {
- this.a(dimensionmanager, persistentcollection, chunkcoordintpair.x, chunkcoordintpair.z);
+ this.a(dimensionmanager, persistentcollection, chunkcoordintpair.x, chunkcoordintpair.z, null); // CraftBukkit
2018-08-26 04:00:00 +02:00
while (this.a()) {
flag = true;