mirror of
https://github.com/barkeser2002/CatServer.git
synced 2026-09-25 01:39:52 +03:00
1862 lines
78 KiB
Diff
1862 lines
78 KiB
Diff
--- ../src-base/minecraft/net/minecraft/world/World.java
|
|
+++ ../src-work/minecraft/net/minecraft/world/World.java
|
|
@@ -4,14 +4,12 @@
|
|
import com.google.common.base.MoreObjects;
|
|
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 java.util.*;
|
|
import java.util.function.Supplier;
|
|
import javax.annotation.Nullable;
|
|
+
|
|
+import com.google.common.collect.Maps;
|
|
import net.minecraft.advancements.AdvancementManager;
|
|
import net.minecraft.advancements.FunctionManager;
|
|
import net.minecraft.block.Block;
|
|
@@ -24,12 +22,22 @@
|
|
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;
|
|
import net.minecraft.init.Blocks;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.network.Packet;
|
|
+import net.minecraft.network.play.server.SPacketWorldBorder;
|
|
import net.minecraft.pathfinding.PathWorldListener;
|
|
import net.minecraft.profiler.Profiler;
|
|
import net.minecraft.scoreboard.Scoreboard;
|
|
@@ -43,28 +51,46 @@
|
|
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.math.*;
|
|
import net.minecraft.village.VillageCollection;
|
|
import net.minecraft.world.biome.Biome;
|
|
import net.minecraft.world.biome.BiomeProvider;
|
|
+import net.minecraft.world.border.IBorderListener;
|
|
import net.minecraft.world.border.WorldBorder;
|
|
import net.minecraft.world.chunk.Chunk;
|
|
import net.minecraft.world.chunk.IChunkProvider;
|
|
+import net.minecraft.world.gen.ChunkProviderServer;
|
|
import net.minecraft.world.gen.structure.StructureBoundingBox;
|
|
import net.minecraft.world.storage.ISaveHandler;
|
|
import net.minecraft.world.storage.MapStorage;
|
|
import net.minecraft.world.storage.WorldInfo;
|
|
import net.minecraft.world.storage.WorldSavedData;
|
|
import net.minecraft.world.storage.loot.LootTableManager;
|
|
+import net.minecraftforge.common.DimensionManager;
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
+import org.bukkit.Bukkit;
|
|
+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.entity.NPC;
|
|
+import org.bukkit.event.block.BlockCanBuildEvent;
|
|
+import org.bukkit.event.block.BlockPhysicsEvent;
|
|
+import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
+import org.bukkit.generator.ChunkGenerator;
|
|
|
|
-public abstract class World implements IBlockAccess
|
|
+public abstract class World implements IBlockAccess, net.minecraftforge.common.capabilities.ICapabilityProvider
|
|
{
|
|
+ /**
|
|
+ * Used in the getEntitiesWithinAABB functions to expand the search area for entities.
|
|
+ * Modders should change this variable to a higher value if it is less then the radius
|
|
+ * of one of there entities.
|
|
+ */
|
|
+ public static double MAX_ENTITY_RADIUS = 2.0D;
|
|
+
|
|
+ private int tilesThisCycle = 0; // CatServer - Move up to keep LVT clean
|
|
private int seaLevel = 63;
|
|
protected boolean scheduledUpdatesAreImmediate;
|
|
public final List<Entity> loadedEntityList = Lists.<Entity>newArrayList();
|
|
@@ -86,30 +112,149 @@
|
|
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 villageCollection;
|
|
protected LootTableManager lootTable;
|
|
protected AdvancementManager advancementManager;
|
|
protected FunctionManager functionManager;
|
|
public final Profiler profiler;
|
|
private final Calendar calendar;
|
|
- 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;
|
|
|
|
+ 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>();
|
|
+ private net.minecraftforge.common.capabilities.CapabilityDispatcher capabilities;
|
|
+ private net.minecraftforge.common.util.WorldCapabilityData capabilityData;
|
|
+
|
|
+ private final CraftWorld world;
|
|
+ public boolean pvpMode;
|
|
+ public boolean keepSpawnInMemory = true;
|
|
+ public ChunkGenerator generator;
|
|
+
|
|
+ public boolean captureTreeGeneration = false;
|
|
+
|
|
+ public List<EntityItem> captureDrops;
|
|
+ public long ticksPerAnimalSpawns;
|
|
+ public long ticksPerMonsterSpawns;
|
|
+ public boolean populating;
|
|
+ private int tickPosition;
|
|
+ public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
|
|
+
|
|
+ public final SpigotTimings.WorldTimingsHandler timings; // Spigot
|
|
+
|
|
+ public static boolean haveWeSilencedAPhysicsCrash;
|
|
+ public static String blockLocation;
|
|
+ private org.spigotmc.TickLimiter entityLimiter;
|
|
+ private org.spigotmc.TickLimiter tileLimiter;
|
|
+ private int tileTickPosition;
|
|
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
|
+
|
|
+ public CraftWorld getWorld() {
|
|
+ return this.world;
|
|
+ }
|
|
+
|
|
+ public CraftServer getServer() {
|
|
+ return (CraftServer) Bukkit.getServer();
|
|
+ }
|
|
+
|
|
+ public Chunk getChunkIfLoaded(int x, int z) {
|
|
+ if (this.chunkProvider instanceof ChunkProviderServer) {
|
|
+ return ((ChunkProviderServer) this.chunkProvider).getChunkIfLoaded(x, z);
|
|
+ } else {
|
|
+ return isChunkLoaded(x, z, true) ? this.chunkProvider.getLoadedChunk(x, z) : null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client, ChunkGenerator gen, org.bukkit.World.Environment env) {
|
|
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig( info.getWorldName() ); // Spigot
|
|
+ this.generator = gen;
|
|
+ this.world = new CraftWorld((WorldServer) this, gen, env);
|
|
+ this.ticksPerAnimalSpawns = this.getServer().getTicksPerAnimalSpawns(); // CraftBukkit
|
|
+ this.ticksPerMonsterSpawns = this.getServer().getTicksPerMonsterSpawns(); // CraftBukkit
|
|
+ // CraftBukkit end
|
|
+ this.eventListeners = Lists.newArrayList(this.pathListener);
|
|
+ this.calendar = Calendar.getInstance();
|
|
+ this.worldScoreboard = new Scoreboard();
|
|
+ this.spawnHostileMobs = true;
|
|
+ this.spawnPeacefulMobs = true;
|
|
+ this.lightUpdateBlockList = new int[32768];
|
|
+ this.saveHandler = saveHandlerIn;
|
|
+ this.profiler = profilerIn;
|
|
+ this.worldInfo = info;
|
|
+ this.provider = providerIn;
|
|
+ this.isRemote = client;
|
|
+ this.worldBorder = providerIn.createWorldBorder();
|
|
+ perWorldStorage = new MapStorage((ISaveHandler)null);
|
|
+ // CatServer start
|
|
+ if(this.worldInfo != null) // 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) // Set generator for overworld
|
|
+ {
|
|
+ generator = this.getServer().getGenerator(this.worldInfo.getWorldName());
|
|
+ getWorld().generator = generator;
|
|
+ }
|
|
+ // CatServer end
|
|
+ // CraftBukkit start
|
|
+ getWorldBorder().world = (WorldServer) this;
|
|
+ // From PlayerList.setPlayerFileData
|
|
+ getWorldBorder().addListener(new IBorderListener() {
|
|
+ public void onSizeChanged(WorldBorder worldborder, double d0) {
|
|
+ getServer().getHandle().sendAll(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.SET_SIZE), worldborder.world);
|
|
+ }
|
|
+
|
|
+ public void onTransitionStarted(WorldBorder worldborder, double d0, double d1, long i) {
|
|
+ getServer().getHandle().sendAll(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.LERP_SIZE), worldborder.world);
|
|
+ }
|
|
+
|
|
+ public void onCenterChanged(WorldBorder worldborder, double d0, double d1) {
|
|
+ getServer().getHandle().sendAll(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.SET_CENTER), worldborder.world);
|
|
+ }
|
|
+
|
|
+ public void onWarningTimeChanged(WorldBorder worldborder, int i) {
|
|
+ getServer().getHandle().sendAll(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.SET_WARNING_TIME), worldborder.world);
|
|
+ }
|
|
+
|
|
+ public void onWarningDistanceChanged(WorldBorder worldborder, int i) {
|
|
+ getServer().getHandle().sendAll(new SPacketWorldBorder(worldborder, SPacketWorldBorder.Action.SET_WARNING_BLOCKS), worldborder.world);
|
|
+ }
|
|
+
|
|
+ public void onDamageAmountChanged(WorldBorder worldborder, double d0) {}
|
|
+
|
|
+ public void onDamageBufferChanged(WorldBorder worldborder, double d0) {}
|
|
+ });
|
|
+ this.getServer().addWorld(this.world);
|
|
+ // CraftBukkit end
|
|
+ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
|
|
+ this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
|
|
+ this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
|
|
+ }
|
|
+
|
|
protected World(ISaveHandler saveHandlerIn, WorldInfo info, WorldProvider providerIn, Profiler profilerIn, boolean client)
|
|
{
|
|
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig( info.getWorldName() ); // Spigot
|
|
+ this.world = DimensionManager.getWorld(0) != null ? DimensionManager.getWorld(0).getWorld() : null;
|
|
this.eventListeners = Lists.newArrayList(this.pathListener);
|
|
this.calendar = Calendar.getInstance();
|
|
this.worldScoreboard = new Scoreboard();
|
|
@@ -122,6 +267,10 @@
|
|
this.provider = providerIn;
|
|
this.isRemote = client;
|
|
this.worldBorder = providerIn.createWorldBorder();
|
|
+ perWorldStorage = new MapStorage((ISaveHandler)null);
|
|
+ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
|
|
+ this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
|
|
+ this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
|
|
}
|
|
|
|
public World init()
|
|
@@ -131,6 +280,11 @@
|
|
|
|
public Biome getBiome(final BlockPos pos)
|
|
{
|
|
+ return this.provider.getBiomeForCoords(pos);
|
|
+ }
|
|
+
|
|
+ public Biome getBiomeForCoordsBody(final BlockPos pos)
|
|
+ {
|
|
if (this.isBlockLoaded(pos))
|
|
{
|
|
Chunk chunk = this.getChunkFromBlockCoords(pos);
|
|
@@ -207,7 +361,7 @@
|
|
|
|
public boolean isAirBlock(BlockPos pos)
|
|
{
|
|
- return this.getBlockState(pos).getMaterial() == Material.AIR;
|
|
+ return this.getBlockState(pos).getBlock().isAir(this.getBlockState(pos), this, pos);
|
|
}
|
|
|
|
public boolean isBlockLoaded(BlockPos pos)
|
|
@@ -278,7 +432,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)
|
|
{
|
|
@@ -297,6 +451,26 @@
|
|
|
|
public boolean setBlockState(BlockPos pos, IBlockState newState, int flags)
|
|
{
|
|
+ // CatServer 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;
|
|
+ }
|
|
+ // CatServer end
|
|
if (this.isOutsideBuildHeight(pos))
|
|
{
|
|
return false;
|
|
@@ -308,24 +482,53 @@
|
|
else
|
|
{
|
|
Chunk chunk = this.getChunkFromBlockCoords(pos);
|
|
- Block block = newState.getBlock();
|
|
+
|
|
+ pos = pos.toImmutable(); // Forge - prevent mutable BlockPos leaks
|
|
+ net.minecraftforge.common.util.BlockSnapshot blockSnapshot = null;
|
|
+ if (this.captureBlockSnapshots && !this.isRemote)
|
|
+ {
|
|
+ blockSnapshot = net.minecraftforge.common.util.BlockSnapshot.getBlockSnapshot(this, pos, flags);
|
|
+ this.capturedBlockSnapshots.add(blockSnapshot);
|
|
+ }
|
|
+
|
|
+ IBlockState oldState = getBlockState(pos);
|
|
+ int oldLight = oldState.getLightValue(this, pos);
|
|
+ int oldOpacity = oldState.getLightOpacity(this, pos);
|
|
+
|
|
IBlockState iblockstate = chunk.setBlockState(pos, newState);
|
|
|
|
if (iblockstate == null)
|
|
{
|
|
+ if (blockSnapshot != null) this.capturedBlockSnapshots.remove(blockSnapshot);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
- if (newState.getLightOpacity() != iblockstate.getLightOpacity() || newState.getLightValue() != iblockstate.getLightValue())
|
|
+ if (newState.getLightOpacity(this, pos) != oldOpacity || newState.getLightValue(this, pos) != oldLight)
|
|
{
|
|
this.profiler.startSection("checkLight");
|
|
this.checkLight(pos);
|
|
this.profiler.endSection();
|
|
}
|
|
|
|
- if ((flags & 2) != 0 && (!this.isRemote || (flags & 4) == 0) && chunk.isPopulated())
|
|
+ if (blockSnapshot == null) // Don't notify clients or update physics while capturing blockstates
|
|
{
|
|
+ this.markAndNotifyBlock(pos, chunk, iblockstate, newState, flags);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Split off from original setBlockState(BlockPos, IBlockState, int) method in order to directly send client and physic updates
|
|
+ public void markAndNotifyBlock(BlockPos pos, @Nullable Chunk chunk, IBlockState iblockstate, IBlockState newState, int flags)
|
|
+ {
|
|
+ Block block = newState.getBlock();
|
|
+ {
|
|
+ {
|
|
+ if ((flags & 2) != 0 && (!this.isRemote || (flags & 4) == 0) && (chunk == null || chunk.isPopulated()))
|
|
+ {
|
|
this.notifyBlockUpdate(pos, iblockstate, newState, flags);
|
|
}
|
|
|
|
@@ -342,8 +545,6 @@
|
|
{
|
|
this.updateObservingBlocksAt(pos, block);
|
|
}
|
|
-
|
|
- return true;
|
|
}
|
|
}
|
|
}
|
|
@@ -358,7 +559,7 @@
|
|
IBlockState iblockstate = this.getBlockState(pos);
|
|
Block block = iblockstate.getBlock();
|
|
|
|
- if (iblockstate.getMaterial() == Material.AIR)
|
|
+ if (block.isAir(iblockstate, this, pos))
|
|
{
|
|
return false;
|
|
}
|
|
@@ -392,6 +593,9 @@
|
|
{
|
|
if (this.worldInfo.getTerrainType() != WorldType.DEBUG_ALL_BLOCK_STATES)
|
|
{
|
|
+ if (populating) {
|
|
+ return;
|
|
+ }
|
|
this.notifyNeighborsOfStateChange(pos, blockType, p_175722_3_);
|
|
}
|
|
}
|
|
@@ -441,6 +645,9 @@
|
|
|
|
public void notifyNeighborsOfStateChange(BlockPos pos, Block blockType, boolean updateObservers)
|
|
{
|
|
+ if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, pos, this.getBlockState(pos), java.util.EnumSet.allOf(EnumFacing.class), updateObservers).isCanceled())
|
|
+ return;
|
|
+
|
|
this.neighborChanged(pos.west(), blockType, pos);
|
|
this.neighborChanged(pos.east(), blockType, pos);
|
|
this.neighborChanged(pos.down(), blockType, pos);
|
|
@@ -456,6 +663,11 @@
|
|
|
|
public void notifyNeighborsOfStateExcept(BlockPos pos, Block blockType, EnumFacing skipSide)
|
|
{
|
|
+ java.util.EnumSet<EnumFacing> directions = java.util.EnumSet.allOf(EnumFacing.class);
|
|
+ directions.remove(skipSide);
|
|
+ if(net.minecraftforge.event.ForgeEventFactory.onNeighborNotify(this, pos, this.getBlockState(pos), directions, false).isCanceled())
|
|
+ return;
|
|
+
|
|
if (skipSide != EnumFacing.WEST)
|
|
{
|
|
this.neighborChanged(pos.west(), blockType, pos);
|
|
@@ -495,6 +707,15 @@
|
|
|
|
try
|
|
{
|
|
+ CraftWorld world = 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;
|
|
+ }
|
|
+ }
|
|
iblockstate.neighborChanged(this, pos, blockIn, fromPos);
|
|
}
|
|
catch (Throwable throwable)
|
|
@@ -507,7 +728,7 @@
|
|
{
|
|
try
|
|
{
|
|
- return String.format("ID #%d (%s // %s)", Block.getIdFromBlock(blockIn), blockIn.getUnlocalizedName(), blockIn.getClass().getCanonicalName());
|
|
+ return String.format("ID #%d (%s // %s // %s)", Block.getIdFromBlock(blockIn), blockIn.getUnlocalizedName(), blockIn.getClass().getName(), blockIn.getRegistryName());
|
|
}
|
|
catch (Throwable var2)
|
|
{
|
|
@@ -527,12 +748,17 @@
|
|
{
|
|
IBlockState iblockstate = this.getBlockState(pos);
|
|
|
|
- if (iblockstate.getBlock() == Blocks.OBSERVER)
|
|
+ if (true)
|
|
{
|
|
try
|
|
{
|
|
- ((BlockObserver)iblockstate.getBlock()).observedNeighborChanged(iblockstate, this, pos, p_190529_2_, p_190529_3_);
|
|
+ iblockstate.getBlock().observedNeighborChange(iblockstate, this, pos, p_190529_2_, p_190529_3_);
|
|
}
|
|
+ catch (StackOverflowError stackoverflowerror) { // Spigot Start
|
|
+ haveWeSilencedAPhysicsCrash = true;
|
|
+ blockLocation = pos.getX() + ", " + pos.getY() + ", " + pos.getZ();
|
|
+ // Spigot End
|
|
+ }
|
|
catch (Throwable throwable)
|
|
{
|
|
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception while updating neighbours");
|
|
@@ -588,7 +814,7 @@
|
|
{
|
|
IBlockState iblockstate = this.getBlockState(blockpos1);
|
|
|
|
- if (iblockstate.getLightOpacity() > 0 && !iblockstate.getMaterial().isLiquid())
|
|
+ if (iblockstate.getBlock().getLightOpacity(iblockstate, this, blockpos) > 0 && !iblockstate.getMaterial().isLiquid())
|
|
{
|
|
return false;
|
|
}
|
|
@@ -849,12 +1075,24 @@
|
|
|
|
public IBlockState getBlockState(BlockPos pos)
|
|
{
|
|
+ // CatServer start - tree generation
|
|
+ if (captureTreeGeneration)
|
|
+ {
|
|
+ for (net.minecraftforge.common.util.BlockSnapshot blocksnapshot : this.capturedBlockSnapshots)
|
|
+ {
|
|
+ if (blocksnapshot.getPos().equals(pos)) {
|
|
+ return blocksnapshot.getReplacedBlock();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // CraftBukkit end
|
|
if (this.isOutsideBuildHeight(pos))
|
|
{
|
|
return Blocks.AIR.getDefaultState();
|
|
}
|
|
else
|
|
{
|
|
+ if (catserver.server.CatServer.getConfig().preventBlockLoadChunk && !isBlockLoaded(pos)) return Blocks.AIR.getDefaultState();
|
|
Chunk chunk = this.getChunkFromBlockCoords(pos);
|
|
return chunk.getBlockState(pos);
|
|
}
|
|
@@ -862,7 +1100,7 @@
|
|
|
|
public boolean isDaytime()
|
|
{
|
|
- return this.skylightSubtracted < 4;
|
|
+ return this.provider.isDaytime();
|
|
}
|
|
|
|
@Nullable
|
|
@@ -1065,6 +1303,13 @@
|
|
|
|
public void playSound(@Nullable EntityPlayer player, double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch)
|
|
{
|
|
+ net.minecraftforge.event.entity.PlaySoundAtEntityEvent event = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAtEntity(player, soundIn, category, volume, pitch);
|
|
+ if (event.isCanceled() || event.getSound() == null) return;
|
|
+ soundIn = event.getSound();
|
|
+ category = event.getCategory();
|
|
+ volume = event.getVolume();
|
|
+ pitch = event.getPitch();
|
|
+
|
|
for (int i = 0; i < this.eventListeners.size(); ++i)
|
|
{
|
|
((IWorldEventListener)this.eventListeners.get(i)).playSoundToAllNearExcept(player, soundIn, category, x, y, z, volume, pitch);
|
|
@@ -1112,17 +1357,76 @@
|
|
|
|
public boolean addWeatherEffect(Entity entityIn)
|
|
{
|
|
+ if(net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)))
|
|
+ return false;
|
|
+
|
|
this.weatherEffects.add(entityIn);
|
|
return true;
|
|
}
|
|
|
|
public boolean spawnEntity(Entity entityIn)
|
|
{
|
|
- int i = MathHelper.floor(entityIn.posX / 16.0D);
|
|
- int j = MathHelper.floor(entityIn.posZ / 16.0D);
|
|
- boolean flag = entityIn.forceSpawn;
|
|
+ // CraftBukkit start - Used for entities other than creatures
|
|
+ return addEntity(entityIn, CreatureSpawnEvent.SpawnReason.DEFAULT);
|
|
+ }
|
|
|
|
- if (entityIn instanceof EntityPlayer)
|
|
+ public boolean addEntity(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
|
|
+ if (catserver.server.AsyncCatcher.checkAsync("add entity")) return catserver.server.AsyncCatcher.ensureExecuteOnPrimaryThread(() -> addEntity(entity, spawnReason)); // CatServer
|
|
+ if (entity == null) return false;
|
|
+
|
|
+ org.bukkit.event.Cancellable event = null;
|
|
+ if (entity instanceof EntityLivingBase && !(entity instanceof EntityPlayerMP)) {
|
|
+ boolean isAnimal = entity instanceof EntityAnimal || entity instanceof EntityWaterMob || entity instanceof EntityGolem;
|
|
+ boolean isMonster = entity instanceof EntityMob || entity instanceof EntityGhast || entity instanceof EntitySlime;
|
|
+ boolean isNpc = entity instanceof NPC;
|
|
+
|
|
+ if (spawnReason != CreatureSpawnEvent.SpawnReason.CUSTOM) {
|
|
+ if (isAnimal && !spawnPeacefulMobs || isMonster && !spawnHostileMobs || isNpc && !getServer().getServer().getCanSpawnNPCs()) {
|
|
+ entity.isDead = true;
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ event = CraftEventFactory.callCreatureSpawnEvent((EntityLivingBase) entity, spawnReason);
|
|
+ } else if (entity instanceof EntityItem) {
|
|
+ event = CraftEventFactory.callItemSpawnEvent((EntityItem) entity);
|
|
+ } else if (entity.getBukkitEntity() instanceof org.bukkit.entity.Projectile) {
|
|
+ // Not all projectiles extend EntityProjectile, so check for Bukkit interface instead
|
|
+ event = CraftEventFactory.callProjectileLaunchEvent(entity);
|
|
+ } else if (entity.getBukkitEntity() instanceof org.bukkit.entity.Vehicle){
|
|
+ event = CraftEventFactory.callVehicleCreateEvent(entity);
|
|
+ }
|
|
+ // Spigot start
|
|
+ else if (entity instanceof EntityXPOrb) {
|
|
+ EntityXPOrb xp = (EntityXPOrb) entity;
|
|
+ double radius = spigotConfig.expMerge;
|
|
+ if (radius > 0) {
|
|
+ List<Entity> entities = this.getEntitiesWithinAABBExcludingEntity(entity, entity.getEntityBoundingBox().grow(radius, radius, radius));
|
|
+ for (Entity e : entities) {
|
|
+ if (e instanceof EntityXPOrb) {
|
|
+ EntityXPOrb loopItem = (EntityXPOrb) e;
|
|
+ if (!loopItem.isDead) {
|
|
+ xp.xpValue += loopItem.xpValue;
|
|
+ loopItem.setDead();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ } // Spigot end
|
|
+
|
|
+ if (event != null && (event.isCancelled() || entity.isDead)) {
|
|
+ entity.isDead = true;
|
|
+ return false;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+ // do not drop any items while restoring blocksnapshots. Prevents dupes
|
|
+ if (!this.isRemote && (entity == null || (entity instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;
|
|
+
|
|
+ int i = MathHelper.floor(entity.posX / 16.0D);
|
|
+ int j = MathHelper.floor(entity.posZ / 16.0D);
|
|
+ boolean flag = entity.forceSpawn;
|
|
+
|
|
+ if (entity instanceof EntityPlayer)
|
|
{
|
|
flag = true;
|
|
}
|
|
@@ -1133,16 +1437,18 @@
|
|
}
|
|
else
|
|
{
|
|
- if (entityIn instanceof EntityPlayer)
|
|
+ if (entity instanceof EntityPlayer)
|
|
{
|
|
- EntityPlayer entityplayer = (EntityPlayer)entityIn;
|
|
+ EntityPlayer entityplayer = (EntityPlayer)entity;
|
|
this.playerEntities.add(entityplayer);
|
|
this.updateAllPlayersSleepingFlag();
|
|
}
|
|
|
|
- this.getChunkFromChunkCoords(i, j).addEntity(entityIn);
|
|
- this.loadedEntityList.add(entityIn);
|
|
- this.onEntityAdded(entityIn);
|
|
+ if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entity, this)) && !flag) return false;
|
|
+
|
|
+ this.getChunkFromChunkCoords(i, j).addEntity(entity);
|
|
+ this.loadedEntityList.add(entity);
|
|
+ this.onEntityAdded(entity);
|
|
return true;
|
|
}
|
|
}
|
|
@@ -1153,6 +1459,8 @@
|
|
{
|
|
((IWorldEventListener)this.eventListeners.get(i)).onEntityAdded(entityIn);
|
|
}
|
|
+ entityIn.onAddedToWorld();
|
|
+ entityIn.valid = true;
|
|
}
|
|
|
|
public void onEntityRemoved(Entity entityIn)
|
|
@@ -1161,10 +1469,13 @@
|
|
{
|
|
((IWorldEventListener)this.eventListeners.get(i)).onEntityRemoved(entityIn);
|
|
}
|
|
+ entityIn.onRemovedFromWorld();
|
|
+ entityIn.valid = false;
|
|
}
|
|
|
|
public void removeEntity(Entity entityIn)
|
|
{
|
|
+ if (catserver.server.AsyncCatcher.checkAsync("kill entity")) { catserver.server.AsyncCatcher.ensureExecuteOnPrimaryThread(() -> removeEntity(entityIn)); return; } // CatServer
|
|
if (entityIn.isBeingRidden())
|
|
{
|
|
entityIn.removePassengers();
|
|
@@ -1187,6 +1498,7 @@
|
|
|
|
public void removeEntityDangerously(Entity entityIn)
|
|
{
|
|
+ if (catserver.server.AsyncCatcher.checkAsync("remove entity")) { catserver.server.AsyncCatcher.ensureExecuteOnPrimaryThread(() -> removeEntityDangerously(entityIn)); return; } // CatServer
|
|
entityIn.setDropItemsWhenDead(false);
|
|
entityIn.setDead();
|
|
|
|
@@ -1204,7 +1516,16 @@
|
|
this.getChunkFromChunkCoords(i, j).removeEntity(entityIn);
|
|
}
|
|
|
|
- this.loadedEntityList.remove(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.onEntityRemoved(entityIn);
|
|
}
|
|
|
|
@@ -1227,6 +1548,7 @@
|
|
IBlockState iblockstate = Blocks.STONE.getDefaultState();
|
|
BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
|
|
|
|
+ if (p_191504_3_ && !net.minecraftforge.event.ForgeEventFactory.gatherCollisionBoxes(this, entityIn, aabb, outList)) return true;
|
|
try
|
|
{
|
|
for (int k1 = i; k1 < j; ++k1)
|
|
@@ -1269,7 +1591,7 @@
|
|
|
|
iblockstate1.addCollisionBoxToList(this, blockpos$pooledmutableblockpos, aabb, outList, entityIn, false);
|
|
|
|
- if (p_191504_3_ && !outList.isEmpty())
|
|
+ if (p_191504_3_ && !net.minecraftforge.event.ForgeEventFactory.gatherCollisionBoxes(this, entityIn, aabb, outList))
|
|
{
|
|
boolean flag5 = true;
|
|
return flag5;
|
|
@@ -1319,11 +1641,10 @@
|
|
}
|
|
}
|
|
}
|
|
-
|
|
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.GetCollisionBoxesEvent(this, entityIn, aabb, list));
|
|
return list;
|
|
}
|
|
|
|
- @SideOnly(Side.CLIENT)
|
|
public void removeEventListener(IWorldEventListener listener)
|
|
{
|
|
this.eventListeners.remove(listener);
|
|
@@ -1361,19 +1682,38 @@
|
|
|
|
public int calculateSkylightSubtracted(float partialTicks)
|
|
{
|
|
+ float f = provider.getSunBrightnessFactor(partialTicks);
|
|
+ f = 1 - f;
|
|
+ return (int)(f * 11);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * The current sun brightness factor for this dimension.
|
|
+ * 0.0f means no light at all, and 1.0f means maximum sunlight.
|
|
+ * Highly recommended for sunlight detection like solar panel.
|
|
+ *
|
|
+ * @return The current brightness factor
|
|
+ * */
|
|
+ public float getSunBrightnessFactor(float partialTicks)
|
|
+ {
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F);
|
|
f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
|
|
f1 = 1.0F - f1;
|
|
f1 = (float)((double)f1 * (1.0D - (double)(this.getRainStrength(partialTicks) * 5.0F) / 16.0D));
|
|
f1 = (float)((double)f1 * (1.0D - (double)(this.getThunderStrength(partialTicks) * 5.0F) / 16.0D));
|
|
- f1 = 1.0F - f1;
|
|
- return (int)(f1 * 11.0F);
|
|
+ return f1;
|
|
}
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
public float getSunBrightness(float partialTicks)
|
|
{
|
|
+ return this.provider.getSunBrightness(partialTicks);
|
|
+ }
|
|
+
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public float getSunBrightnessBody(float partialTicks)
|
|
+ {
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.2F);
|
|
f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
|
|
@@ -1386,6 +1726,12 @@
|
|
@SideOnly(Side.CLIENT)
|
|
public Vec3d getSkyColor(Entity entityIn, float partialTicks)
|
|
{
|
|
+ return this.provider.getSkyColor(entityIn, partialTicks);
|
|
+ }
|
|
+
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public Vec3d getSkyColorBody(Entity entityIn, float partialTicks)
|
|
+ {
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
float f1 = MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F;
|
|
f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
|
|
@@ -1393,9 +1739,7 @@
|
|
int j = MathHelper.floor(entityIn.posY);
|
|
int k = MathHelper.floor(entityIn.posZ);
|
|
BlockPos blockpos = new BlockPos(i, j, k);
|
|
- Biome biome = this.getBiome(blockpos);
|
|
- float f2 = biome.getTemperature(blockpos);
|
|
- int l = biome.getSkyColorByTemp(f2);
|
|
+ int l = net.minecraftforge.client.ForgeHooksClient.getSkyBlendColour(this, blockpos);
|
|
float f3 = (float)(l >> 16 & 255) / 255.0F;
|
|
float f4 = (float)(l >> 8 & 255) / 255.0F;
|
|
float f5 = (float)(l & 255) / 255.0F;
|
|
@@ -1444,20 +1788,25 @@
|
|
|
|
public float getCelestialAngle(float partialTicks)
|
|
{
|
|
- return this.provider.calculateCelestialAngle(this.worldInfo.getWorldTime(), partialTicks);
|
|
+ return this.provider.calculateCelestialAngle(this.getWorldTime(), partialTicks);
|
|
}
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
public int getMoonPhase()
|
|
{
|
|
- return this.provider.getMoonPhase(this.worldInfo.getWorldTime());
|
|
+ return this.provider.getMoonPhase(this.getWorldTime());
|
|
}
|
|
|
|
public float getCurrentMoonPhaseFactor()
|
|
{
|
|
- return WorldProvider.MOON_PHASE_FACTORS[this.provider.getMoonPhase(this.worldInfo.getWorldTime())];
|
|
+ return provider.getCurrentMoonPhaseFactor();
|
|
}
|
|
|
|
+ public float getCurrentMoonPhaseFactorBody()
|
|
+ {
|
|
+ return WorldProvider.MOON_PHASE_FACTORS[this.provider.getMoonPhase(this.getWorldTime())];
|
|
+ }
|
|
+
|
|
public float getCelestialAngleRadians(float partialTicks)
|
|
{
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
@@ -1467,6 +1816,12 @@
|
|
@SideOnly(Side.CLIENT)
|
|
public Vec3d getCloudColour(float partialTicks)
|
|
{
|
|
+ return this.provider.getCloudColor(partialTicks);
|
|
+ }
|
|
+
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public Vec3d getCloudColorBody(float partialTicks)
|
|
+ {
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
float f1 = MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.5F;
|
|
f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
|
|
@@ -1522,9 +1877,9 @@
|
|
for (blockpos = new BlockPos(pos.getX(), chunk.getTopFilledSegment() + 16, pos.getZ()); blockpos.getY() >= 0; blockpos = blockpos1)
|
|
{
|
|
blockpos1 = blockpos.down();
|
|
- Material material = chunk.getBlockState(blockpos1).getMaterial();
|
|
+ IBlockState state = chunk.getBlockState(blockpos1);
|
|
|
|
- if (material.blocksMovement() && material != Material.LEAVES)
|
|
+ if (state.getMaterial().blocksMovement() && !state.getBlock().isLeaves(state, this, blockpos1) && !state.getBlock().isFoliage(this, blockpos1))
|
|
{
|
|
break;
|
|
}
|
|
@@ -1536,6 +1891,12 @@
|
|
@SideOnly(Side.CLIENT)
|
|
public float getStarBrightness(float partialTicks)
|
|
{
|
|
+ return this.provider.getStarBrightness(partialTicks);
|
|
+ }
|
|
+
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public float getStarBrightnessBody(float partialTicks)
|
|
+ {
|
|
float f = this.getCelestialAngle(partialTicks);
|
|
float f1 = 1.0F - (MathHelper.cos(f * ((float)Math.PI * 2F)) * 2.0F + 0.25F);
|
|
f1 = MathHelper.clamp(f1, 0.0F, 1.0F);
|
|
@@ -1567,9 +1928,14 @@
|
|
for (int i = 0; i < this.weatherEffects.size(); ++i)
|
|
{
|
|
Entity entity = this.weatherEffects.get(i);
|
|
-
|
|
+ // CraftBukkit start - Fixed an NPE
|
|
+ if (entity == null) {
|
|
+ continue;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
try
|
|
{
|
|
+ if(entity.updateBlocked) continue;
|
|
++entity.ticksExisted;
|
|
entity.onUpdate();
|
|
}
|
|
@@ -1587,6 +1953,12 @@
|
|
entity.addEntityCrashInfo(crashreportcategory);
|
|
}
|
|
|
|
+ if (net.minecraftforge.common.ForgeModContainer.removeErroringEntities)
|
|
+ {
|
|
+ net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport.getCompleteReport());
|
|
+ removeEntity(entity);
|
|
+ }
|
|
+ else
|
|
throw new ReportedException(crashreport);
|
|
}
|
|
|
|
@@ -1620,9 +1992,20 @@
|
|
this.tickPlayers();
|
|
this.profiler.endStartSection("regular");
|
|
|
|
- for (int i1 = 0; i1 < this.loadedEntityList.size(); ++i1)
|
|
- {
|
|
- Entity entity2 = this.loadedEntityList.get(i1);
|
|
+ org.spigotmc.ActivationRange.activateEntities(this); // Spigot
|
|
+ timings.entityTick.startTiming(); // Spigot
|
|
+ { // CatServer - Dont break asm
|
|
+ // CraftBukkit start - Use field for loop variable
|
|
+ int entitiesThisCycle = 0;
|
|
+ if (tickPosition < 0) tickPosition = 0;
|
|
+ for ( entityLimiter.initTick();
|
|
+ entitiesThisCycle < loadedEntityList.size() && (entitiesThisCycle % 10 != 0 || entityLimiter.shouldContinue());
|
|
+ tickPosition++, entitiesThisCycle++) {
|
|
+ if (catserver.server.WorldTickSkipManager.shouldSkipWorldEntityTick && playerEntities.size() == 0) continue; // CatServer - Don't update Entity for no player world
|
|
+ tickPosition = (tickPosition < loadedEntityList.size()) ? tickPosition : 0;
|
|
+ Entity entity2 = (Entity) this.loadedEntityList.get(this.tickPosition);
|
|
+ // CraftBukkit end
|
|
+ if (catserver.server.WorldTickSkipManager.shouldSkipEntity && entity2.skipTick) continue; // CatServer
|
|
Entity entity3 = entity2.getRidingEntity();
|
|
|
|
if (entity3 != null)
|
|
@@ -1641,13 +2024,25 @@
|
|
{
|
|
try
|
|
{
|
|
+ SpigotTimings.tickEntityTimer.startTiming(); // Spigot
|
|
+ net.minecraftforge.server.timings.TimeTracker.ENTITY_UPDATE.trackStart(entity2);
|
|
+ catserver.server.command.internal.CommandChunkStats.onTickStart();
|
|
this.updateEntity(entity2);
|
|
+ catserver.server.command.internal.CommandChunkStats.onTickEnd(this, entity2.getPosition());
|
|
+ net.minecraftforge.server.timings.TimeTracker.ENTITY_UPDATE.trackEnd(entity2);
|
|
+ SpigotTimings.tickEntityTimer.stopTiming(); // Spigot
|
|
}
|
|
catch (Throwable throwable1)
|
|
{
|
|
CrashReport crashreport1 = CrashReport.makeCrashReport(throwable1, "Ticking entity");
|
|
CrashReportCategory crashreportcategory1 = crashreport1.makeCategory("Entity being ticked");
|
|
entity2.addEntityCrashInfo(crashreportcategory1);
|
|
+ if (net.minecraftforge.common.ForgeModContainer.removeErroringEntities)
|
|
+ {
|
|
+ net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport1.getCompleteReport());
|
|
+ removeEntity(entity2);
|
|
+ }
|
|
+ else
|
|
throw new ReportedException(crashreport1);
|
|
}
|
|
}
|
|
@@ -1665,34 +2060,59 @@
|
|
this.getChunkFromChunkCoords(l1, i2).removeEntity(entity2);
|
|
}
|
|
|
|
- this.loadedEntityList.remove(i1--);
|
|
+ this.loadedEntityList.remove(this.tickPosition--); // CraftBukkit - Use field for loop variable
|
|
this.onEntityRemoved(entity2);
|
|
}
|
|
|
|
this.profiler.endSection();
|
|
}
|
|
+ } // CatServer - Dont break asm
|
|
|
|
+ timings.entityTick.stopTiming(); // Spigot
|
|
this.profiler.endStartSection("blockEntities");
|
|
+ timings.tileEntityTick.startTiming(); // Spigot
|
|
|
|
+ this.processingLoadedTiles = true; //FML Move above remove to prevent CMEs
|
|
+
|
|
if (!this.tileEntitiesToBeRemoved.isEmpty())
|
|
{
|
|
- this.tickableTileEntities.removeAll(this.tileEntitiesToBeRemoved);
|
|
- this.loadedTileEntityList.removeAll(this.tileEntitiesToBeRemoved);
|
|
+ for (Object tile : tileEntitiesToBeRemoved)
|
|
+ {
|
|
+ ((TileEntity)tile).onChunkUnload();
|
|
+ }
|
|
+
|
|
+ // forge: faster "contains" makes this removal much more efficient
|
|
+ java.util.Set<TileEntity> remove = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap<>());
|
|
+ remove.addAll(tileEntitiesToBeRemoved);
|
|
+ this.tickableTileEntities.removeAll(remove);
|
|
+ this.loadedTileEntityList.removeAll(remove);
|
|
this.tileEntitiesToBeRemoved.clear();
|
|
}
|
|
|
|
- this.processingLoadedTiles = true;
|
|
- Iterator<TileEntity> iterator = this.tickableTileEntities.iterator();
|
|
+ // Iterator<TileEntity> iterator = this.tickableTileEntities.iterator();
|
|
+ Iterator<TileEntity> iterator = this.tickableTileEntities.iterator(); // The code is no used, but do not remove, if remove will asm boom
|
|
|
|
- while (iterator.hasNext())
|
|
- {
|
|
- TileEntity tileentity = iterator.next();
|
|
-
|
|
+ { // CatServer - Dont break asm
|
|
+ tilesThisCycle = 0; // CatServer - reset value
|
|
+ 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.hasWorld())
|
|
{
|
|
+ if (catserver.server.WorldTickSkipManager.shouldSkipTileEntity && tileentity.skipTick) continue; // CatServer
|
|
BlockPos blockpos = tileentity.getPos();
|
|
|
|
- if (this.isBlockLoaded(blockpos) && this.worldBorder.contains(blockpos))
|
|
+ if (this.isBlockLoaded(blockpos, false) && this.worldBorder.contains(blockpos)) //Forge: Fix TE's getting an extra tick on the client side....
|
|
{
|
|
try
|
|
{
|
|
@@ -1700,7 +2120,12 @@
|
|
{
|
|
return String.valueOf((Object)TileEntity.getKey(tileentity.getClass()));
|
|
});
|
|
+ tileentity.tickTimer.startTiming(); // Spigot
|
|
+ net.minecraftforge.server.timings.TimeTracker.TILE_ENTITY_UPDATE.trackStart(tileentity);
|
|
+ catserver.server.command.internal.CommandChunkStats.onTickStart();
|
|
((ITickable)tileentity).update();
|
|
+ catserver.server.command.internal.CommandChunkStats.onTickEnd(this, tileentity.getPos());
|
|
+ net.minecraftforge.server.timings.TimeTracker.TILE_ENTITY_UPDATE.trackEnd(tileentity);
|
|
this.profiler.endSection();
|
|
}
|
|
catch (Throwable throwable)
|
|
@@ -1708,23 +2133,43 @@
|
|
CrashReport crashreport2 = CrashReport.makeCrashReport(throwable, "Ticking block entity");
|
|
CrashReportCategory crashreportcategory2 = crashreport2.makeCategory("Block entity being ticked");
|
|
tileentity.addInfoToCrashReport(crashreportcategory2);
|
|
+ if (net.minecraftforge.common.ForgeModContainer.removeErroringTileEntities)
|
|
+ {
|
|
+ net.minecraftforge.fml.common.FMLLog.log.fatal("{}", crashreport2.getCompleteReport());
|
|
+ tileentity.invalidate();
|
|
+ this.removeTileEntity(tileentity.getPos());
|
|
+ }
|
|
+ else
|
|
throw new ReportedException(crashreport2);
|
|
}
|
|
+ // Spigot start
|
|
+ finally {
|
|
+ tileentity.tickTimer.stopTiming();
|
|
+ }
|
|
+ // Spigot end
|
|
+
|
|
}
|
|
}
|
|
|
|
if (tileentity.isInvalid())
|
|
{
|
|
- iterator.remove();
|
|
+ tilesThisCycle--;
|
|
+ this.tickableTileEntities.remove(tileTickPosition--);
|
|
this.loadedTileEntityList.remove(tileentity);
|
|
|
|
if (this.isBlockLoaded(tileentity.getPos()))
|
|
{
|
|
- this.getChunkFromBlockCoords(tileentity.getPos()).removeTileEntity(tileentity.getPos());
|
|
+ //Forge: Bugfix: If we set the tile entity it immediately sets it in the chunk, so we could be desyned
|
|
+ Chunk chunk = this.getChunkFromBlockCoords(tileentity.getPos());
|
|
+ if (chunk.getTileEntity(tileentity.getPos(), Chunk.EnumCreateEntityType.CHECK) == tileentity)
|
|
+ chunk.removeTileEntity(tileentity.getPos());
|
|
}
|
|
}
|
|
}
|
|
+ } // CatServer - Dont break asm
|
|
|
|
+ timings.tileEntityTick.stopTiming(); // Spigot
|
|
+ timings.tileEntityPending.startTiming(); // Spigot
|
|
this.processingLoadedTiles = false;
|
|
this.profiler.endStartSection("pendingBlockEntities");
|
|
|
|
@@ -1736,10 +2181,12 @@
|
|
|
|
if (!tileentity1.isInvalid())
|
|
{
|
|
+ /* CraftBukkit start - Order matters, moved down
|
|
if (!this.loadedTileEntityList.contains(tileentity1))
|
|
{
|
|
this.addTileEntity(tileentity1);
|
|
}
|
|
+ // CraftBukkit end */
|
|
|
|
if (this.isBlockLoaded(tileentity1.getPos()))
|
|
{
|
|
@@ -1747,6 +2194,12 @@
|
|
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
|
|
}
|
|
}
|
|
}
|
|
@@ -1754,6 +2207,7 @@
|
|
this.addedTileEntityList.clear();
|
|
}
|
|
|
|
+ timings.tileEntityPending.stopTiming(); // Spigot
|
|
this.profiler.endSection();
|
|
this.profiler.endSection();
|
|
}
|
|
@@ -1764,12 +2218,18 @@
|
|
|
|
public boolean addTileEntity(TileEntity tile)
|
|
{
|
|
+ // Forge - set the world early as vanilla doesn't set it until next tick
|
|
+ if (tile.getWorld() != this) tile.setWorld(this);
|
|
+ // Forge: wait to add new TE if we're currently processing existing ones
|
|
+ if (processingLoadedTiles) return addedTileEntityList.add(tile);
|
|
+
|
|
boolean flag = this.loadedTileEntityList.add(tile);
|
|
|
|
if (flag && tile instanceof ITickable)
|
|
{
|
|
this.tickableTileEntities.add(tile);
|
|
}
|
|
+ tile.onLoad();
|
|
|
|
if (this.isRemote)
|
|
{
|
|
@@ -1785,6 +2245,11 @@
|
|
{
|
|
if (this.processingLoadedTiles)
|
|
{
|
|
+ for (TileEntity te : tileEntityCollection)
|
|
+ {
|
|
+ if (te.getWorld() != this) // Forge - set the world early as vanilla doesn't set it until next tick
|
|
+ te.setWorld(this);
|
|
+ }
|
|
this.addedTileEntityList.addAll(tileEntityCollection);
|
|
}
|
|
else
|
|
@@ -1807,14 +2272,26 @@
|
|
{
|
|
int j2 = MathHelper.floor(entityIn.posX);
|
|
int k2 = MathHelper.floor(entityIn.posZ);
|
|
- int l2 = 32;
|
|
|
|
- if (forceUpdate && !this.isAreaLoaded(j2 - 32, 0, k2 - 32, j2 + 32, 0, k2 + 32, true))
|
|
+ boolean isForced = !this.isRemote && getPersistentChunks().containsKey(new net.minecraft.util.math.ChunkPos(j2 >> 4, k2 >> 4));
|
|
+ int range = isForced ? 0 : 32;
|
|
+ boolean canUpdate = !forceUpdate || this.isAreaLoaded(j2 - range, 0, k2 - range, j2 + range, 0, k2 + range, true);
|
|
+ if (!canUpdate) canUpdate = net.minecraftforge.event.ForgeEventFactory.canEntityUpdate(entityIn);
|
|
+
|
|
+ if (!canUpdate)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ // Spigot start
|
|
+ if (forceUpdate && !org.spigotmc.ActivationRange.checkIfActive(entityIn)) {
|
|
+ entityIn.ticksExisted++;
|
|
+ entityIn.inactiveTick();
|
|
+ return;
|
|
+ }
|
|
+ // Spigot end
|
|
+
|
|
entityIn.lastTickPosX = entityIn.posX;
|
|
entityIn.lastTickPosY = entityIn.posY;
|
|
entityIn.lastTickPosZ = entityIn.posZ;
|
|
@@ -1831,7 +2308,9 @@
|
|
}
|
|
else
|
|
{
|
|
+ if(!entityIn.updateBlocked)
|
|
entityIn.onUpdate();
|
|
+ entityIn.postTick();
|
|
}
|
|
}
|
|
|
|
@@ -1914,7 +2393,7 @@
|
|
{
|
|
Entity entity4 = list.get(j2);
|
|
|
|
- if (!entity4.isDead && entity4.preventEntitySpawning && entity4 != entityIn && (entityIn == null || entity4.isRidingSameEntity(entityIn)))
|
|
+ if (!entity4.isDead && entity4.preventEntitySpawning && entity4 != entityIn && (entityIn == null || !entity4.isRidingSameEntity(entityIn))) // Forge: fix MC-103516
|
|
{
|
|
return false;
|
|
}
|
|
@@ -1972,6 +2451,12 @@
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4));
|
|
|
|
+ Boolean result = iblockstate1.getBlock().isAABBInsideLiquid(this, blockpos$pooledmutableblockpos, bb);
|
|
+ if (result != null) {
|
|
+ if (!result) continue;
|
|
+ blockpos$pooledmutableblockpos.release();
|
|
+ return true;
|
|
+ }
|
|
if (iblockstate1.getMaterial().isLiquid())
|
|
{
|
|
blockpos$pooledmutableblockpos.release();
|
|
@@ -2011,6 +2496,11 @@
|
|
blockpos$pooledmutableblockpos.release();
|
|
return true;
|
|
}
|
|
+ else if (block.isBurning(this, new BlockPos(l3, i4, j4)))
|
|
+ {
|
|
+ blockpos$pooledmutableblockpos.release();
|
|
+ return true;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -2050,6 +2540,16 @@
|
|
IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos);
|
|
Block block = iblockstate1.getBlock();
|
|
|
|
+ Boolean result = block.isEntityInsideMaterial(this, blockpos$pooledmutableblockpos, iblockstate1, entityIn, (double)i3, materialIn, false);
|
|
+ if (result != null && result == true)
|
|
+ {
|
|
+ // Forge: When requested call blocks modifyAcceleration method, and more importantly cause this method to return true, which results in an entity being "inWater"
|
|
+ flag = true;
|
|
+ vec3d = block.modifyAcceleration(this, blockpos$pooledmutableblockpos, entityIn, vec3d);
|
|
+ continue;
|
|
+ }
|
|
+ else if (result != null && result == false) continue;
|
|
+
|
|
if (iblockstate1.getMaterial() == materialIn)
|
|
{
|
|
double d0 = (double)((float)(i4 + 1) - BlockLiquid.getLiquidHeightPercent(((Integer)iblockstate1.getValue(BlockLiquid.LEVEL)).intValue()));
|
|
@@ -2095,7 +2595,14 @@
|
|
{
|
|
for (int j4 = j3; j4 < k3; ++j4)
|
|
{
|
|
- if (this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4)).getMaterial() == materialIn)
|
|
+ IBlockState iblockstate1 = this.getBlockState(blockpos$pooledmutableblockpos.setPos(l3, i4, j4));
|
|
+ Boolean result = iblockstate1.getBlock().isAABBInsideMaterial(this, blockpos$pooledmutableblockpos, bb, materialIn);
|
|
+ if (result != null) {
|
|
+ if (!result) continue;
|
|
+ blockpos$pooledmutableblockpos.release();
|
|
+ return true;
|
|
+ }
|
|
+ if (iblockstate1.getMaterial() == materialIn)
|
|
{
|
|
blockpos$pooledmutableblockpos.release();
|
|
return true;
|
|
@@ -2116,6 +2623,7 @@
|
|
public Explosion newExplosion(@Nullable Entity entityIn, double x, double y, double z, float strength, boolean isFlaming, boolean isSmoking)
|
|
{
|
|
Explosion explosion = new Explosion(this, entityIn, x, y, z, strength, isFlaming, isSmoking);
|
|
+ if (net.minecraftforge.event.ForgeEventFactory.onExplosionStart(this, explosion)) return explosion;
|
|
explosion.doExplosionA();
|
|
explosion.doExplosionB(true);
|
|
return explosion;
|
|
@@ -2206,7 +2714,7 @@
|
|
tileentity2 = this.getPendingTileEntityAt(pos);
|
|
}
|
|
|
|
- if (tileentity2 == null)
|
|
+ if (tileentity2 == null && (!catserver.server.CatServer.getConfig().preventBlockLoadChunk || isBlockLoaded(pos)))
|
|
{
|
|
tileentity2 = this.getChunkFromBlockCoords(pos).getTileEntity(pos, Chunk.EnumCreateEntityType.IMMEDIATE);
|
|
}
|
|
@@ -2238,6 +2746,7 @@
|
|
|
|
public void setTileEntity(BlockPos pos, @Nullable TileEntity tileEntityIn)
|
|
{
|
|
+ pos = pos.toImmutable(); // Forge - prevent mutable BlockPos leaks
|
|
if (!this.isOutsideBuildHeight(pos))
|
|
{
|
|
if (tileEntityIn != null && !tileEntityIn.isInvalid())
|
|
@@ -2245,7 +2754,10 @@
|
|
if (this.processingLoadedTiles)
|
|
{
|
|
tileEntityIn.setPos(pos);
|
|
+ if (tileEntityIn.getWorld() != this)
|
|
+ tileEntityIn.setWorld(this); // Forge - set the world early as vanilla doesn't set it until next tick
|
|
Iterator<TileEntity> iterator1 = this.addedTileEntityList.iterator();
|
|
+ List<TileEntity> toInvalidate = Lists.newArrayList();
|
|
|
|
while (iterator1.hasNext())
|
|
{
|
|
@@ -2253,16 +2765,19 @@
|
|
|
|
if (tileentity2.getPos().equals(pos))
|
|
{
|
|
- tileentity2.invalidate();
|
|
+ toInvalidate.add(tileentity2); // Forge - don't call invalidate while iterating
|
|
iterator1.remove();
|
|
}
|
|
}
|
|
|
|
+ tileEntityIn.setWorld(this); // Spigot - No null worlds
|
|
+ toInvalidate.forEach(TileEntity::invalidate);
|
|
this.addedTileEntityList.add(tileEntityIn);
|
|
}
|
|
else
|
|
{
|
|
- this.getChunkFromBlockCoords(pos).addTileEntity(pos, tileEntityIn);
|
|
+ Chunk chunk = this.getChunkFromBlockCoords(pos);
|
|
+ if (chunk != null) chunk.addTileEntity(pos, tileEntityIn);
|
|
this.addTileEntity(tileEntityIn);
|
|
}
|
|
}
|
|
@@ -2277,6 +2792,8 @@
|
|
{
|
|
tileentity2.invalidate();
|
|
this.addedTileEntityList.remove(tileentity2);
|
|
+ if (!(tileentity2 instanceof ITickable)) //Forge: If they are not tickable they wont be removed in the update loop.
|
|
+ this.loadedTileEntityList.remove(tileentity2);
|
|
}
|
|
else
|
|
{
|
|
@@ -2289,6 +2806,7 @@
|
|
|
|
this.getChunkFromBlockCoords(pos).removeTileEntity(pos);
|
|
}
|
|
+ this.updateComparatorOutputLevel(pos, getBlockState(pos).getBlock()); //Notify neighbors of changes
|
|
}
|
|
|
|
public void markTileEntityForRemoval(TileEntity tileEntityIn)
|
|
@@ -2315,7 +2833,7 @@
|
|
if (chunk1 != null && !chunk1.isEmpty())
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(pos);
|
|
- return iblockstate1.getMaterial().isOpaque() && iblockstate1.isFullCube();
|
|
+ return iblockstate1.getBlock().isNormalCube(iblockstate1, this, pos);
|
|
}
|
|
else
|
|
{
|
|
@@ -2338,6 +2856,7 @@
|
|
{
|
|
this.spawnHostileMobs = hostile;
|
|
this.spawnPeacefulMobs = peaceful;
|
|
+ this.provider.setAllowedSpawnTypes(hostile, peaceful);
|
|
}
|
|
|
|
public void tick()
|
|
@@ -2347,6 +2866,11 @@
|
|
|
|
protected void calculateInitialWeather()
|
|
{
|
|
+ this.provider.calculateInitialWeather();
|
|
+ }
|
|
+
|
|
+ public void calculateInitialWeatherBody()
|
|
+ {
|
|
if (this.worldInfo.isRaining())
|
|
{
|
|
this.rainingStrength = 1.0F;
|
|
@@ -2360,6 +2884,11 @@
|
|
|
|
protected void updateWeather()
|
|
{
|
|
+ this.provider.updateWeather();
|
|
+ }
|
|
+
|
|
+ public void updateWeatherBody()
|
|
+ {
|
|
if (this.provider.hasSkyLight())
|
|
{
|
|
if (!this.isRemote)
|
|
@@ -2451,6 +2980,11 @@
|
|
}
|
|
|
|
this.rainingStrength = MathHelper.clamp(this.rainingStrength, 0.0F, 1.0F);
|
|
+ for (int idx = 0; idx < this.playerEntities.size(); ++idx) {
|
|
+ if (((EntityPlayerMP) this.playerEntities.get(idx)).world == this) {
|
|
+ ((EntityPlayerMP) this.playerEntities.get(idx)).tickWeather();
|
|
+ }
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -2484,6 +3018,11 @@
|
|
|
|
public boolean canBlockFreeze(BlockPos pos, boolean noWaterAdj)
|
|
{
|
|
+ return this.provider.canBlockFreeze(pos, noWaterAdj);
|
|
+ }
|
|
+
|
|
+ public boolean canBlockFreezeBody(BlockPos pos, boolean noWaterAdj)
|
|
+ {
|
|
Biome biome = this.getBiome(pos);
|
|
float f = biome.getTemperature(pos);
|
|
|
|
@@ -2525,6 +3064,11 @@
|
|
|
|
public boolean canSnowAt(BlockPos pos, boolean checkLight)
|
|
{
|
|
+ return this.provider.canSnowAt(pos, checkLight);
|
|
+ }
|
|
+
|
|
+ public boolean canSnowAtBody(BlockPos pos, boolean checkLight)
|
|
+ {
|
|
Biome biome = this.getBiome(pos);
|
|
float f = biome.getTemperature(pos);
|
|
|
|
@@ -2542,7 +3086,7 @@
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(pos);
|
|
|
|
- if (iblockstate1.getMaterial() == Material.AIR && Blocks.SNOW_LAYER.canPlaceBlockAt(this, pos))
|
|
+ if (iblockstate1.getBlock().isAir(iblockstate1, this, pos) && Blocks.SNOW_LAYER.canPlaceBlockAt(this, pos))
|
|
{
|
|
return true;
|
|
}
|
|
@@ -2574,10 +3118,10 @@
|
|
else
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(pos);
|
|
- int j2 = lightType == EnumSkyBlock.SKY ? 0 : iblockstate1.getLightValue();
|
|
- int k2 = iblockstate1.getLightOpacity();
|
|
+ int j2 = lightType == EnumSkyBlock.SKY ? 0 : iblockstate1.getBlock().getLightValue(iblockstate1, this, pos);
|
|
+ int k2 = iblockstate1.getBlock().getLightOpacity(iblockstate1, this, pos);
|
|
|
|
- if (k2 >= 15 && iblockstate1.getLightValue() > 0)
|
|
+ if (false) // Forge: fix MC-119932
|
|
{
|
|
k2 = 1;
|
|
}
|
|
@@ -2589,7 +3133,7 @@
|
|
|
|
if (k2 >= 15)
|
|
{
|
|
- return 0;
|
|
+ return j2; // Forge: fix MC-119932
|
|
}
|
|
else if (j2 >= 14)
|
|
{
|
|
@@ -2630,12 +3174,16 @@
|
|
|
|
public boolean checkLightFor(EnumSkyBlock lightType, BlockPos pos)
|
|
{
|
|
- 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.isAreaLoaded(pos, 16, false)*/)
|
|
{
|
|
+ // CraftBukkit end
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
+ int updateRange = this.isAreaLoaded(pos, 18, false) ? 17 : 15;
|
|
int j2 = 0;
|
|
int k2 = 0;
|
|
this.profiler.startSection("getBrightness");
|
|
@@ -2673,7 +3221,7 @@
|
|
int l5 = MathHelper.abs(k4 - k3);
|
|
int i6 = MathHelper.abs(l4 - l3);
|
|
|
|
- if (k5 + l5 + i6 < 17)
|
|
+ if (k5 + l5 + i6 < updateRange)
|
|
{
|
|
BlockPos.PooledMutableBlockPos blockpos$pooledmutableblockpos = BlockPos.PooledMutableBlockPos.retain();
|
|
|
|
@@ -2683,7 +3231,8 @@
|
|
int k6 = k4 + enumfacing.getFrontOffsetY();
|
|
int l6 = l4 + enumfacing.getFrontOffsetZ();
|
|
blockpos$pooledmutableblockpos.setPos(j6, k6, l6);
|
|
- int i7 = Math.max(1, this.getBlockState(blockpos$pooledmutableblockpos).getLightOpacity());
|
|
+ IBlockState bs = this.getBlockState(blockpos$pooledmutableblockpos);
|
|
+ int i7 = Math.max(1, bs.getBlock().getLightOpacity(bs, this, blockpos$pooledmutableblockpos));
|
|
j5 = this.getLightFor(lightType, blockpos$pooledmutableblockpos);
|
|
|
|
if (j5 == i5 - i7 && k2 < this.lightUpdateBlockList.length)
|
|
@@ -2725,7 +3274,7 @@
|
|
int j9 = Math.abs(i8 - l3);
|
|
boolean flag = k2 < this.lightUpdateBlockList.length - 6;
|
|
|
|
- if (l8 + i9 + j9 < 17 && flag)
|
|
+ if (l8 + i9 + j9 < updateRange && flag)
|
|
{
|
|
if (this.getLightFor(lightType, blockpos2.west()) < k8)
|
|
{
|
|
@@ -2791,10 +3340,10 @@
|
|
public List<Entity> getEntitiesInAABBexcluding(@Nullable Entity entityIn, AxisAlignedBB boundingBox, @Nullable Predicate <? super Entity > predicate)
|
|
{
|
|
List<Entity> list = Lists.<Entity>newArrayList();
|
|
- int j2 = MathHelper.floor((boundingBox.minX - 2.0D) / 16.0D);
|
|
- int k2 = MathHelper.floor((boundingBox.maxX + 2.0D) / 16.0D);
|
|
- int l2 = MathHelper.floor((boundingBox.minZ - 2.0D) / 16.0D);
|
|
- int i3 = MathHelper.floor((boundingBox.maxZ + 2.0D) / 16.0D);
|
|
+ int j2 = MathHelper.floor((boundingBox.minX - MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int k2 = MathHelper.floor((boundingBox.maxX + MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int l2 = MathHelper.floor((boundingBox.minZ - MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int i3 = MathHelper.floor((boundingBox.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
|
|
|
|
for (int j3 = j2; j3 <= k2; ++j3)
|
|
{
|
|
@@ -2847,10 +3396,10 @@
|
|
|
|
public <T extends Entity> List<T> getEntitiesWithinAABB(Class <? extends T > clazz, AxisAlignedBB aabb, @Nullable Predicate <? super T > filter)
|
|
{
|
|
- int j2 = MathHelper.floor((aabb.minX - 2.0D) / 16.0D);
|
|
- int k2 = MathHelper.ceil((aabb.maxX + 2.0D) / 16.0D);
|
|
- int l2 = MathHelper.floor((aabb.minZ - 2.0D) / 16.0D);
|
|
- int i3 = MathHelper.ceil((aabb.maxZ + 2.0D) / 16.0D);
|
|
+ int j2 = MathHelper.floor((aabb.minX - MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int k2 = MathHelper.ceil((aabb.maxX + MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int l2 = MathHelper.floor((aabb.minZ - MAX_ENTITY_RADIUS) / 16.0D);
|
|
+ int i3 = MathHelper.ceil((aabb.maxZ + MAX_ENTITY_RADIUS) / 16.0D);
|
|
List<T> list = Lists.<T>newArrayList();
|
|
|
|
for (int j3 = j2; j3 < k2; ++j3)
|
|
@@ -2919,7 +3468,16 @@
|
|
|
|
for (Entity entity4 : this.loadedEntityList)
|
|
{
|
|
- if ((!(entity4 instanceof EntityLiving) || !((EntityLiving)entity4).isNoDespawnRequired()) && entityType.isAssignableFrom(entity4.getClass()))
|
|
+ // CraftBukkit start - Split out persistent check, don't apply it to special persistent mobs
|
|
+ if (entity4 instanceof EntityLiving) {
|
|
+ EntityLiving entityinsentient = (EntityLiving) entity4;
|
|
+ if (entityinsentient.canDespawn() && entityinsentient.isNoDespawnRequired()) {
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // if ((!(entity4 instanceof EntityLiving) || !((EntityLiving)entity4).isNoDespawnRequired()) && entityType.isAssignableFrom(entity4.getClass()))
|
|
+ if (entityType.isAssignableFrom(entity4.getClass()))
|
|
{
|
|
++j2;
|
|
}
|
|
@@ -2930,11 +3488,17 @@
|
|
|
|
public void loadEntities(Collection<Entity> entityCollection)
|
|
{
|
|
- this.loadedEntityList.addAll(entityCollection);
|
|
-
|
|
+ if (catserver.server.AsyncCatcher.checkAsync("load entities")) { catserver.server.AsyncCatcher.ensureExecuteOnPrimaryThread(() -> loadEntities(entityCollection)); return; } // CatServer
|
|
for (Entity entity4 : entityCollection)
|
|
{
|
|
- this.onEntityAdded(entity4);
|
|
+ if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entity4, this)))
|
|
+ {
|
|
+ if (entity4 == null) {
|
|
+ continue;
|
|
+ }
|
|
+ loadedEntityList.add(entity4);
|
|
+ this.onEntityAdded(entity4);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -2948,18 +3512,24 @@
|
|
IBlockState iblockstate1 = this.getBlockState(pos);
|
|
AxisAlignedBB axisalignedbb = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionBoundingBox(this, pos);
|
|
|
|
- if (axisalignedbb != Block.NULL_AABB && !this.checkNoEntityCollision(axisalignedbb.offset(pos), placer))
|
|
+ if (!((placer instanceof EntityPlayer) || !net.minecraftforge.event.ForgeEventFactory.onBlockPlace(placer, new net.minecraftforge.common.util.BlockSnapshot(this, pos, blockIn.getDefaultState()), sidePlacedOn).isCanceled())) return false;
|
|
+ boolean defaultReturn;
|
|
+ if (axisalignedbb != Block.NULL_AABB && !this.checkNoEntityCollision(axisalignedbb.offset(pos))) // Forge: Remove second parameter, we patch placer to be non-null, passing it here skips collision checks for the placer
|
|
{
|
|
- return false;
|
|
+ defaultReturn = false;
|
|
}
|
|
else if (iblockstate1.getMaterial() == Material.CIRCUITS && blockIn == Blocks.ANVIL)
|
|
{
|
|
- return true;
|
|
+ defaultReturn = true;
|
|
}
|
|
else
|
|
{
|
|
- return iblockstate1.getMaterial().isReplaceable() && blockIn.canPlaceBlockOnSide(this, pos, sidePlacedOn);
|
|
+ defaultReturn = iblockstate1.getBlock().isReplaceable(this, pos) && blockIn.canPlaceBlockOnSide(this, pos, sidePlacedOn);
|
|
}
|
|
+ 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();
|
|
}
|
|
|
|
public int getSeaLevel()
|
|
@@ -3042,7 +3612,7 @@
|
|
public int getRedstonePower(BlockPos pos, EnumFacing facing)
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(pos);
|
|
- return iblockstate1.isNormalCube() ? this.getStrongPower(pos) : iblockstate1.getWeakPower(this, pos, facing);
|
|
+ return iblockstate1.getBlock().shouldCheckWeakPower(iblockstate1, this, pos, facing) ? this.getStrongPower(pos) : iblockstate1.getWeakPower(this, pos, facing);
|
|
}
|
|
|
|
public boolean isBlockPowered(BlockPos pos)
|
|
@@ -3124,6 +3694,12 @@
|
|
{
|
|
EntityPlayer entityplayer1 = this.playerEntities.get(j2);
|
|
|
|
+ // CraftBukkit start - Fixed an NPE
|
|
+ if (entityplayer1 == null || entityplayer1.isDead) {
|
|
+ continue;
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
if (p_190525_9_.apply(entityplayer1))
|
|
{
|
|
double d1 = entityplayer1.getDistanceSq(x, y, z);
|
|
@@ -3208,6 +3784,8 @@
|
|
d2 *= ((Double)MoreObjects.firstNonNull(playerToDouble.apply(entityplayer1), Double.valueOf(1.0D))).doubleValue();
|
|
}
|
|
|
|
+ d2 = net.minecraftforge.common.ForgeHooks.getPlayerVisibilityDistance(entityplayer1, d2, maxYDistance);
|
|
+
|
|
if ((maxYDistance < 0.0D || Math.abs(entityplayer1.posY - posY) < maxYDistance * maxYDistance) && (maxXZDistance < 0.0D || d1 < d2 * d2) && (d0 == -1.0D || d1 < d0))
|
|
{
|
|
d0 = d1;
|
|
@@ -3269,7 +3847,7 @@
|
|
|
|
public long getSeed()
|
|
{
|
|
- return this.worldInfo.getSeed();
|
|
+ return this.provider.getSeed();
|
|
}
|
|
|
|
public long getTotalWorldTime()
|
|
@@ -3279,17 +3857,17 @@
|
|
|
|
public long getWorldTime()
|
|
{
|
|
- return this.worldInfo.getWorldTime();
|
|
+ return this.provider.getWorldTime();
|
|
}
|
|
|
|
public void setWorldTime(long time)
|
|
{
|
|
- this.worldInfo.setWorldTime(time);
|
|
+ this.provider.setWorldTime(time);
|
|
}
|
|
|
|
public BlockPos getSpawnPoint()
|
|
{
|
|
- BlockPos blockpos1 = new BlockPos(this.worldInfo.getSpawnX(), this.worldInfo.getSpawnY(), this.worldInfo.getSpawnZ());
|
|
+ BlockPos blockpos1 = this.provider.getSpawnPoint();
|
|
|
|
if (!this.getWorldBorder().contains(blockpos1))
|
|
{
|
|
@@ -3301,7 +3879,7 @@
|
|
|
|
public void setSpawnPoint(BlockPos pos)
|
|
{
|
|
- this.worldInfo.setSpawn(pos);
|
|
+ this.provider.setSpawnPoint(pos);
|
|
}
|
|
|
|
@SideOnly(Side.CLIENT)
|
|
@@ -3321,12 +3899,18 @@
|
|
|
|
if (!this.loadedEntityList.contains(entityIn))
|
|
{
|
|
+ if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entityIn, this)))
|
|
this.loadedEntityList.add(entityIn);
|
|
}
|
|
}
|
|
|
|
public boolean isBlockModifiable(EntityPlayer player, BlockPos pos)
|
|
{
|
|
+ return this.provider.canMineBlock(player, pos);
|
|
+ }
|
|
+
|
|
+ public boolean canMineBlockBody(EntityPlayer player, BlockPos pos)
|
|
+ {
|
|
return true;
|
|
}
|
|
|
|
@@ -3363,6 +3947,16 @@
|
|
{
|
|
}
|
|
|
|
+ // 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)
|
|
{
|
|
return (this.prevThunderingStrength + (this.thunderingStrength - this.prevThunderingStrength) * delta) * this.getRainStrength(delta);
|
|
@@ -3428,8 +4022,7 @@
|
|
|
|
public boolean isBlockinHighHumidity(BlockPos pos)
|
|
{
|
|
- Biome biome = this.getBiome(pos);
|
|
- return biome.isHighHumidity();
|
|
+ return this.provider.isBlockHighHumidity(pos);
|
|
}
|
|
|
|
@Nullable
|
|
@@ -3490,12 +4083,12 @@
|
|
|
|
public int getHeight()
|
|
{
|
|
- return 256;
|
|
+ return this.provider.getHeight();
|
|
}
|
|
|
|
public int getActualHeight()
|
|
{
|
|
- return this.provider.isNether() ? 128 : 256;
|
|
+ return this.provider.getActualHeight();
|
|
}
|
|
|
|
public Random setRandomSeed(int p_72843_1_, int p_72843_2_, int p_72843_3_)
|
|
@@ -3539,7 +4132,7 @@
|
|
@SideOnly(Side.CLIENT)
|
|
public double getHorizon()
|
|
{
|
|
- return this.worldInfo.getTerrainType() == WorldType.FLAT ? 0.0D : 63.0D;
|
|
+ return provider.getHorizon();
|
|
}
|
|
|
|
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress)
|
|
@@ -3573,7 +4166,7 @@
|
|
|
|
public void updateComparatorOutputLevel(BlockPos pos, Block blockIn)
|
|
{
|
|
- for (EnumFacing enumfacing : EnumFacing.Plane.HORIZONTAL)
|
|
+ for (EnumFacing enumfacing : EnumFacing.VALUES)
|
|
{
|
|
BlockPos blockpos1 = pos.offset(enumfacing);
|
|
|
|
@@ -3581,18 +4174,15 @@
|
|
{
|
|
IBlockState iblockstate1 = this.getBlockState(blockpos1);
|
|
|
|
- if (Blocks.UNPOWERED_COMPARATOR.isSameDiode(iblockstate1))
|
|
+ iblockstate1.getBlock().onNeighborChange(this, blockpos1, pos);
|
|
+ if (iblockstate1.getBlock().isNormalCube(iblockstate1, this, blockpos1))
|
|
{
|
|
- iblockstate1.neighborChanged(this, blockpos1, blockIn, pos);
|
|
- }
|
|
- else if (iblockstate1.isNormalCube())
|
|
- {
|
|
blockpos1 = blockpos1.offset(enumfacing);
|
|
iblockstate1 = this.getBlockState(blockpos1);
|
|
|
|
- if (Blocks.UNPOWERED_COMPARATOR.isSameDiode(iblockstate1))
|
|
+ if (iblockstate1.getBlock().getWeakChanges(this, blockpos1))
|
|
{
|
|
- iblockstate1.neighborChanged(this, blockpos1, blockIn, pos);
|
|
+ iblockstate1.getBlock().onNeighborChange(this, blockpos1, pos);
|
|
}
|
|
}
|
|
}
|
|
@@ -3655,9 +4245,127 @@
|
|
int j2 = x * 16 + 8 - blockpos1.getX();
|
|
int k2 = z * 16 + 8 - blockpos1.getZ();
|
|
int l2 = 128;
|
|
- return j2 >= -128 && j2 <= 128 && k2 >= -128 && k2 <= 128;
|
|
+ return j2 >= -128 && j2 <= 128 && k2 >= -128 && k2 <= 128 && this.keepSpawnInMemory;
|
|
}
|
|
|
|
+ /* ======================================== FORGE START =====================================*/
|
|
+ /**
|
|
+ * Determine if the given block is considered solid on the
|
|
+ * specified side. Used by placement logic.
|
|
+ *
|
|
+ * @param pos Block Position
|
|
+ * @param side The Side in question
|
|
+ * @return True if the side is solid
|
|
+ */
|
|
+ public boolean isSideSolid(BlockPos pos, EnumFacing side)
|
|
+ {
|
|
+ return isSideSolid(pos, side, false);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determine if the given block is considered solid on the
|
|
+ * specified side. Used by placement logic.
|
|
+ *
|
|
+ * @param pos Block Position
|
|
+ * @param side The Side in question
|
|
+ * @param _default The default to return if the block doesn't exist.
|
|
+ * @return True if the side is solid
|
|
+ */
|
|
+ @Override
|
|
+ public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default)
|
|
+ {
|
|
+ if (!this.isValid(pos)) return _default;
|
|
+
|
|
+ Chunk chunk = getChunkFromBlockCoords(pos);
|
|
+ if (chunk == null || chunk.isEmpty()) return _default;
|
|
+ return getBlockState(pos).isSideSolid(this, pos, side);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the persistent chunks for this world
|
|
+ *
|
|
+ * @return
|
|
+ */
|
|
+ public com.google.common.collect.ImmutableSetMultimap<net.minecraft.util.math.ChunkPos, net.minecraftforge.common.ForgeChunkManager.Ticket> getPersistentChunks()
|
|
+ {
|
|
+ return net.minecraftforge.common.ForgeChunkManager.getPersistentChunksFor(this);
|
|
+ }
|
|
+
|
|
+ public Iterator<Chunk> getPersistentChunkIterable(Iterator<Chunk> chunkIterator)
|
|
+ {
|
|
+ return net.minecraftforge.common.ForgeChunkManager.getPersistentChunksIterableFor(this, chunkIterator);
|
|
+ }
|
|
+ /**
|
|
+ * Readded as it was removed, very useful helper function
|
|
+ *
|
|
+ * @param pos Block position
|
|
+ * @return The blocks light opacity
|
|
+ */
|
|
+ public int getBlockLightOpacity(BlockPos pos)
|
|
+ {
|
|
+ if (!this.isValid(pos)) return 0;
|
|
+ return getChunkFromBlockCoords(pos).getBlockLightOpacity(pos);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns a count of entities that classify themselves as the specified creature type.
|
|
+ */
|
|
+ public int countEntities(net.minecraft.entity.EnumCreatureType type, boolean forSpawnCount)
|
|
+ {
|
|
+ int count = 0;
|
|
+ for (int x = 0; x < loadedEntityList.size(); x++)
|
|
+ {
|
|
+ if (((Entity)loadedEntityList.get(x)).isCreatureType(type, forSpawnCount))
|
|
+ {
|
|
+ count++;
|
|
+ }
|
|
+ }
|
|
+ return count;
|
|
+ }
|
|
+
|
|
+ @Deprecated // remove in 1.13
|
|
+ public void markTileEntitiesInChunkForRemoval(Chunk chunk)
|
|
+ {
|
|
+ for (TileEntity tileentity : chunk.getTileEntityMap().values())
|
|
+ {
|
|
+ markTileEntityForRemoval(tileentity);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ protected void initCapabilities()
|
|
+ {
|
|
+ net.minecraftforge.common.capabilities.ICapabilityProvider parent = provider.initCapabilities();
|
|
+ capabilities = net.minecraftforge.event.ForgeEventFactory.gatherCapabilities(this, parent);
|
|
+ net.minecraftforge.common.util.WorldCapabilityData data = (net.minecraftforge.common.util.WorldCapabilityData)perWorldStorage.getOrLoadData(net.minecraftforge.common.util.WorldCapabilityData.class, net.minecraftforge.common.util.WorldCapabilityData.ID);
|
|
+ if (data == null)
|
|
+ {
|
|
+ capabilityData = new net.minecraftforge.common.util.WorldCapabilityData(capabilities);
|
|
+ perWorldStorage.setData(capabilityData.mapName, capabilityData);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ capabilityData = data;
|
|
+ capabilityData.setCapabilities(provider, capabilities);
|
|
+ }
|
|
+ }
|
|
+ @Override
|
|
+ public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, @Nullable EnumFacing facing)
|
|
+ {
|
|
+ return capabilities == null ? false : capabilities.hasCapability(capability, facing);
|
|
+ }
|
|
+ @Override
|
|
+ @Nullable
|
|
+ public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, @Nullable EnumFacing facing)
|
|
+ {
|
|
+ return capabilities == null ? null : capabilities.getCapability(capability, facing);
|
|
+ }
|
|
+
|
|
+ protected MapStorage perWorldStorage; //Moved to a getter to simulate final without being final so we can load in subclasses.
|
|
+ public MapStorage getPerWorldStorage()
|
|
+ {
|
|
+ return perWorldStorage;
|
|
+ }
|
|
+
|
|
public void sendPacketToServer(Packet<?> packetIn)
|
|
{
|
|
throw new UnsupportedOperationException("Can't send packets to server unless you're on the client.");
|
|
@@ -3673,4 +4381,6 @@
|
|
{
|
|
return null;
|
|
}
|
|
+
|
|
+ public Map<BlockPos, TileEntity> capturedTileEntities = Maps.newHashMap(); // CatServer - Add spigot field, no used
|
|
}
|