Fix non-player entity freezing on chunk unload in 1.14+ (fixes #203)
This commit is contained in:
@@ -23,6 +23,7 @@ import net.minecraft.client.network.OtherClientPlayerEntity;
|
|||||||
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
|
import net.minecraft.client.gui.screen.DownloadingTerrainScreen;
|
||||||
import net.minecraft.client.gui.screen.NoticeScreen;
|
import net.minecraft.client.gui.screen.NoticeScreen;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.network.NetworkState;
|
import net.minecraft.network.NetworkState;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
@@ -52,8 +53,7 @@ import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
|
|||||||
import net.minecraft.network.packet.s2c.play.SignEditorOpenS2CPacket;
|
import net.minecraft.network.packet.s2c.play.SignEditorOpenS2CPacket;
|
||||||
import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket;
|
import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.world.chunk.ChunkProvider;
|
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
@@ -77,16 +77,16 @@ import net.minecraft.network.packet.s2c.play.OpenContainerS2CPacket;
|
|||||||
import net.minecraft.network.packet.s2c.play.OpenWrittenBookS2CPacket;
|
import net.minecraft.network.packet.s2c.play.OpenWrittenBookS2CPacket;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.world.chunk.ChunkManager;
|
||||||
|
import net.minecraft.world.chunk.WorldChunk;
|
||||||
import net.minecraft.world.chunk.light.LightingProvider;
|
import net.minecraft.world.chunk.light.LightingProvider;
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraft.client.resources.I18n;
|
//$$ import net.minecraft.client.resources.I18n;
|
||||||
//$$ import net.minecraft.entity.Entity;
|
|
||||||
//$$ import net.minecraft.util.math.MathHelper;
|
|
||||||
//$$ import net.minecraft.world.EnumDifficulty;
|
//$$ import net.minecraft.world.EnumDifficulty;
|
||||||
|
//$$ import net.minecraft.world.World;
|
||||||
//$$ import net.minecraft.world.WorldType;
|
//$$ import net.minecraft.world.WorldType;
|
||||||
//$$ import net.minecraft.world.chunk.Chunk;
|
//$$ import net.minecraft.world.chunk.Chunk;
|
||||||
//$$ import java.util.ArrayList;
|
//$$ import net.minecraft.world.chunk.IChunkProvider;
|
||||||
//$$ import java.util.Collection;
|
|
||||||
//$$ import java.util.Iterator;
|
//$$ import java.util.Iterator;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
@@ -125,7 +125,9 @@ import net.minecraft.network.NetworkSide;
|
|||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -1150,52 +1152,76 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
// Note: This is only half of the truth. Entities may be removed by chunk-unloading, see else-case below.
|
// Note: This is only half of the truth. Entities may be removed by chunk-unloading, see else-case below.
|
||||||
// To make things worse, it seems like players were never supposed to be unloaded this way because
|
// To make things worse, it seems like players were never supposed to be unloaded this way because
|
||||||
// they will remain glitched in the World#playerEntities list.
|
// they will remain glitched in the World#playerEntities list.
|
||||||
World world = mc.world;
|
// 1.14+: The update issue remains but only for non-players and the unloading list bug appears to have been
|
||||||
ChunkProvider chunkProvider = world.getChunkManager();
|
// fixed (chunk unloading no longer removes the entities).
|
||||||
// Get the chunk that will be unloaded
|
// Get the chunk that will be unloaded
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
// FIXME fabric
|
ClientWorld world = mc.world;
|
||||||
//#else
|
ChunkManager chunkProvider = world.getChunkManager();
|
||||||
//#if MC>=11400
|
WorldChunk chunk = chunkProvider.getWorldChunk(x, z
|
||||||
//$$ Chunk chunk = chunkProvider.provideChunk(x, z, false, false);
|
//#if MC<11500
|
||||||
//#else
|
//$$ , false
|
||||||
//$$ Chunk chunk = chunkProvider.provideChunk(x, z);
|
|
||||||
//#endif
|
//#endif
|
||||||
|
);
|
||||||
|
if (chunk != null) {
|
||||||
|
//#else
|
||||||
|
//$$ World world = mc.world;
|
||||||
|
//$$ IChunkProvider chunkProvider = world.getChunkProvider();
|
||||||
|
//$$ Chunk chunk = chunkProvider.provideChunk(x, z);
|
||||||
//$$ if (!chunk.isEmpty()) {
|
//$$ if (!chunk.isEmpty()) {
|
||||||
//$$ List<Entity> entitiesInChunk = new ArrayList<>();
|
//#endif
|
||||||
//$$ // Gather all entities in that chunk
|
List<Entity> entitiesInChunk = new ArrayList<>();
|
||||||
//$$ for (Collection<Entity> entityList : getEntityLists(chunk)) {
|
// Gather all entities in that chunk
|
||||||
//$$ entitiesInChunk.addAll(entityList);
|
for (Collection<Entity> entityList : getEntityLists(chunk)) {
|
||||||
//$$ }
|
entitiesInChunk.addAll(entityList);
|
||||||
//$$ for (Entity entity : entitiesInChunk) {
|
}
|
||||||
//$$ // Skip interpolation of position updates coming from server
|
for (Entity entity : entitiesInChunk) {
|
||||||
//$$ // (See: newX in EntityLivingBase or otherPlayerMPX in EntityOtherPlayerMP)
|
// Skip interpolation of position updates coming from server
|
||||||
//$$ // Needs to be called at least 4 times thanks to
|
// (See: newX in EntityLivingBase or otherPlayerMPX in EntityOtherPlayerMP)
|
||||||
//$$ // EntityOtherPlayerMP#otherPlayerMPPosRotationIncrements (max vanilla value is 3)
|
// Needs to be called at least 4 times thanks to
|
||||||
//$$ for (int i = 0; i < 4; i++) {
|
// EntityOtherPlayerMP#otherPlayerMPPosRotationIncrements (max vanilla value is 3)
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
//$$ entity.tick();
|
entity.tick();
|
||||||
//#else
|
//#else
|
||||||
//$$ entity.onUpdate();
|
//$$ entity.onUpdate();
|
||||||
//#endif
|
//#endif
|
||||||
//$$ }
|
}
|
||||||
//$$
|
|
||||||
//$$ // Check whether the entity has left the chunk
|
// Check whether the entity has left the chunk
|
||||||
|
//#if MC>=11404
|
||||||
|
int chunkX = MathHelper.floor(Entity_getX(entity) / 16);
|
||||||
|
int chunkY = MathHelper.floor(Entity_getY(entity) / 16);
|
||||||
|
int chunkZ = MathHelper.floor(Entity_getZ(entity) / 16);
|
||||||
|
if (entity.chunkX != chunkX || entity.chunkY != chunkY || entity.chunkZ != chunkZ) {
|
||||||
|
if (entity.updateNeeded) {
|
||||||
|
// Entity has left the chunk
|
||||||
|
chunk.remove(entity, entity.chunkY);
|
||||||
|
}
|
||||||
|
WorldChunk newChunk = chunkProvider.getWorldChunk(chunkX, chunkZ
|
||||||
|
//#if MC<11500
|
||||||
|
//$$ , false
|
||||||
|
//#endif
|
||||||
|
);
|
||||||
|
if (newChunk != null) {
|
||||||
|
newChunk.addEntity(entity);
|
||||||
|
} else {
|
||||||
|
// Entity has left all loaded chunks
|
||||||
|
entity.updateNeeded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//#else
|
||||||
//$$ int chunkX = MathHelper.floor(entity.posX / 16);
|
//$$ int chunkX = MathHelper.floor(entity.posX / 16);
|
||||||
//$$ int chunkZ = MathHelper.floor(entity.posZ / 16);
|
//$$ int chunkZ = MathHelper.floor(entity.posZ / 16);
|
||||||
//$$ if (entity.chunkCoordX != chunkX || entity.chunkCoordZ != chunkZ) {
|
//$$ if (entity.chunkCoordX != chunkX || entity.chunkCoordZ != chunkZ) {
|
||||||
//$$ // Entity has left the chunk
|
//$$ // Entity has left the chunk
|
||||||
//$$ chunk.removeEntityAtIndex(entity, entity.chunkCoordY);
|
//$$ chunk.removeEntityAtIndex(entity, entity.chunkCoordY);
|
||||||
//#if MC>=11400
|
|
||||||
//$$ Chunk newChunk = chunkProvider.provideChunk(chunkX, chunkZ, false, false);
|
|
||||||
//#else
|
|
||||||
//#if MC>=10904
|
//#if MC>=10904
|
||||||
//$$ Chunk newChunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
//$$ Chunk newChunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
||||||
//#else
|
//#else
|
||||||
//$$ Chunk newChunk = chunkProvider.chunkExists(chunkX, chunkZ)
|
//$$ Chunk newChunk = chunkProvider.chunkExists(chunkX, chunkZ)
|
||||||
//$$ ? chunkProvider.provideChunk(chunkX, chunkZ) : null;
|
//$$ ? chunkProvider.provideChunk(chunkX, chunkZ) : null;
|
||||||
//#endif
|
//#endif
|
||||||
//#endif
|
|
||||||
//$$ if (newChunk != null) {
|
//$$ if (newChunk != null) {
|
||||||
//$$ newChunk.addEntity(entity);
|
//$$ newChunk.addEntity(entity);
|
||||||
//$$ } else {
|
//$$ } else {
|
||||||
@@ -1222,10 +1248,10 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
|
|||||||
//$$ chunk.removeEntityAtIndex(entity, entity.chunkCoordY);
|
//$$ chunk.removeEntityAtIndex(entity, entity.chunkCoordY);
|
||||||
//$$ entity.addedToChunk = false;
|
//$$ entity.addedToChunk = false;
|
||||||
//$$ }
|
//$$ }
|
||||||
//$$ }
|
|
||||||
//$$ }
|
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return p; // During synchronous playback everything is sent normally
|
return p; // During synchronous playback everything is sent normally
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user