import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.EntityEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.List;
import java.util.WeakHashMap;
@SideOnly(Side.SERVER)
public class EntityChunkLoadingManager implements ForgeChunkManager.LoadingCallback{
private final Object mod;
private final WeakHashMap<ChunkLoadingEntity, Ticket> tickets = new WeakHashMap<>();
private final WorldAccessor worldAccessor = new WorldAccessor();
public EntityChunkLoadingManager(Object modInstance){
mod = modInstance;
MinecraftForge.EVENT_BUS.register(this);
ForgeChunkManager.setForcedChunkLoadingCallback(mod, this);
}
@SubscribeEvent
public void onEnteringChunk(EntityEvent.EnteringChunk e){
if(e.getEntity() instanceof ChunkLoadingEntity && !e.getEntity().isDead){
ChunkLoadingEntity loadingEntity = (ChunkLoadingEntity)e.getEntity();
ForgeChunkManager.Ticket ticket = getTicket(loadingEntity);
if(ticket == null){
ticket = ForgeChunkManager.requestTicket(mod, e.getEntity().world, ForgeChunkManager.Type.ENTITY);
if(ticket != null){
ticket.bindEntity(e.getEntity());
addTicket(loadingEntity, ticket);
loadingEntity.onAddedTicket(ticket);
}
}
if(ticket != null){
if(e.getOldChunkX() != 0 && e.getOldChunkZ() != 0){
ForgeChunkManager.unforceChunk(ticket, new ChunkPos(e.getOldChunkX(), e.getOldChunkZ()));
}
ForgeChunkManager.forceChunk(ticket, new ChunkPos(e.getNewChunkX(), e.getNewChunkZ()));
}
}
}
@SubscribeEvent
public void onWorldLoad(WorldEvent.Load e){
e.getWorld().removeEventListener(worldAccessor);
e.getWorld().addEventListener(worldAccessor);
}
@Override
public void ticketsLoaded(List<Ticket> tickets, World world){
for(ForgeChunkManager.Ticket ticket : tickets){
boolean saved = false;
Entity entity = ticket.getEntity();
if(entity instanceof ChunkLoadingEntity && !entity.isDead){
saved = true;
addTicket((ChunkLoadingEntity)entity, ticket);
}
if(!saved){
ForgeChunkManager.releaseTicket(ticket);
}
}
}
public ForgeChunkManager.Ticket removeTicket(ChunkLoadingEntity entity){
ForgeChunkManager.Ticket ticket = tickets.get(entity);
if(ticket != null){
ForgeChunkManager.releaseTicket(ticket);
}
tickets.remove(entity);
return ticket;
}
public void addTicket(ChunkLoadingEntity entity, ForgeChunkManager.Ticket ticket){
if(tickets.get(entity) != null){
removeTicket(entity);
}
tickets.put(entity, ticket);
}
public ForgeChunkManager.Ticket getTicket(ChunkLoadingEntity entity){
return tickets.get(entity);
}
private class WorldAccessor implements IWorldEventListener{
@Override
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags){
}
@Override
public void notifyLightSet(BlockPos pos){
}
@Override
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2){
}
@Override
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, double x, double y, double z, float volume, float pitch){
}
@Override
public void playRecord(SoundEvent soundIn, BlockPos pos){
}
@Override
public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters){
}
@Override
public void spawnParticle(int id, boolean ignoreRange, boolean minimiseParticleLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int... parameters){
}
@Override
public void onEntityAdded(Entity entityIn){
}
@Override
public void onEntityRemoved(Entity entity){
if(entity instanceof ChunkLoadingEntity){
ChunkLoadingEntity loadingEntity = (ChunkLoadingEntity)entity;
Ticket ticket = removeTicket(loadingEntity);
loadingEntity.onRemovedTicket(ticket);
}
}
@Override
public void broadcastSound(int soundID, BlockPos pos, int data){
}
@Override
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data){
}
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress){
}
}
}