SPIGOT-4752: Fixed inconsistency between isChunkLoaded and chunk load/unload events
Dieser Commit ist enthalten in:
Ursprung
3f9f31c3ce
Commit
8d0f37228d
@ -1,32 +1,18 @@
|
||||
--- a/net/minecraft/server/Chunk.java
|
||||
+++ b/net/minecraft/server/Chunk.java
|
||||
@@ -22,6 +22,13 @@
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
+// CraftBukkit start
|
||||
+import com.google.common.collect.Lists;
|
||||
+import java.util.LinkedList;
|
||||
+import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
+// CraftBukkit end
|
||||
+
|
||||
public class Chunk implements IChunkAccess {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -95,8 +102,19 @@
|
||||
@@ -95,8 +95,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
+ public org.bukkit.Chunk bukkitChunk;
|
||||
+ public org.bukkit.Chunk getBukkitChunk() {
|
||||
+ return bukkitChunk;
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ public boolean mustNotSave;
|
||||
+ public boolean needsDecoration;
|
||||
+ // CraftBukkit end
|
||||
@ -34,7 +20,7 @@
|
||||
public Chunk(World world, ProtoChunk protochunk) {
|
||||
this(world, protochunk.getPos(), protochunk.getBiomeIndex(), protochunk.p(), protochunk.n(), protochunk.o(), protochunk.q(), protochunk.getSections(), (Consumer) null);
|
||||
Iterator iterator = protochunk.y().iterator();
|
||||
@@ -138,6 +156,7 @@
|
||||
@@ -138,6 +149,7 @@
|
||||
|
||||
this.b(protochunk.r());
|
||||
this.s = true;
|
||||
@ -42,7 +28,7 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -228,9 +247,16 @@
|
||||
@@ -228,9 +240,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +45,7 @@
|
||||
int i = blockposition.getX() & 15;
|
||||
int j = blockposition.getY();
|
||||
int k = blockposition.getZ() & 15;
|
||||
@@ -282,7 +308,8 @@
|
||||
@@ -282,7 +301,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +55,7 @@
|
||||
iblockdata.onPlace(this.world, blockposition, iblockdata1, flag);
|
||||
}
|
||||
|
||||
@@ -382,7 +409,12 @@
|
||||
@@ -382,7 +402,12 @@
|
||||
|
||||
@Nullable
|
||||
public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) {
|
||||
@ -83,7 +69,7 @@
|
||||
|
||||
if (tileentity == null) {
|
||||
NBTTagCompound nbttagcompound = (NBTTagCompound) this.e.remove(blockposition);
|
||||
@@ -429,6 +461,13 @@
|
||||
@@ -429,6 +454,13 @@
|
||||
tileentity1.m();
|
||||
}
|
||||
|
||||
@ -97,7 +83,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,6 +496,41 @@
|
||||
@@ -457,6 +489,50 @@
|
||||
|
||||
}
|
||||
|
||||
@ -113,6 +99,7 @@
|
||||
+ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(this.bukkitChunk, this.needsDecoration));
|
||||
+
|
||||
+ if (this.needsDecoration) {
|
||||
+ this.needsDecoration = false;
|
||||
+ java.util.Random random = new java.util.Random();
|
||||
+ random.setSeed(world.getSeed());
|
||||
+ long xRand = random.nextLong() / 2L * 2L + 1L;
|
||||
@ -134,12 +121,20 @@
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void unloadCallback() {
|
||||
+ org.bukkit.Server server = this.world.getServer();
|
||||
+ org.bukkit.event.world.ChunkUnloadEvent unloadEvent = new org.bukkit.event.world.ChunkUnloadEvent(this.bukkitChunk, this.isNeedsSaving());
|
||||
+ server.getPluginManager().callEvent(unloadEvent);
|
||||
+ // note: saving can be prevented, but not forced if no saving is actually required
|
||||
+ this.mustNotSave = !unloadEvent.isSaveChunk();
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public void markDirty() {
|
||||
this.s = true;
|
||||
}
|
||||
@@ -531,7 +605,7 @@
|
||||
@@ -531,7 +607,7 @@
|
||||
Iterator iterator = this.entitySlices[k].a(oclass).iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@ -148,7 +143,7 @@
|
||||
|
||||
if (t0.getBoundingBox().c(axisalignedbb) && (predicate == null || predicate.test(t0))) {
|
||||
list.add(t0);
|
||||
@@ -605,7 +679,7 @@
|
||||
@@ -605,7 +681,7 @@
|
||||
|
||||
@Override
|
||||
public boolean isNeedsSaving() {
|
||||
@ -157,7 +152,7 @@
|
||||
}
|
||||
|
||||
public void d(boolean flag) {
|
||||
@@ -746,7 +820,7 @@
|
||||
@@ -746,7 +822,7 @@
|
||||
|
||||
public void B() {
|
||||
if (this.o instanceof ProtoChunkTickList) {
|
||||
@ -166,7 +161,7 @@
|
||||
return this.getType(blockposition).getBlock();
|
||||
});
|
||||
this.o = TickListEmpty.a();
|
||||
@@ -756,7 +830,7 @@
|
||||
@@ -756,7 +832,7 @@
|
||||
}
|
||||
|
||||
if (this.p instanceof ProtoChunkTickList) {
|
||||
@ -175,7 +170,7 @@
|
||||
return this.getFluid(blockposition).getType();
|
||||
});
|
||||
this.p = TickListEmpty.a();
|
||||
@@ -768,12 +842,12 @@
|
||||
@@ -768,12 +844,12 @@
|
||||
}
|
||||
|
||||
public void a(WorldServer worldserver) {
|
||||
|
@ -1,6 +1,49 @@
|
||||
--- a/net/minecraft/server/ChunkProviderServer.java
|
||||
+++ b/net/minecraft/server/ChunkProviderServer.java
|
||||
@@ -241,6 +241,17 @@
|
||||
@@ -81,7 +81,7 @@
|
||||
for (int l = 0; l < 4; ++l) {
|
||||
if (k == this.n[l] && chunkstatus == this.o[l]) {
|
||||
ichunkaccess = this.p[l];
|
||||
- if (ichunkaccess != null || !flag) {
|
||||
+ if (ichunkaccess != null) { // CraftBukkit - the chunk can become accessible in the meantime TODO for non-null chunks it might also make sense to check that the chunk's state hasn't changed in the meantime
|
||||
return ichunkaccess;
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,15 @@
|
||||
int l = 33 + ChunkStatus.a(chunkstatus);
|
||||
PlayerChunk playerchunk = this.getChunk(k);
|
||||
|
||||
- if (flag) {
|
||||
+ // CraftBukkit start - don't add new ticket for currently unloading chunk
|
||||
+ boolean currentlyUnloading = false;
|
||||
+ if (playerchunk != null) {
|
||||
+ PlayerChunk.State oldChunkState = PlayerChunk.c(playerchunk.oldTicketLevel); // PAIL getChunkState
|
||||
+ PlayerChunk.State currentChunkState = PlayerChunk.c(playerchunk.getTicketLevel()); // PAIL getChunkState
|
||||
+ currentlyUnloading = (oldChunkState.a(PlayerChunk.State.BORDER) && !currentChunkState.a(PlayerChunk.State.BORDER)); // PAIL isAtLeast
|
||||
+ }
|
||||
+ if (flag && !currentlyUnloading) {
|
||||
+ // CraftBukkit end
|
||||
this.chunkMapDistance.a(TicketType.UNKNOWN, chunkcoordintpair, l, chunkcoordintpair);
|
||||
if (this.a(playerchunk, l)) {
|
||||
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
|
||||
@@ -144,14 +152,14 @@
|
||||
}
|
||||
|
||||
private boolean a(@Nullable PlayerChunk playerchunk, int i) {
|
||||
- return playerchunk == null || playerchunk.getTicketLevel() > i;
|
||||
+ return playerchunk == null || playerchunk.oldTicketLevel > i; // CraftBukkit using oldTicketLevel for isLoaded checks
|
||||
}
|
||||
|
||||
public boolean isLoaded(int i, int j) {
|
||||
PlayerChunk playerchunk = this.getChunk((new ChunkCoordIntPair(i, j)).pair());
|
||||
int k = 33 + ChunkStatus.a(ChunkStatus.FULL);
|
||||
|
||||
- return playerchunk != null && playerchunk.getTicketLevel() <= k ? ((Either) playerchunk.getStatusFuture(ChunkStatus.FULL).getNow(PlayerChunk.UNLOADED_CHUNK_ACCESS)).left().isPresent() : false;
|
||||
+ return playerchunk != null && playerchunk.oldTicketLevel <= k ? ((Either) playerchunk.getStatusFuture(ChunkStatus.FULL).getNow(PlayerChunk.UNLOADED_CHUNK_ACCESS)).left().isPresent() : false; // CraftBukkit using oldTicketLevel for isLoaded checks
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,6 +249,18 @@
|
||||
this.playerChunkMap.close();
|
||||
}
|
||||
|
||||
@ -12,13 +55,14 @@
|
||||
+ this.world.getMethodProfiler().exitEnter("unload");
|
||||
+ this.playerChunkMap.unloadChunks(() -> true);
|
||||
+ this.world.getMethodProfiler().exit();
|
||||
+ this.l(); // PAIL clearCache
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public void tick(BooleanSupplier booleansupplier) {
|
||||
this.world.getMethodProfiler().enter("purge");
|
||||
this.chunkMapDistance.purgeTickets();
|
||||
@@ -260,13 +271,13 @@
|
||||
@@ -260,13 +280,13 @@
|
||||
this.lastTickTime = i;
|
||||
WorldData worlddata = this.world.getWorldData();
|
||||
boolean flag = worlddata.getType() == WorldType.DEBUG_ALL_BLOCK_STATES;
|
||||
@ -34,7 +78,7 @@
|
||||
|
||||
this.world.getMethodProfiler().enter("naturalSpawnCount");
|
||||
int l = this.chunkMapDistance.b();
|
||||
@@ -299,8 +310,30 @@
|
||||
@@ -299,8 +319,30 @@
|
||||
for (int j1 = 0; j1 < i1; ++j1) {
|
||||
EnumCreatureType enumcreaturetype = aenumcreaturetype1[j1];
|
||||
|
||||
|
@ -58,7 +58,7 @@
|
||||
protected static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final AtomicInteger entityCount = new AtomicInteger();
|
||||
private static final List<ItemStack> c = Collections.emptyList();
|
||||
@@ -106,6 +155,16 @@
|
||||
@@ -106,6 +155,20 @@
|
||||
private long aH;
|
||||
private EntitySize size;
|
||||
private float headHeight;
|
||||
@ -71,11 +71,15 @@
|
||||
+ public float getBukkitYaw() {
|
||||
+ return this.yaw;
|
||||
+ }
|
||||
+
|
||||
+ public boolean isChunkLoaded() {
|
||||
+ return world.isChunkLoaded((int) Math.floor(this.locX) >> 4, (int) Math.floor(this.locZ) >> 4);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
public Entity(EntityTypes<?> entitytypes, World world) {
|
||||
this.id = Entity.entityCount.incrementAndGet();
|
||||
@@ -204,6 +263,12 @@
|
||||
@@ -204,6 +267,12 @@
|
||||
}
|
||||
|
||||
protected void setPose(EntityPose entitypose) {
|
||||
@ -88,7 +92,7 @@
|
||||
this.datawatcher.set(Entity.POSE, entitypose);
|
||||
}
|
||||
|
||||
@@ -212,6 +277,33 @@
|
||||
@@ -212,6 +281,33 @@
|
||||
}
|
||||
|
||||
protected void setYawPitch(float f, float f1) {
|
||||
@ -122,7 +126,7 @@
|
||||
this.yaw = f % 360.0F;
|
||||
this.pitch = f1 % 360.0F;
|
||||
}
|
||||
@@ -224,6 +316,7 @@
|
||||
@@ -224,6 +320,7 @@
|
||||
float f1 = this.size.height;
|
||||
|
||||
this.a(new AxisAlignedBB(d0 - (double) f, d1, d2 - (double) f, d0 + (double) f, d1 + (double) f1, d2 + (double) f));
|
||||
@ -130,7 +134,7 @@
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
@@ -234,6 +327,15 @@
|
||||
@@ -234,6 +331,15 @@
|
||||
this.entityBaseTick();
|
||||
}
|
||||
|
||||
@ -146,7 +150,7 @@
|
||||
public void entityBaseTick() {
|
||||
this.world.getMethodProfiler().enter("entityBaseTick");
|
||||
if (this.isPassenger() && this.getVehicle().dead) {
|
||||
@@ -250,7 +352,7 @@
|
||||
@@ -250,7 +356,7 @@
|
||||
this.lastZ = this.locZ;
|
||||
this.lastPitch = this.pitch;
|
||||
this.lastYaw = this.yaw;
|
||||
@ -155,7 +159,7 @@
|
||||
this.az();
|
||||
this.m();
|
||||
if (this.world.isClientSide) {
|
||||
@@ -300,12 +402,44 @@
|
||||
@@ -300,12 +406,44 @@
|
||||
|
||||
protected void burnFromLava() {
|
||||
if (!this.isFireProof()) {
|
||||
@ -201,7 +205,7 @@
|
||||
int j = i * 20;
|
||||
|
||||
if (this instanceof EntityLiving) {
|
||||
@@ -401,6 +535,28 @@
|
||||
@@ -401,6 +539,28 @@
|
||||
block1.a((IBlockAccess) this.world, this);
|
||||
}
|
||||
|
||||
@ -230,7 +234,7 @@
|
||||
if (this.playStepSound() && (!this.onGround || !this.isSneaking() || !(this instanceof EntityHuman)) && !this.isPassenger()) {
|
||||
double d0 = vec3d1.x;
|
||||
double d1 = vec3d1.y;
|
||||
@@ -454,7 +610,14 @@
|
||||
@@ -454,7 +614,14 @@
|
||||
if (!flag) {
|
||||
++this.fireTicks;
|
||||
if (this.fireTicks == 0) {
|
||||
@ -246,7 +250,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,7 +728,7 @@
|
||||
@@ -565,7 +732,7 @@
|
||||
VoxelShape voxelshape = this.world.getWorldBorder().a();
|
||||
Stream<VoxelShape> stream = VoxelShapes.c(voxelshape, VoxelShapes.a(axisalignedbb.shrink(1.0E-7D)), OperatorBoolean.AND) ? Stream.empty() : Stream.of(voxelshape);
|
||||
AxisAlignedBB axisalignedbb1 = axisalignedbb.a(vec3d).g(1.0E-7D);
|
||||
@ -255,7 +259,7 @@
|
||||
return !this.x(entity);
|
||||
}).flatMap((entity) -> {
|
||||
return Stream.of(entity.ap(), this.j(entity));
|
||||
@@ -649,6 +812,7 @@
|
||||
@@ -649,6 +816,7 @@
|
||||
this.locX = (axisalignedbb.minX + axisalignedbb.maxX) / 2.0D;
|
||||
this.locY = axisalignedbb.minY;
|
||||
this.locZ = (axisalignedbb.minZ + axisalignedbb.maxZ) / 2.0D;
|
||||
@ -263,7 +267,7 @@
|
||||
}
|
||||
|
||||
protected SoundEffect getSoundSwim() {
|
||||
@@ -820,7 +984,7 @@
|
||||
@@ -820,7 +988,7 @@
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -272,7 +276,7 @@
|
||||
if (!this.isFireProof()) {
|
||||
this.damageEntity(DamageSource.FIRE, (float) i);
|
||||
}
|
||||
@@ -1053,6 +1217,13 @@
|
||||
@@ -1053,6 +1221,13 @@
|
||||
}
|
||||
|
||||
public void spawnIn(World world) {
|
||||
@ -286,7 +290,7 @@
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@@ -1078,6 +1249,7 @@
|
||||
@@ -1078,6 +1253,7 @@
|
||||
this.lastYaw -= 360.0F;
|
||||
}
|
||||
|
||||
@ -294,7 +298,7 @@
|
||||
this.setPosition(this.locX, this.locY, this.locZ);
|
||||
this.setYawPitch(f, f1);
|
||||
}
|
||||
@@ -1246,7 +1418,7 @@
|
||||
@@ -1246,7 +1422,7 @@
|
||||
public boolean c(NBTTagCompound nbttagcompound) {
|
||||
String s = this.getSaveID();
|
||||
|
||||
@ -303,7 +307,7 @@
|
||||
nbttagcompound.setString("id", s);
|
||||
this.save(nbttagcompound);
|
||||
return true;
|
||||
@@ -1265,15 +1437,33 @@
|
||||
@@ -1265,15 +1441,33 @@
|
||||
Vec3D vec3d = this.getMot();
|
||||
|
||||
nbttagcompound.set("Motion", this.a(vec3d.x, vec3d.y, vec3d.z));
|
||||
@ -338,7 +342,7 @@
|
||||
IChatBaseComponent ichatbasecomponent = this.getCustomName();
|
||||
|
||||
if (ichatbasecomponent != null) {
|
||||
@@ -1331,6 +1521,11 @@
|
||||
@@ -1331,6 +1525,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +354,7 @@
|
||||
return nbttagcompound;
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT");
|
||||
@@ -1371,7 +1566,7 @@
|
||||
@@ -1371,7 +1570,7 @@
|
||||
this.setAirTicks(nbttagcompound.getShort("Air"));
|
||||
this.onGround = nbttagcompound.getBoolean("OnGround");
|
||||
if (nbttagcompound.hasKey("Dimension")) {
|
||||
@ -359,7 +363,7 @@
|
||||
}
|
||||
|
||||
this.invulnerable = nbttagcompound.getBoolean("Invulnerable");
|
||||
@@ -1414,6 +1609,42 @@
|
||||
@@ -1414,6 +1613,42 @@
|
||||
} else {
|
||||
throw new IllegalStateException("Entity has invalid position");
|
||||
}
|
||||
@ -402,7 +406,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT");
|
||||
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded");
|
||||
@@ -1489,9 +1720,22 @@
|
||||
@@ -1489,9 +1724,22 @@
|
||||
} else if (this.world.isClientSide) {
|
||||
return null;
|
||||
} else {
|
||||
@ -425,7 +429,7 @@
|
||||
this.world.addEntity(entityitem);
|
||||
return entityitem;
|
||||
}
|
||||
@@ -1595,7 +1839,7 @@
|
||||
@@ -1595,7 +1843,7 @@
|
||||
}
|
||||
|
||||
this.vehicle = entity;
|
||||
@ -434,7 +438,7 @@
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1620,15 +1864,36 @@
|
||||
@@ -1620,15 +1868,36 @@
|
||||
Entity entity = this.vehicle;
|
||||
|
||||
this.vehicle = null;
|
||||
@ -473,7 +477,7 @@
|
||||
if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.getRidingPassenger() instanceof EntityHuman)) {
|
||||
this.passengers.add(0, entity);
|
||||
} else {
|
||||
@@ -1636,15 +1901,33 @@
|
||||
@@ -1636,15 +1905,33 @@
|
||||
}
|
||||
|
||||
}
|
||||
@ -508,7 +512,7 @@
|
||||
}
|
||||
|
||||
protected boolean q(Entity entity) {
|
||||
@@ -1687,11 +1970,17 @@
|
||||
@@ -1687,11 +1974,17 @@
|
||||
int i = this.ab();
|
||||
|
||||
if (this.ai) {
|
||||
@ -528,7 +532,7 @@
|
||||
this.world.getMethodProfiler().exit();
|
||||
}
|
||||
|
||||
@@ -1771,6 +2060,13 @@
|
||||
@@ -1771,6 +2064,13 @@
|
||||
}
|
||||
|
||||
public void setSwimming(boolean flag) {
|
||||
@ -542,7 +546,7 @@
|
||||
this.setFlag(4, flag);
|
||||
}
|
||||
|
||||
@@ -1831,16 +2127,56 @@
|
||||
@@ -1831,16 +2131,56 @@
|
||||
}
|
||||
|
||||
public void setAirTicks(int i) {
|
||||
@ -577,8 +581,9 @@
|
||||
+ this.setOnFire(entityCombustEvent.getDuration(), false);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
- this.damageEntity(DamageSource.LIGHTNING, 5.0F);
|
||||
+ // CraftBukkit start
|
||||
+ if (thisBukkitEntity instanceof Hanging) {
|
||||
+ HangingBreakByEntityEvent hangingEvent = new HangingBreakByEntityEvent((Hanging) thisBukkitEntity, stormBukkitEntity);
|
||||
@ -587,9 +592,8 @@
|
||||
+ if (hangingEvent.isCancelled()) {
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
- this.damageEntity(DamageSource.LIGHTNING, 5.0F);
|
||||
+ }
|
||||
+
|
||||
+ if (this.isFireProof()) {
|
||||
+ return;
|
||||
+ }
|
||||
@ -602,7 +606,7 @@
|
||||
}
|
||||
|
||||
public void j(boolean flag) {
|
||||
@@ -1988,20 +2324,33 @@
|
||||
@@ -1988,20 +2328,33 @@
|
||||
|
||||
@Nullable
|
||||
public Entity a(DimensionManager dimensionmanager) {
|
||||
@ -639,7 +643,7 @@
|
||||
if (dimensionmanager1 == DimensionManager.THE_END && dimensionmanager == DimensionManager.OVERWORLD) {
|
||||
blockposition = worldserver1.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.getSpawn());
|
||||
} else if (dimensionmanager == DimensionManager.THE_END) {
|
||||
@@ -2039,6 +2388,25 @@
|
||||
@@ -2039,6 +2392,25 @@
|
||||
vec3d = shapedetector_c.b;
|
||||
f = (float) shapedetector_c.c;
|
||||
}
|
||||
@ -665,7 +669,7 @@
|
||||
|
||||
this.world.getMethodProfiler().exitEnter("reloading");
|
||||
Entity entity = this.getEntityType().a((World) worldserver1);
|
||||
@@ -2048,6 +2416,14 @@
|
||||
@@ -2048,6 +2420,14 @@
|
||||
entity.setPositionRotation(blockposition, entity.yaw + f, entity.pitch);
|
||||
entity.setMot(vec3d);
|
||||
worldserver1.addEntityTeleport(entity);
|
||||
@ -680,7 +684,7 @@
|
||||
}
|
||||
|
||||
this.dead = true;
|
||||
@@ -2239,7 +2615,26 @@
|
||||
@@ -2239,7 +2619,26 @@
|
||||
}
|
||||
|
||||
public void a(AxisAlignedBB axisalignedbb) {
|
||||
|
@ -1,5 +1,14 @@
|
||||
--- a/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/net/minecraft/server/PlayerChunk.java
|
||||
@@ -23,7 +23,7 @@
|
||||
private volatile CompletableFuture<Either<Chunk, PlayerChunk.Failure>> tickingFuture;
|
||||
private volatile CompletableFuture<Either<Chunk, PlayerChunk.Failure>> entityTickingFuture;
|
||||
private CompletableFuture<IChunkAccess> chunkSave;
|
||||
- private int oldTicketLevel;
|
||||
+ public int oldTicketLevel; // CraftBukkit - public
|
||||
private int ticketLevel;
|
||||
private int n;
|
||||
private final ChunkCoordIntPair location;
|
||||
@@ -43,7 +43,7 @@
|
||||
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
||||
this.tickingFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
||||
@ -9,7 +18,31 @@
|
||||
this.dirtyBlocks = new short[64];
|
||||
this.location = chunkcoordintpair;
|
||||
this.lightEngine = lightengine;
|
||||
@@ -76,9 +76,9 @@
|
||||
@@ -55,6 +55,14 @@
|
||||
this.a(i);
|
||||
}
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ public Chunk getFullChunk() {
|
||||
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> statusFuture = this.getStatusFuture(ChunkStatus.FULL);
|
||||
+ Either<IChunkAccess, PlayerChunk.Failure> either = (Either<IChunkAccess, PlayerChunk.Failure>) statusFuture.getNow(null);
|
||||
+ return either == null ? null : (Chunk) either.left().orElse(null);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFutureUnchecked(ChunkStatus chunkstatus) {
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = (CompletableFuture) this.statusFutures.get(chunkstatus.c());
|
||||
|
||||
@@ -62,7 +70,7 @@
|
||||
}
|
||||
|
||||
public CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> getStatusFuture(ChunkStatus chunkstatus) {
|
||||
- return b(this.ticketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE;
|
||||
+ return b(this.oldTicketLevel).b(chunkstatus) ? this.getStatusFutureUnchecked(chunkstatus) : PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE; // CraftBukkit using oldTicketLevel for isLoaded checks
|
||||
}
|
||||
|
||||
public CompletableFuture<Either<Chunk, PlayerChunk.Failure>> a() {
|
||||
@@ -76,9 +84,9 @@
|
||||
@Nullable
|
||||
public Chunk getChunk() {
|
||||
CompletableFuture<Either<Chunk, PlayerChunk.Failure>> completablefuture = this.a();
|
||||
@ -21,7 +54,7 @@
|
||||
}
|
||||
|
||||
public CompletableFuture<IChunkAccess> getChunkSave() {
|
||||
@@ -201,7 +201,7 @@
|
||||
@@ -201,7 +209,7 @@
|
||||
CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture = (CompletableFuture) this.statusFutures.get(i);
|
||||
|
||||
if (completablefuture != null) {
|
||||
@ -30,23 +63,29 @@
|
||||
|
||||
if (either == null || either.left().isPresent()) {
|
||||
return completablefuture;
|
||||
@@ -213,6 +213,15 @@
|
||||
|
||||
this.a(completablefuture1);
|
||||
this.statusFutures.set(i, completablefuture1);
|
||||
+ // CraftBukkit start
|
||||
+ if (chunkstatus == ChunkStatus.FULL) {
|
||||
+ completablefuture1.thenAccept((either) -> {
|
||||
+ Chunk chunk = (Chunk) either.left().get();
|
||||
+
|
||||
+ chunk.loadCallback();
|
||||
@@ -256,6 +264,21 @@
|
||||
boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET;
|
||||
PlayerChunk.State playerchunk_state = c(this.oldTicketLevel);
|
||||
PlayerChunk.State playerchunk_state1 = c(this.ticketLevel);
|
||||
+ // CraftBukkit start
|
||||
+ // ChunkUnloadEvent: Called before the chunk is unloaded: isChunkLoaded is still true and chunk can still be modified by plugins.
|
||||
+ if (playerchunk_state.a(PlayerChunk.State.BORDER) && !playerchunk_state1.a(PlayerChunk.State.BORDER)) { // PAIL oldChunkState, newChunkState, isAtLeast
|
||||
+ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ either.ifLeft((chunkAccess) -> {
|
||||
+ Chunk chunk = (Chunk) chunkAccess;
|
||||
+ // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick
|
||||
+ // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag.
|
||||
+ // These actions may however happen deferred, so we manually set the needsSaving flag already here.
|
||||
+ chunk.setNeedsSaving(true);
|
||||
+ chunk.unloadCallback();
|
||||
+ });
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return completablefuture1;
|
||||
} else {
|
||||
return completablefuture == null ? PlayerChunk.UNLOADED_CHUNK_ACCESS_FUTURE : completablefuture;
|
||||
@@ -294,7 +303,7 @@
|
||||
+ });
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
|
||||
if (flag1) {
|
||||
for (int i = flag ? chunkstatus.c() + 1 : 0; i <= chunkstatus1.c(); ++i) {
|
||||
@@ -294,7 +317,7 @@
|
||||
if (flag2 && !flag3) {
|
||||
completablefuture = this.fullChunkFuture;
|
||||
this.fullChunkFuture = PlayerChunk.UNLOADED_CHUNK_FUTURE;
|
||||
@ -55,3 +94,21 @@
|
||||
playerchunkmap.getClass();
|
||||
return either1.ifLeft(playerchunkmap::a);
|
||||
}));
|
||||
@@ -332,6 +355,17 @@
|
||||
|
||||
this.w.a(this.location, this::j, this.ticketLevel, this::d);
|
||||
this.oldTicketLevel = this.ticketLevel;
|
||||
+ // CraftBukkit start
|
||||
+ // ChunkLoadEvent: Called after the chunk is loaded: isChunkLoaded returns true and chunk is ready to be modified by plugins.
|
||||
+ if (!playerchunk_state.a(PlayerChunk.State.BORDER) && playerchunk_state1.a(PlayerChunk.State.BORDER)) { // PAIL oldChunkState, newChunkState, isAtLeast
|
||||
+ this.getStatusFutureUnchecked(ChunkStatus.FULL).thenAccept((either) -> {
|
||||
+ either.ifLeft((chunkAccess) -> {
|
||||
+ Chunk chunk = (Chunk) chunkAccess;
|
||||
+ chunk.loadCallback();
|
||||
+ });
|
||||
+ });
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public static ChunkStatus b(int i) {
|
||||
|
@ -1,17 +1,14 @@
|
||||
--- a/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -35,6 +35,10 @@
|
||||
@@ -35,6 +35,7 @@
|
||||
import org.apache.commons.lang3.mutable.MutableBoolean;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.entity.Player;
|
||||
+import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
+// CraftBukkit end
|
||||
+import org.bukkit.entity.Player; // CraftBukkit
|
||||
|
||||
public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
||||
@@ -181,9 +185,12 @@
|
||||
@@ -181,9 +182,12 @@
|
||||
|
||||
return completablefuture1.thenApply((list1) -> {
|
||||
List<IChunkAccess> list2 = Lists.newArrayList();
|
||||
@ -26,7 +23,7 @@
|
||||
final Either<IChunkAccess, PlayerChunk.Failure> either = (Either) iterator.next();
|
||||
Optional<IChunkAccess> optional = either.left();
|
||||
|
||||
@@ -279,7 +286,7 @@
|
||||
@@ -279,7 +283,7 @@
|
||||
PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.x.getName());
|
||||
} else {
|
||||
this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> {
|
||||
@ -35,7 +32,7 @@
|
||||
|
||||
if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) {
|
||||
this.saveChunk(ichunkaccess);
|
||||
@@ -290,7 +297,6 @@
|
||||
@@ -290,7 +294,6 @@
|
||||
}
|
||||
|
||||
}
|
||||
@ -43,27 +40,7 @@
|
||||
protected void unloadChunks(BooleanSupplier booleansupplier) {
|
||||
GameProfilerFiller gameprofilerfiller = this.world.getMethodProfiler();
|
||||
|
||||
@@ -330,9 +336,19 @@
|
||||
if (this.loadedChunks.remove(i) && ichunkaccess instanceof Chunk) {
|
||||
Chunk chunk = (Chunk) ichunkaccess;
|
||||
|
||||
+ // CraftBukkit start
|
||||
+ ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk, chunk.isNeedsSaving());
|
||||
+ this.world.getServer().getPluginManager().callEvent(event);
|
||||
+ this.saveChunk(ichunkaccess, event.isSaveChunk());
|
||||
+ // CraftBukkit end
|
||||
+
|
||||
chunk.setLoaded(false);
|
||||
this.world.unloadChunk(chunk);
|
||||
+ // CraftBukkit start
|
||||
+ } else {
|
||||
+ this.saveChunk(ichunkaccess);
|
||||
}
|
||||
+ // CraftBukkit end
|
||||
|
||||
this.lightEngine.a(ichunkaccess.getPos());
|
||||
this.lightEngine.queueUpdate();
|
||||
@@ -416,7 +432,7 @@
|
||||
@@ -416,7 +419,7 @@
|
||||
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
|
||||
});
|
||||
}, (runnable) -> {
|
||||
@ -72,7 +49,7 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -498,7 +514,7 @@
|
||||
@@ -498,7 +501,7 @@
|
||||
long i = playerchunk.h().pair();
|
||||
|
||||
playerchunk.getClass();
|
||||
@ -81,7 +58,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -515,7 +531,7 @@
|
||||
@@ -515,7 +518,7 @@
|
||||
return Either.left(chunk);
|
||||
});
|
||||
}, (runnable) -> {
|
||||
@ -90,7 +67,7 @@
|
||||
});
|
||||
|
||||
completablefuture1.thenAcceptAsync((either) -> {
|
||||
@@ -529,7 +545,7 @@
|
||||
@@ -529,7 +532,7 @@
|
||||
return Either.left(chunk);
|
||||
});
|
||||
}, (runnable) -> {
|
||||
@ -99,7 +76,7 @@
|
||||
});
|
||||
return completablefuture1;
|
||||
}
|
||||
@@ -543,7 +559,7 @@
|
||||
@@ -543,7 +546,7 @@
|
||||
return chunk;
|
||||
});
|
||||
}, (runnable) -> {
|
||||
@ -108,23 +85,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -552,8 +568,14 @@
|
||||
}
|
||||
|
||||
public boolean saveChunk(IChunkAccess ichunkaccess) {
|
||||
+ // CraftBukkit start
|
||||
+ return this.saveChunk(ichunkaccess, ichunkaccess.isNeedsSaving());
|
||||
+ }
|
||||
+
|
||||
+ public boolean saveChunk(IChunkAccess ichunkaccess, boolean save) {
|
||||
+ // CraftBukkit end
|
||||
this.n.a(ichunkaccess.getPos());
|
||||
- if (!ichunkaccess.isNeedsSaving()) {
|
||||
+ if (!save) { // CraftBukkit
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
@@ -607,9 +629,10 @@
|
||||
@@ -607,9 +610,10 @@
|
||||
ChunkCoordIntPair chunkcoordintpair = playerchunk.h();
|
||||
Packet<?>[] apacket = new Packet[2];
|
||||
|
||||
@ -136,7 +97,7 @@
|
||||
boolean flag1 = i1 <= this.viewDistance;
|
||||
|
||||
this.sendChunk(entityplayer, chunkcoordintpair, apacket, flag, flag1);
|
||||
@@ -664,7 +687,7 @@
|
||||
@@ -664,7 +668,7 @@
|
||||
private NBTTagCompound readChunkData(ChunkCoordIntPair chunkcoordintpair) throws IOException {
|
||||
NBTTagCompound nbttagcompound = this.read(chunkcoordintpair);
|
||||
|
||||
@ -145,7 +106,7 @@
|
||||
}
|
||||
|
||||
boolean d(ChunkCoordIntPair chunkcoordintpair) {
|
||||
@@ -984,7 +1007,7 @@
|
||||
@@ -984,7 +988,7 @@
|
||||
public final Set<EntityPlayer> trackedPlayers = Sets.newHashSet();
|
||||
|
||||
public EntityTracker(Entity entity, int i, int j, boolean flag) {
|
||||
@ -154,7 +115,7 @@
|
||||
this.tracker = entity;
|
||||
this.trackingDistance = i;
|
||||
this.e = SectionPosition.a(entity);
|
||||
@@ -1053,6 +1076,17 @@
|
||||
@@ -1053,6 +1057,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,9 @@ public class CraftChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public Entity[] getEntities() {
|
||||
if (!isLoaded()) {
|
||||
getWorld().getChunkAt(x, z); // Transient load for this tick
|
||||
}
|
||||
int count = 0, index = 0;
|
||||
net.minecraft.server.Chunk chunk = getHandle();
|
||||
|
||||
@ -118,6 +121,9 @@ public class CraftChunk implements Chunk {
|
||||
|
||||
@Override
|
||||
public BlockState[] getTileEntities() {
|
||||
if (!isLoaded()) {
|
||||
getWorld().getChunkAt(x, z); // Transient load for this tick
|
||||
}
|
||||
int index = 0;
|
||||
net.minecraft.server.Chunk chunk = getHandle();
|
||||
|
||||
|
@ -330,7 +330,7 @@ public class CraftWorld implements World {
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
net.minecraft.server.Chunk chunk = world.getChunkProvider().getChunkAt(x, z, false);
|
||||
return chunk != null && chunk.loaded;
|
||||
return chunk != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -345,8 +345,7 @@ public class CraftWorld implements World {
|
||||
@Override
|
||||
public Chunk[] getLoadedChunks() {
|
||||
Long2ObjectLinkedOpenHashMap<PlayerChunk> chunks = world.getChunkProvider().playerChunkMap.visibleChunks;
|
||||
|
||||
return chunks.values().stream().map(PlayerChunk::getChunk).filter(Objects::nonNull).filter((chunk) -> chunk.loaded).map(net.minecraft.server.Chunk::getBukkitChunk).toArray(Chunk[]::new);
|
||||
return chunks.values().stream().map(PlayerChunk::getFullChunk).filter(Objects::nonNull).map(net.minecraft.server.Chunk::getBukkitChunk).toArray(Chunk[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -530,7 +530,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return entity.isAlive() && entity.valid;
|
||||
return entity.isAlive() && entity.valid && entity.isChunkLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren