package net.minecraft.client.multiplayer;
import com.google.common.collect.Sets;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.Callable;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.MovingSoundMinecart;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.particle.EntityFireworkStarterFX;
import net.minecraft.crash.CrashReport;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityMinecart;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.profiler.Profiler;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.src.BlockPosM;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import net.minecraft.world.WorldProvider;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.storage.SaveDataMemoryStorage;
import net.minecraft.world.storage.SaveHandlerMP;
import net.minecraft.world.storage.WorldInfo;
public class WorldClient extends World
{
/** The packets that need to be sent to the server. */
private NetHandlerPlayClient sendQueue;
/** The ChunkProviderClient instance */
private ChunkProviderClient clientChunkProvider;
/** Contains all entities for this client, both spawned and non-spawned. */
private final Set entityList = Sets.newHashSet();
/**
* Contains all entities for this client that were not spawned due to a non-present chunk. The game will attempt to
* spawn up to 10 pending entities with each subsequent tick until the spawn queue is empty.
*/
private final Set entitySpawnQueue = Sets.newHashSet();
private final Minecraft mc = Minecraft.getMinecraft();
private final Set previousActiveChunkSet = Sets.newHashSet();
private static final String __OBFID = "CL_00000882";
public WorldClient(NetHandlerPlayClient p_i45063_1_, WorldSettings p_i45063_2_, int p_i45063_3_, EnumDifficulty p_i45063_4_, Profiler p_i45063_5_)
{
super(new SaveHandlerMP(), new WorldInfo(p_i45063_2_, "MpServer"), WorldProvider.getProviderForDimension(p_i45063_3_), p_i45063_5_, true);
this.sendQueue = p_i45063_1_;
this.getWorldInfo().setDifficulty(p_i45063_4_);
this.setSpawnLocation(new BlockPos(8, 64, 8));
this.provider.registerWorld(this);
this.chunkProvider = this.createChunkProvider();
this.mapStorage = new SaveDataMemoryStorage();
this.calculateInitialSkylight();
this.calculateInitialWeather();
}
/**
* Runs a single tick for the world
*/
public void tick()
{
super.tick();
this.func_82738_a(this.getTotalWorldTime() + 1L);
if (this.getGameRules().getGameRuleBooleanValue("doDaylightCycle"))
{
this.setWorldTime(this.getWorldTime() + 1L);
}
this.theProfiler.startSection("reEntryProcessing");
for (int var1 = 0; var1 < 10 && !this.entitySpawnQueue.isEmpty(); ++var1)
{
Entity var2 = (Entity)this.entitySpawnQueue.iterator().next();
this.entitySpawnQueue.remove(var2);
if (!this.loadedEntityList.contains(var2))
{
this.spawnEntityInWorld(var2);
}
}
this.theProfiler.endStartSection("chunkCache");
this.clientChunkProvider.unloadQueuedChunks();
this.theProfiler.endStartSection("blocks");
this.func_147456_g();
this.theProfiler.endSection();
}
/**
* Invalidates an AABB region of blocks from the receive queue, in the event that the block has been modified
* client-side in the intervening 80 receive ticks.
*/
public void invalidateBlockReceiveRegion(int p_73031_1_, int p_73031_2_, int p_73031_3_, int p_73031_4_, int p_73031_5_, int p_73031_6_) {}
/**
* Creates the chunk provider for this world. Called in the constructor. Retrieves provider from worldProvider?
*/
protected IChunkProvider createChunkProvider()
{
this.clientChunkProvider = new ChunkProviderClient(this);
return this.clientChunkProvider;
}
protected void func_147456_g()
{
super.func_147456_g();
this.previousActiveChunkSet.retainAll(this.activeChunkSet);
if (this.previousActiveChunkSet.size() == this.activeChunkSet.size())
{
this.previousActiveChunkSet.clear();
}
int var1 = 0;
Iterator var2 = this.activeChunkSet.iterator();
while (var2.hasNext())
{
ChunkCoordIntPair var3 = (ChunkCoordIntPair)var2.next();
if (!this.previousActiveChunkSet.contains(var3))
{
int var4 = var3.chunkXPos * 16;
int var5 = var3.chunkZPos * 16;
this.theProfiler.startSection("getChunk");
Chunk var6 = this.getChunkFromChunkCoords(var3.chunkXPos, var3.chunkZPos);
this.func_147467_a(var4, var5, var6);
this.theProfiler.endSection();
this.previousActiveChunkSet.add(var3);
++var1;
if (var1 >= 10)
{
return;
}
}
}
}
public void doPreChunk(int p_73025_1_, int p_73025_2_, boolean p_73025_3_)
{
if (p_73025_3_)
{
this.clientChunkProvider.loadChunk(p_73025_1_, p_73025_2_);
}
else
{
this.clientChunkProvider.unloadChunk(p_73025_1_, p_73025_2_);
}
if (!p_73025_3_)
{
this.markBlockRangeForRenderUpdate(p_73025_1_ * 16, 0, p_73025_2_ * 16, p_73025_1_ * 16 + 15, 256, p_73025_2_ * 16 + 15);
}
}
/**
* Called when an entity is spawned in the world. This includes players.
*/
public boolean spawnEntityInWorld(Entity p_72838_1_)
{
boolean var2 = super.spawnEntityInWorld(p_72838_1_);
this.entityList.add(p_72838_1_);
if (!var2)
{
this.entitySpawnQueue.add(p_72838_1_);
}
else if (p_72838_1_ instanceof EntityMinecart)
{
this.mc.getSoundHandler().playSound(new MovingSoundMinecart((EntityMinecart)p_72838_1_));
}
return var2;
}
/**
* Schedule the entity for removal during the next tick. Marks the entity dead in anticipation.
*/
public void removeEntity(Entity p_72900_1_)
{
super.removeEntity(p_72900_1_);
this.entityList.remove(p_72900_1_);
}
protected void onEntityAdded(Entity p_72923_1_)
{
super.onEntityAdded(p_72923_1_);
if (this.entitySpawnQueue.contains(p_72923_1_))
{
this.entitySpawnQueue.remove(p_72923_1_);
}
}
protected void onEntityRemoved(Entity p_72847_1_)
{
super.onEntityRemoved(p_72847_1_);
boolean var2 = false;
if (this.entityList.contains(p_72847_1_))
{
if (p_72847_1_.isEntityAlive())
{
this.entitySpawnQueue.add(p_72847_1_);
var2 = true;
}
else
{
this.entityList.remove(p_72847_1_);
}
}
}
/**
* Add an ID to Entity mapping to entityHashSet
*/
public void addEntityToWorld(int p_73027_1_, Entity p_73027_2_)
{
Entity var3 = this.getEntityByID(p_73027_1_);
if (var3 != null)
{
this.removeEntity(var3);
}
this.entityList.add(p_73027_2_);
p_73027_2_.setEntityId(p_73027_1_);
if (!this.spawnEntityInWorld(p_73027_2_))
{
this.entitySpawnQueue.add(p_73027_2_);
}
this.entitiesById.addKey(p_73027_1_, p_73027_2_);
}
/**
* Returns the Entity with the given ID, or null if it doesn't exist in this World.
*/
public Entity getEntityByID(int p_73045_1_)
{
return (Entity)(p_73045_1_ == this.mc.thePlayer.getEntityId() ? this.mc.thePlayer : super.getEntityByID(p_73045_1_));
}
public Entity removeEntityFromWorld(int p_73028_1_)
{
Entity var2 = (Entity)this.entitiesById.removeObject(p_73028_1_);
if (var2 != null)
{
this.entityList.remove(var2);
this.removeEntity(var2);
}
return var2;
}
public boolean func_180503_b(BlockPos p_180503_1_, IBlockState p_180503_2_)
{
int var3 = p_180503_1_.getX();
int var4 = p_180503_1_.getY();
int var5 = p_180503_1_.getZ();
this.invalidateBlockReceiveRegion(var3, var4, var5, var3, var4, var5);
return super.setBlockState(p_180503_1_, p_180503_2_, 3);
}
/**
* If on MP, sends a quitting packet.
*/
public void sendQuittingDisconnectingPacket()
{
this.sendQueue.getNetworkManager().closeChannel(new ChatComponentText("Quitting"));
}
/**
* Updates all weather states.
*/
protected void updateWeather() {}
protected int getRenderDistanceChunks()
{
return this.mc.gameSettings.renderDistanceChunks;
}
public void doVoidFogParticles(int p_73029_1_, int p_73029_2_, int p_73029_3_)
{
byte var4 = 16;
Random var5 = new Random();
ItemStack var6 = this.mc.thePlayer.getHeldItem();
boolean var7 = this.mc.playerController.func_178889_l() == WorldSettings.GameType.CREATIVE && var6 != null && Block.getBlockFromItem(var6.getItem()) == Blocks.barrier;
BlockPosM blockPosM = new BlockPosM(0, 0, 0, 3);
for (int var8 = 0; var8 < 1000; ++var8)
{
int var9 = p_73029_1_ + this.rand.nextInt(var4) - this.rand.nextInt(var4);
int var10 = p_73029_2_ + this.rand.nextInt(var4) - this.rand.nextInt(var4);
int var11 = p_73029_3_ + this.rand.nextInt(var4) - this.rand.nextInt(var4);
blockPosM.setXyz(var9, var10, var11);
IBlockState var13 = this.getBlockState(blockPosM);
var13.getBlock().randomDisplayTick(this, blockPosM, var13, var5);
if (var7 && var13.getBlock() == Blocks.barrier)
{
this.spawnParticle(EnumParticleTypes.BARRIER, (double)((float)var9 + 0.5F), (double)((float)var10 + 0.5F), (double)((float)var11 + 0.5F), 0.0D, 0.0D, 0.0D, new int[0]);
}
}
}
/**
* also releases skins.
*/
public void removeAllEntities()
{
this.loadedEntityList.removeAll(this.unloadedEntityList);
int var1;
Entity var2;
int var3;
int var4;
for (var1 = 0; var1 < this.unloadedEntityList.size(); ++var1)
{
var2 = (Entity)this.unloadedEntityList.get(var1);
var3 = var2.chunkCoordX;
var4 = var2.chunkCoordZ;
if (var2.addedToChunk && this.isChunkLoaded(var3, var4, true))
{
this.getChunkFromChunkCoords(var3, var4).removeEntity(var2);
}
}
for (var1 = 0; var1 < this.unloadedEntityList.size(); ++var1)
{
this.onEntityRemoved((Entity)this.unloadedEntityList.get(var1));
}
this.unloadedEntityList.clear();
for (var1 = 0; var1 < this.loadedEntityList.size(); ++var1)
{
var2 = (Entity)this.loadedEntityList.get(var1);
if (var2.ridingEntity != null)
{
if (!var2.ridingEntity.isDead && var2.ridingEntity.riddenByEntity == var2)
{
continue;
}
var2.ridingEntity.riddenByEntity = null;
var2.ridingEntity = null;
}
if (var2.isDead)
{
var3 = var2.chunkCoordX;
var4 = var2.chunkCoordZ;
if (var2.addedToChunk && this.isChunkLoaded(var3, var4, true))
{
this.getChunkFromChunkCoords(var3, var4).removeEntity(var2);
}
this.loadedEntityList.remove(var1--);
this.onEntityRemoved(var2);
}
}
}
/**
* Adds some basic stats of the world to the given crash report.
*/
public CrashReportCategory addWorldInfoToCrashReport(CrashReport report)
{
CrashReportCategory var2 = super.addWorldInfoToCrashReport(report);
var2.addCrashSectionCallable("Forced entities", new Callable()
{
private static final String __OBFID = "CL_00000883";
public String call()
{
return WorldClient.this.entityList.size() + " total; " + WorldClient.this.entityList.toString();
}
});
var2.addCrashSectionCallable("Retry entities", new Callable()
{
private static final String __OBFID = "CL_00000884";
public String call()
{
return WorldClient.this.entitySpawnQueue.size() + " total; " + WorldClient.this.entitySpawnQueue.toString();
}
});
var2.addCrashSectionCallable("Server brand", new Callable()
{
private static final String __OBFID = "CL_00000885";
public String call()
{
return WorldClient.this.mc.thePlayer.getClientBrand();
}
});
var2.addCrashSectionCallable("Server type", new Callable()
{
private static final String __OBFID = "CL_00000886";
public String call()
{
return WorldClient.this.mc.getIntegratedServer() == null ? "Non-integrated multiplayer server" : "Integrated singleplayer server";
}
});
return var2;
}
public void func_175731_a(BlockPos p_175731_1_, String p_175731_2_, float p_175731_3_, float p_175731_4_, boolean p_175731_5_)
{
this.playSound((double)p_175731_1_.getX() + 0.5D, (double)p_175731_1_.getY() + 0.5D, (double)p_175731_1_.getZ() + 0.5D, p_175731_2_, p_175731_3_, p_175731_4_, p_175731_5_);
}
/**
* par8 is loudness, all pars passed to minecraftInstance.sndManager.playSound
*/
public void playSound(double x, double y, double z, String soundName, float volume, float pitch, boolean distanceDelay)
{
double var11 = this.mc.func_175606_aa().getDistanceSq(x, y, z);
PositionedSoundRecord var13 = new PositionedSoundRecord(new ResourceLocation(soundName), volume, pitch, (float)x, (float)y, (float)z);
if (distanceDelay && var11 > 100.0D)
{
double var14 = Math.sqrt(var11) / 40.0D;
this.mc.getSoundHandler().playDelayedSound(var13, (int)(var14 * 20.0D));
}
else
{
this.mc.getSoundHandler().playSound(var13);
}
}
public void makeFireworks(double x, double y, double z, double motionX, double motionY, double motionZ, NBTTagCompound compund)
{
this.mc.effectRenderer.addEffect(new EntityFireworkStarterFX(this, x, y, z, motionX, motionY, motionZ, this.mc.effectRenderer, compund));
}
public void setWorldScoreboard(Scoreboard p_96443_1_)
{
this.worldScoreboard = p_96443_1_;
}
/**
* Sets the world time.
*/
public void setWorldTime(long time)
{
if (time < 0L)
{
time = -time;
this.getGameRules().setOrCreateGameRule("doDaylightCycle", "false");
}
else
{
this.getGameRules().setOrCreateGameRule("doDaylightCycle", "true");
}
super.setWorldTime(time);
}
}