mirror of
https://github.com/barkeser2002/CatServer.git
synced 2026-09-25 08:00:02 +03:00
925 lines
38 KiB
Diff
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;
|
|
+ }
|
|
}
|