Files

925 lines
38 KiB
Diff

--- ../src-base/minecraft/net/minecraft/world/World.java
+++ ../src-work/minecraft/net/minecraft/world/World.java
@@ -4,13 +4,10 @@
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-import java.util.UUID;
-import javax.annotation.Nullable;
+import com.google.common.collect.Maps;
+
+import luohuayu.CatServer.capture.WorldCapture;
+import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material;
@@ -20,6 +17,15 @@
import net.minecraft.crash.ICrashReportDetail;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.entity.item.EntityXPOrb;
+import net.minecraft.entity.monster.EntityGhast;
+import net.minecraft.entity.monster.EntityGolem;
+import net.minecraft.entity.monster.EntityMob;
+import net.minecraft.entity.monster.EntitySlime;
+import net.minecraft.entity.passive.EntityAnimal;
+import net.minecraft.entity.passive.EntityWaterMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Biomes;
@@ -32,19 +38,8 @@
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.EntitySelectors;
-import net.minecraft.util.EnumFacing;
-import net.minecraft.util.EnumParticleTypes;
-import net.minecraft.util.ITickable;
-import net.minecraft.util.IntHashMap;
-import net.minecraft.util.ReportedException;
-import net.minecraft.util.SoundCategory;
-import net.minecraft.util.SoundEvent;
-import net.minecraft.util.math.AxisAlignedBB;
-import net.minecraft.util.math.BlockPos;
-import net.minecraft.util.math.MathHelper;
-import net.minecraft.util.math.RayTraceResult;
-import net.minecraft.util.math.Vec3d;
+import net.minecraft.util.*;
+import net.minecraft.util.math.*;
import net.minecraft.village.VillageCollection;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeProvider;
@@ -53,12 +48,32 @@
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.structure.StructureBoundingBox;
import net.minecraft.world.storage.ISaveHandler;
+import net.minecraft.world.storage.MapData;
import net.minecraft.world.storage.MapStorage;
import net.minecraft.world.storage.WorldInfo;
import net.minecraft.world.storage.loot.LootTableManager;
+import net.minecraftforge.common.DimensionManager;
+import net.minecraftforge.common.WorldSpecificSaveHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
+import org.bukkit.Bukkit;
+import org.bukkit.block.BlockState;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.CraftWorld;
+import org.bukkit.craftbukkit.SpigotTimings;
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+import org.bukkit.craftbukkit.util.CraftMagicNumbers;
+import org.bukkit.event.block.BlockCanBuildEvent;
+import org.bukkit.event.block.BlockPhysicsEvent;
+import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
+import org.bukkit.generator.ChunkGenerator;
+import org.spigotmc.ActivationRange;
+import org.spigotmc.SpigotWorldConfig;
+import org.spigotmc.TickLimiter;
+import javax.annotation.Nullable;
+import java.util.*;
+
public abstract class World implements IBlockAccess, net.minecraftforge.common.capabilities.ICapabilityProvider
{
/**
@@ -67,6 +82,12 @@
* of one of there entities.
*/
public static double MAX_ENTITY_RADIUS = 2.0D;
+ public static boolean haveWeSilencedAPhysicsCrash;
+ public static String blockLocation;
+ public final SpigotWorldConfig spigotConfig;
+ public final SpigotTimings.WorldTimingsHandler timings;
+ private TickLimiter entityLimiter;
+ private TickLimiter tileLimiter;
private int seaLevel = 63;
protected boolean scheduledUpdatesAreImmediate;
@@ -89,22 +110,22 @@
public float thunderingStrength;
private int lastLightningBolt;
public final Random rand = new Random();
- public final WorldProvider provider;
+ public WorldProvider provider;
protected PathWorldListener pathListener = new PathWorldListener();
protected List<IWorldEventListener> eventListeners;
protected IChunkProvider chunkProvider;
protected final ISaveHandler saveHandler;
- protected WorldInfo worldInfo;
+ public WorldInfo worldInfo;
protected boolean findingSpawnPoint;
- protected MapStorage mapStorage;
+ public MapStorage mapStorage;
public VillageCollection villageCollectionObj;
protected LootTableManager lootTable;
public final Profiler theProfiler;
private final Calendar theCalendar;
- protected Scoreboard worldScoreboard;
+ public Scoreboard worldScoreboard;
public final boolean isRemote;
- protected boolean spawnHostileMobs;
- protected boolean spawnPeacefulMobs;
+ public boolean spawnHostileMobs;
+ public boolean spawnPeacefulMobs;
private boolean processingLoadedTiles;
private final WorldBorder worldBorder;
int[] lightUpdateBlockList;
@@ -112,11 +133,61 @@
public boolean restoringBlockSnapshots = false;
public boolean captureBlockSnapshots = false;
public java.util.ArrayList<net.minecraftforge.common.util.BlockSnapshot> capturedBlockSnapshots = new java.util.ArrayList<net.minecraftforge.common.util.BlockSnapshot>();
+ public WorldCapture mCapture=new WorldCapture(this,capturedBlockSnapshots);
private net.minecraftforge.common.capabilities.CapabilityDispatcher capabilities;
private net.minecraftforge.common.util.WorldCapabilityData capabilityData;
+
+ // CraftBukkit start Added the following
+ private final CraftWorld world;
+ public boolean pvpMode;
+ public boolean keepSpawnInMemory = true;
+ public ChunkGenerator generator;
- protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client)
- {
+ public boolean captureTreeGeneration = false;
+
+ public long ticksPerAnimalSpawns;
+ public long ticksPerMonsterSpawns;
+ public boolean populating;
+ private int tickPosition;
+ private int tileTickPosition;
+ private boolean guardEntityList;
+
+ public CraftWorld getWorld() {
+ return this.world;
+ }
+
+ public CraftServer getServer() {
+ return (CraftServer) Bukkit.getServer();
+ }
+
+ @MethodsReturnNonnullByDefault
+ public Chunk getChunkIfLoaded(int x, int z) {
+ return this.chunkProvider.getLoadedChunk(x, z);
+ }
+
+ private void initLimiter() {
+ entityLimiter = new TickLimiter(spigotConfig.entityMaxTickTime);
+ tileLimiter = new TickLimiter(spigotConfig.tileMaxTickTime);
+ }
+
+ protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client) {
+ // Cauldron start - handle dummy worlds
+ if (DimensionManager.getWorld(0) != null)
+ {
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(info.getWorldName()); // Spigot
+ initLimiter(); // Spigot
+ this.world = DimensionManager.getWorld(0).getWorld();
+ this.timings = DimensionManager.getWorld(0).timings;
+ this.mapStorage = DimensionManager.getWorld(0).mapStorage;
+ }
+ else
+ {
+ this.spigotConfig = null;
+ this.world = null;
+ this.timings = null;
+ this.mapStorage = null;
+ }
+ // Cauldron end
this.eventListeners = Lists.newArrayList(new IWorldEventListener[] {this.pathListener});
this.theCalendar = Calendar.getInstance();
this.worldScoreboard = new Scoreboard();
@@ -126,12 +197,87 @@
this.saveHandler = saveHandlerIn;
this.theProfiler = profilerIn;
this.worldInfo = info;
- this.provider = providerIn;
this.isRemote = client;
this.worldBorder = providerIn.createWorldBorder();
- perWorldStorage = new MapStorage((ISaveHandler)null);
+ if(providerIn != null){
+ this.provider = providerIn;
+ } else if (this.worldInfo != null && this.worldInfo.getDimension() != 0) { // Cauldron
+ this.provider = WorldProvider.getProviderForDimension(this.worldInfo.getDimension());
+ } else {
+ this.provider = WorldProvider.getProviderForDimension(0);
+ }
+ if(this.worldInfo != null){
+ if(this.worldInfo.getDimension() != 0){
+ this.provider.setDimension(this.worldInfo.getDimension());
+ } else {
+ this.worldInfo.setDimension(this.provider.getDimension());
+ }
+ }
+
+ int providerId = this.provider.getDimension();
+ this.provider.registerWorld(this);
+ this.provider.setDimension(providerId);
+
}
+ protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client, ChunkGenerator gen, org.bukkit.World.Environment env) {
+ this.generator = gen;
+ this.world = new CraftWorld((WorldServer) this, gen, env);
+ this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit
+ this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit
+ // CB end
+ this.eventListeners = Lists.newArrayList(new IWorldEventListener[] {this.pathListener});
+ this.theCalendar = Calendar.getInstance();
+ this.worldScoreboard = new Scoreboard();
+ this.spawnHostileMobs = true;
+ this.spawnPeacefulMobs = true;
+ this.lightUpdateBlockList = new int[32768];
+ this.spigotConfig = new SpigotWorldConfig(info.getWorldName());
+ this.initLimiter();
+ this.saveHandler = saveHandlerIn;
+ this.theProfiler = profilerIn;
+ this.worldInfo = info;
+ //this.provider = providerIn;
+ this.isRemote = client;
+ this.worldBorder = providerIn.createWorldBorder();
+ if (DimensionManager.getWorld(0) != null) // if overworld has loaded, use its mapstorage
+ {
+ this.mapStorage = DimensionManager.getWorld(0).mapStorage;
+ }
+ else
+ {
+ this.mapStorage = new MapStorage(saveHandlerIn);
+ }
+ if(providerIn != null){
+ this.provider = providerIn;
+ } else if (this.worldInfo != null && this.worldInfo.getDimension() != 0) { // Cauldron
+ this.provider = WorldProvider.getProviderForDimension(this.worldInfo.getDimension());
+ } else {
+ this.provider = WorldProvider.getProviderForDimension(0);
+ }
+ if(this.worldInfo != null){
+ // Cauldron start - Use saved dimension from level.dat. Fixes issues with MultiVerse
+ if (this.worldInfo.getDimension() != 0)
+ this.provider.setDimension(this.worldInfo.getDimension());
+ else
+ {
+ this.worldInfo.setDimension(this.provider.getDimension());
+ }
+ }
+ if (this.worldInfo.getDimension() == 0)
+ {
+ generator = this.getServer().getGenerator(this.worldInfo.getWorldName());
+ if (generator != null)
+ {
+ getWorld().generator=generator;
+ getWorld().getPopulators().addAll(generator.getDefaultPopulators(getWorld()));
+ }
+ }
+ this.getServer().addWorld(this.world);
+ this.timings = new SpigotTimings.WorldTimingsHandler(this);
+
+ }
+
public World init()
{
return this;
@@ -291,7 +437,7 @@
}
}
- protected abstract boolean isChunkLoaded(int x, int z, boolean allowEmpty);
+ public abstract boolean isChunkLoaded(int x, int z, boolean allowEmpty);
public Chunk getChunkFromBlockCoords(BlockPos pos)
{
@@ -305,6 +451,27 @@
public boolean setBlockState(BlockPos pos, IBlockState newState, int flags)
{
+ // Cauldron start - tree generation
+ if (this.captureTreeGeneration)
+ {
+ net.minecraftforge.common.util.BlockSnapshot blocksnapshot = null;
+
+ for (net.minecraftforge.common.util.BlockSnapshot previous : this.capturedBlockSnapshots)
+ {
+ if (previous.getPos().equals(pos))
+ {
+ blocksnapshot = previous;
+ break;
+ }
+ }
+ if (blocksnapshot != null)
+ {
+ this.capturedBlockSnapshots.remove(blocksnapshot);
+ }
+ this.capturedBlockSnapshots.add(new net.minecraftforge.common.util.BlockSnapshot(this, pos, newState, flags));
+ return true;
+ }
+ // Cauldron end
if (this.isOutsideBuildHeight(pos))
{
return false;
@@ -420,6 +587,11 @@
{
if (this.worldInfo.getTerrainType() != WorldType.DEBUG_WORLD)
{
+ // CraftBukkit start
+ if (populating) {
+ return;
+ }
+ // CraftBukkit end
this.notifyNeighborsOfStateChange(pos, blockType);
}
}
@@ -516,7 +688,21 @@
try
{
+ // CraftBukkit start
+ CraftWorld world = ((WorldServer) this).getWorld();
+ if (world != null) {
+ BlockPhysicsEvent event = new BlockPhysicsEvent(world.getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftMagicNumbers.getId(blockIn));
+ this.getServer().getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+ }
+ // CraftBukkit end
iblockstate.neighborChanged(this, pos, blockIn);
+ } catch (StackOverflowError stackOverflowError) {
+ World.haveWeSilencedAPhysicsCrash = true;
+ World.blockLocation = String.valueOf(pos.getX()) + ", " + pos.getY() + ", " + pos.getZ();
}
catch (Throwable throwable)
{
@@ -833,6 +1019,17 @@
public IBlockState getBlockState(BlockPos pos)
{
+ // Cauldron start - tree generation
+ if (captureTreeGeneration)
+ {
+ for (net.minecraftforge.common.util.BlockSnapshot blocksnapshot : this.capturedBlockSnapshots)
+ {
+ if (blocksnapshot.getPos().equals(pos)) {
+ return blocksnapshot.getReplacedBlock();
+ }
+ }
+ }
+ // Cauldron end
if (this.isOutsideBuildHeight(pos))
{
return Blocks.AIR.getDefaultState();
@@ -1098,12 +1295,21 @@
this.weatherEffects.add(entityIn);
return true;
}
-
- public boolean spawnEntityInWorld(Entity entityIn)
+ public boolean spawnEntityInWorld(Entity entityIn) {
+ return addEntity(entityIn, SpawnReason.DEFAULT);
+ }
+ public boolean addEntity(Entity entityIn, SpawnReason reason)
{
// do not drop any items while restoring blocksnapshots. Prevents dupes
- if (!this.isRemote && (entityIn == null || (entityIn instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;
-
+ if (!this.isRemote){
+ if (entityIn == null) return false;
+ if (this.restoringBlockSnapshots) return true;
+ if (this.mCapture.isCapture()&&!(entityIn instanceof EntityPlayerMP)){
+ this.mCapture.addCaptureEntity(this,entityIn,reason);
+ return true;
+ }
+ }
+
int i = MathHelper.floor_double(entityIn.posX / 16.0D);
int j = MathHelper.floor_double(entityIn.posZ / 16.0D);
boolean flag = entityIn.forceSpawn;
@@ -1112,13 +1318,55 @@
{
flag = true;
}
+ // CraftBukkit start
+ org.bukkit.event.Cancellable event = null;
+ if (entityIn instanceof EntityLivingBase && !(entityIn instanceof EntityPlayerMP)) {
+ boolean isAnimal = entityIn instanceof EntityAnimal || entityIn instanceof EntityWaterMob || entityIn instanceof EntityGolem;
+ boolean isMonster = entityIn instanceof EntityMob || entityIn instanceof EntityGhast || entityIn instanceof EntitySlime;
+ if (reason != SpawnReason.CUSTOM) {
+ if (isAnimal && !spawnPeacefulMobs || isMonster && !spawnHostileMobs) {
+ entityIn.isDead = true;
+ return false;
+ }
+ }
+
+ event = CraftEventFactory.callCreatureSpawnEvent((EntityLivingBase) entityIn, reason);
+ } else if (entityIn instanceof EntityItem) {
+ event = CraftEventFactory.callItemSpawnEvent((EntityItem) entityIn);
+ } else if (entityIn.getBukkitEntity() instanceof org.bukkit.entity.Projectile) {
+ // Not all projectiles extend EntityProjectile, so check for Bukkit interface instead
+ event = CraftEventFactory.callProjectileLaunchEvent(entityIn);
+ } else if(entityIn instanceof EntityXPOrb){
+ EntityXPOrb xp = (EntityXPOrb)entityIn;
+ double radius = this.getSpigotConfig().expMerge;
+ if(radius > 0){
+ List<Entity> entities = this.getEntitiesWithinAABBExcludingEntity(entityIn,entityIn.getEntityBoundingBox().expand(radius,radius,radius));
+ for(Entity e: entities){
+ if(e instanceof EntityXPOrb){
+ EntityXPOrb loopItem = (EntityXPOrb) e;
+ if(!loopItem.isDead){
+ xp.xpValue += loopItem.xpValue;
+ loopItem.setDead();
+ }
+ }
+ }
+ }
+ }
+
+ if (event != null && (event.isCancelled() || entityIn.isDead)) {
+ entityIn.isDead = true;
+ return false;
+ }
+ // CraftBukkit end
if (!flag && !this.isChunkLoaded(i, j, false))
{
+ entityIn.isDead = true;
return false;
}
else
{
+ if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)) && !flag) return false;
if (entityIn instanceof EntityPlayer)
{
EntityPlayer entityplayer = (EntityPlayer)entityIn;
@@ -1126,7 +1374,6 @@
this.updateAllPlayersSleepingFlag();
}
- if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)) && !flag) return false;
this.getChunkFromChunkCoords(i, j).addEntity(entityIn);
this.loadedEntityList.add(entityIn);
@@ -1141,6 +1388,7 @@
{
((IWorldEventListener)this.eventListeners.get(i)).onEntityAdded(entityIn);
}
+ entityIn.valid = true; // CraftBukkit
}
public void onEntityRemoved(Entity entityIn)
@@ -1149,6 +1397,7 @@
{
((IWorldEventListener)this.eventListeners.get(i)).onEntityRemoved(entityIn);
}
+ entityIn.valid = false; // CraftBukkit
}
public void removeEntity(Entity entityIn)
@@ -1168,6 +1417,23 @@
if (entityIn instanceof EntityPlayer)
{
this.playerEntities.remove(entityIn);
+ // Spigot start
+ for (Object o : mapStorage.loadedDataList)
+ {
+ if (o instanceof MapData)
+ {
+ MapData map = (MapData) o;
+ map.playersHashMap.remove(entityIn);
+ for (Iterator<MapData.MapInfo> iter = (Iterator<MapData.MapInfo>) map.playersArrayList.iterator(); iter.hasNext(); )
+ {
+ if (iter.next().entityplayerObj == entityIn)
+ {
+ iter.remove();
+ }
+ }
+ }
+ }
+ // Spigot end
this.updateAllPlayersSleepingFlag();
this.onEntityRemoved(entityIn);
}
@@ -1191,8 +1457,16 @@
{
this.getChunkFromChunkCoords(i, j).removeEntity(entityIn);
}
-
- this.loadedEntityList.remove(entityIn);
+ // CraftBukkit start - Decrement loop variable field if we've already ticked this entity
+ int index = this.loadedEntityList.indexOf(entityIn);
+ if (index != -1) {
+ if (index <= this.tickPosition) {
+ this.tickPosition--;
+ }
+ this.loadedEntityList.remove(index);
+ }
+ // CraftBukkit end
+ //this.loadedEntityList.remove(entityIn);
this.onEntityRemoved(entityIn);
}
@@ -1667,7 +1941,11 @@
for (int i = 0; i < this.weatherEffects.size(); ++i)
{
Entity entity = (Entity)this.weatherEffects.get(i);
-
+ // CraftBukkit start - Fixed an NPE
+ if (entity == null) {
+ continue;
+ }
+ // CraftBukkit end
try
{
++entity.ticksExisted;
@@ -1678,14 +1956,14 @@
CrashReport crashreport = CrashReport.makeCrashReport(throwable2, "Ticking entity");
CrashReportCategory crashreportcategory = crashreport.makeCategory("Entity being ticked");
- if (entity == null)
- {
- crashreportcategory.addCrashSection("Entity", "~~NULL~~");
- }
- else
- {
+ //if (entity == null)
+ //{
+ // crashreportcategory.addCrashSection("Entity", "~~NULL~~");
+ //}
+ //else
+ //{
entity.addEntityCrashInfo(crashreportcategory);
- }
+ //}
if (net.minecraftforge.common.ForgeModContainer.removeErroringEntities)
{
@@ -1725,10 +2003,22 @@
this.unloadedEntityList.clear();
this.tickPlayers();
this.theProfiler.endStartSection("regular");
+ ActivationRange.activateEntities(this);
+ this.timings.entityTick.startTiming();
+ this.guardEntityList = true;
+ int entitiesThisCycle = 0;
+ if (this.tickPosition < 0){
+ this.tickPosition = 0;
+ }
- for (int i1 = 0; i1 < this.loadedEntityList.size(); ++i1)
- {
- Entity entity2 = (Entity)this.loadedEntityList.get(i1);
+ //for (int i1 = 0; i1 < this.loadedEntityList.size(); ++i1)
+ //{
+ // CraftBukkit start - Use field for loop variable
+ for (this.entityLimiter.initTick(); entitiesThisCycle < this.loadedEntityList.size() && (entitiesThisCycle % 10 != 0 || this.entityLimiter.shouldContinue()); tickPosition++, entitiesThisCycle++){
+ this.tickPosition = ((this.tickPosition<this.loadedEntityList.size()) ? this.tickPosition : 0);
+ Entity entity2 = (Entity) this.loadedEntityList.get(this.tickPosition);
+ // CraftBukkit end
+ //Entity entity2 = (Entity)this.loadedEntityList.get(i1);
Entity entity3 = entity2.getRidingEntity();
if (entity3 != null)
@@ -1747,7 +2037,9 @@
{
try
{
+ SpigotTimings.tickEntityTimer.startTiming();
this.updateEntity(entity2);
+ SpigotTimings.tickEntityTimer.stopTiming();
}
catch (Throwable throwable1)
{
@@ -1776,22 +2068,46 @@
{
this.getChunkFromChunkCoords(l1, i2).removeEntity(entity2);
}
-
- this.loadedEntityList.remove(i1--);
+ guardEntityList = false;
+ this.loadedEntityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable
+ guardEntityList = true;
this.onEntityRemoved(entity2);
}
this.theProfiler.endSection();
}
+ guardEntityList = false;
+ this.timings.entityTick.stopTiming();
this.theProfiler.endStartSection("blockEntities");
this.processingLoadedTiles = true;
- Iterator<TileEntity> iterator = this.tickableTileEntities.iterator();
-
- while (iterator.hasNext())
- {
- TileEntity tileentity = (TileEntity)iterator.next();
-
+ this.timings.tileEntityTick.startTiming();
+ // CraftBukkit start - From below, clean up tile entities before ticking them
+ if (!this.tileEntitiesToBeRemoved.isEmpty()) {
+ for (Object tile : tileEntitiesToBeRemoved) // Forge
+ {
+ ((TileEntity)tile).onChunkUnload();
+ }
+ this.tickableTileEntities.removeAll(this.tileEntitiesToBeRemoved);
+ this.loadedTileEntityList.removeAll(this.tileEntitiesToBeRemoved);
+ this.tileEntitiesToBeRemoved.clear();
+ }
+ // CraftBukkit end
+ //Iterator<TileEntity> iterator = this.tickableTileEntities.iterator();
+ int tilesThisCycle = 0;
+ for (tileLimiter.initTick();
+ tilesThisCycle < this.tickableTileEntities.size() && (tilesThisCycle % 10 != 0 || tileLimiter.shouldContinue());
+ tileTickPosition++, tilesThisCycle++) {
+ tileTickPosition = (tileTickPosition < tickableTileEntities.size()) ? tileTickPosition : 0;
+ TileEntity tileentity = (TileEntity) this.tickableTileEntities.get(tileTickPosition);
+ //Spigot start
+ if (tileentity == null) {
+ getServer().getLogger().severe("Spigot has detected a null entity and has removed it, preventing a crash");
+ tilesThisCycle--;
+ this.tickableTileEntities.remove(tileTickPosition--);
+ continue;
+ }
+ //Spigot end
if (!tileentity.isInvalid() && tileentity.hasWorldObj())
{
BlockPos blockpos = tileentity.getPos();
@@ -1801,6 +2117,7 @@
try
{
this.theProfiler.startSection(this.theProfiler.profilingEnabled ? tileentity.getClass().getSimpleName() : ""); // Fix for MC-117087
+ tileentity.tickTimer.startTiming();
((ITickable)tileentity).update();
this.theProfiler.endSection();
}
@@ -1818,13 +2135,17 @@
else
throw new ReportedException(crashreport2);
}
+ finally {
+ tileentity.tickTimer.stopTiming();
+ }
}
}
if (tileentity.isInvalid())
{
- iterator.remove();
+ tilesThisCycle--;
this.loadedTileEntityList.remove(tileentity);
+ this.tickableTileEntities.remove(tileentity);
if (this.isBlockLoaded(tileentity.getPos()))
{
@@ -1835,8 +2156,9 @@
}
}
}
-
- if (!this.tileEntitiesToBeRemoved.isEmpty())
+ timings.tileEntityTick.stopTiming();
+ timings.tileEntityPending.startTiming();
+ /*if (!this.tileEntitiesToBeRemoved.isEmpty())
{
for (Object tile : tileEntitiesToBeRemoved)
{
@@ -1849,7 +2171,7 @@
this.tickableTileEntities.removeAll(remove);
this.loadedTileEntityList.removeAll(remove);
this.tileEntitiesToBeRemoved.clear();
- }
+ }*/
this.processingLoadedTiles = false; //FML Move below remove to prevent CMEs
@@ -1863,10 +2185,11 @@
if (!tileentity1.isInvalid())
{
+ /* CraftBukkit start - Order matters, moved down
if (!this.loadedTileEntityList.contains(tileentity1))
{
this.addTileEntity(tileentity1);
- }
+ }// CraftBukkit end */
if (this.isBlockLoaded(tileentity1.getPos()))
{
@@ -1874,13 +2197,19 @@
IBlockState iblockstate = chunk.getBlockState(tileentity1.getPos());
chunk.addTileEntity(tileentity1.getPos(), tileentity1);
this.notifyBlockUpdate(tileentity1.getPos(), iblockstate, iblockstate, 3);
+ // CraftBukkit start
+ // From above, don't screw this up - SPIGOT-1746
+ if (!this.loadedTileEntityList.contains(tileentity1)) {
+ this.addTileEntity(tileentity1);
+ }
+ // CraftBukkit end
}
}
}
this.addedTileEntityList.clear();
}
-
+ timings.tileEntityPending.stopTiming();
this.theProfiler.endSection();
this.theProfiler.endSection();
}
@@ -1897,9 +2226,13 @@
List<TileEntity> dest = processingLoadedTiles ? addedTileEntityList : loadedTileEntityList;
boolean flag = dest.add(tile);
- if (flag && tile instanceof ITickable)
+ if (flag)
{
- this.tickableTileEntities.add(tile);
+ this.tileEntitiesToBeRemoved.remove(tile); // add by cc,prevent no tick bug
+ if(tile instanceof ITickable)
+ {
+ this.tickableTileEntities.add(tile);
+ }
}
if (this.isRemote)
@@ -1941,13 +2274,16 @@
{
int i = MathHelper.floor_double(entityIn.posX);
int j = MathHelper.floor_double(entityIn.posZ);
- boolean isForced = getPersistentChunks().containsKey(new net.minecraft.util.math.ChunkPos(i >> 4, j >> 4));
- int k = isForced ? 0 : 32;
- boolean canUpdate = !forceUpdate || this.isAreaLoaded(i - k, 0, j - k, i + k, 0, j + k, true);
+ //boolean isForced = getPersistentChunks().containsKey(new net.minecraft.util.math.ChunkPos(i >> 4, j >> 4));
+ //int k = isForced ? 0 : 32;
+ // CraftBukkit start - Use neighbor cache instead of looking up
+ Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4);
+ boolean canUpdate = startingChunk != null && (!forceUpdate || startingChunk.areNeighborsLoaded(2))/*this.isAreaLoaded(i - k, 0, j - k, i + k, 0, j + k, true)*/;
if (!canUpdate) canUpdate = net.minecraftforge.event.ForgeEventFactory.canEntityUpdate(entityIn);
if (canUpdate)
{
+ entityIn.tickTimer.startTiming(); // Spigot
entityIn.lastTickPosX = entityIn.posX;
entityIn.lastTickPosY = entityIn.posY;
entityIn.lastTickPosZ = entityIn.posZ;
@@ -2032,6 +2368,7 @@
}
}
}
+ entityIn.tickTimer.stopTiming(); // Spigot
}
}
@@ -2383,7 +2720,7 @@
{
return this.chunkProvider.makeString();
}
-
+ public Map<BlockPos, TileEntity> capturedTileEntities = Maps.newHashMap();
@Nullable
public TileEntity getTileEntity(BlockPos pos)
{
@@ -2393,6 +2730,11 @@
}
else
{
+ // CraftBukkit start
+ if (capturedTileEntities.containsKey(pos)) {
+ return capturedTileEntities.get(pos);
+ }
+ // CraftBukkit end
TileEntity tileentity = null;
if (this.processingLoadedTiles)
@@ -2659,6 +3001,13 @@
}
this.rainingStrength = MathHelper.clamp_float(this.rainingStrength, 0.0F, 1.0F);
+ // CraftBukkit start
+ for (int idx = 0; idx < this.playerEntities.size(); ++idx) {
+ if (((EntityPlayerMP) this.playerEntities.get(idx)).worldObj == this) {
+ ((EntityPlayerMP) this.playerEntities.get(idx)).tickWeather();
+ }
+ }
+ // CraftBukkit end
}
}
}
@@ -2843,8 +3192,11 @@
public boolean checkLightFor(EnumSkyBlock lightType, BlockPos pos)
{
- if (!this.isAreaLoaded(pos, 17, false))
- {
+ //if (!this.isAreaLoaded(pos, 17, false))
+ // CraftBukkit start - Use neighbor cache instead of looking up
+ Chunk chunk = this.getChunkIfLoaded(pos.getX() >> 4, pos.getZ() >> 4);
+ if (chunk == null || !chunk.areNeighborsLoaded(1) /*!this.areChunksLoaded(blockposition, 17, false)*/) {
+ // CraftBukkit end
return false;
}
else
@@ -3131,11 +3483,20 @@
int i = 0;
for (Entity entity : this.loadedEntityList)
- {
- if ((!(entity instanceof EntityLiving) || !((EntityLiving)entity).isNoDespawnRequired()) && entityType.isAssignableFrom(entity.getClass()))
- {
- ++i;
+ { // CB start
+ //if ((!(entity instanceof EntityLiving) || !((EntityLiving)entity).isNoDespawnRequired()) && entityType.isAssignableFrom(entity.getClass()))
+ //{
+ // ++i;
+ //}
+ if (entity instanceof EntityLiving) {
+ final EntityLiving entityinsentient = (EntityLiving)entity;
+ if (entityinsentient.canDespawn() && entityinsentient.isNoDespawnRequired()) {
+ continue;
+ }
}
+ if (entityType.isAssignableFrom(entity.getClass())) {
+ ++i;
+ } // CB end
}
return i;
@@ -3145,6 +3506,11 @@
{
for (Entity entity : entityCollection)
{
+ // CB start
+ if(entity == null) {
+ continue;
+ }
+ // CB end
if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entity, this)))
{
loadedEntityList.add(entity);
@@ -3159,10 +3525,17 @@
}
public boolean canBlockBePlaced(Block blockIn, BlockPos pos, boolean p_175716_3_, EnumFacing side, @Nullable Entity entityIn, @Nullable ItemStack itemStackIn)
- {
- IBlockState iblockstate = this.getBlockState(pos);
- AxisAlignedBB axisalignedbb = p_175716_3_ ? null : blockIn.getDefaultState().getCollisionBoundingBox(this, pos);
- return axisalignedbb != Block.NULL_AABB && !this.checkNoEntityCollision(axisalignedbb.offset(pos), entityIn) ? false : (iblockstate.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL ? true : iblockstate.getBlock().isReplaceable(this, pos) && blockIn.canReplace(this, pos, side, itemStackIn));
+ { // CB start
+ final IBlockState iblockdata = this.getBlockState(pos);
+ final AxisAlignedBB axisalignedbb = p_175716_3_ ? null : blockIn.getDefaultState().getCollisionBoundingBox(this, pos);
+ final boolean defaultReturn = (axisalignedbb == Block.NULL_AABB || this.checkNoEntityCollision(axisalignedbb.offset(pos), entityIn)) && ((iblockdata.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL) || (iblockdata.getMaterial().isReplaceable() && blockIn.canReplace(this, pos, side, itemStackIn)));
+ final BlockCanBuildEvent event = new BlockCanBuildEvent(this.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ()), CraftMagicNumbers.getId(blockIn), defaultReturn);
+ this.getServer().getPluginManager().callEvent(event);
+ return event.isBuildable();
+ //IBlockState iblockstate = this.getBlockState(pos);
+ //AxisAlignedBB axisalignedbb = p_175716_3_ ? null : blockIn.getDefaultState().getCollisionBoundingBox(this, pos);
+ //return axisalignedbb != Block.NULL_AABB && !this.checkNoEntityCollision(axisalignedbb.offset(pos), entityIn) ? false : (iblockstate.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL ? true : iblockstate.getBlock().isReplaceable(this, pos) && blockIn.canReplace(this, pos, side, itemStackIn));
+ // CB end
}
public int getSeaLevel()
@@ -3296,6 +3669,11 @@
for (int i = 0; i < this.playerEntities.size(); ++i)
{
EntityPlayer entityplayer1 = (EntityPlayer)this.playerEntities.get(i);
+ // CraftBukkit start - Fixed an NPE
+ if (entityplayer1 == null || entityplayer1.isDead) {
+ continue;
+ }
+ // CraftBukkit end
if ((EntitySelectors.CAN_AI_TARGET.apply(entityplayer1) || !spectator) && (EntitySelectors.NOT_SPECTATING.apply(entityplayer1) || spectator))
{
@@ -3541,6 +3919,16 @@
public void updateAllPlayersSleepingFlag()
{
}
+
+ // CraftBukkit start
+ // Calls the method that checks to see if players are sleeping
+ // Called by CraftPlayer.setPermanentSleeping()
+ public void checkSleepStatus() {
+ if (!this.isRemote) {
+ this.updateAllPlayersSleepingFlag();
+ }
+ }
+ // CraftBukkit end
public float getThunderStrength(float delta)
{
@@ -3939,4 +4327,9 @@
{
return this.lootTable;
}
+
+ public SpigotWorldConfig getSpigotConfig() {
+ if (this.spigotConfig == null) if (DimensionManager.getWorld(0) != null) return DimensionManager.getWorld(0).spigotConfig;
+ return spigotConfig;
+ }
}