Fix non-player entity freezing on chunk unload in 1.14+ (fixes #203)

This commit is contained in:
Jonas Herzig
2020-07-13 15:54:42 +02:00
parent dc31605b29
commit f1885ece41

View File

@@ -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
} }