use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.
the class MixinExplosion method doExplosionB.
/**
* @author gabizou - March 26th, 2017
* @reason Since forge will attempt to call the normalized method for modded blocks,
* we must artificially capture the block position for any block drops or changes during the
* explosion phase.
*
* Does the second part of the explosion (sound, particles, drop spawn)
*/
@Overwrite
public void doExplosionB(boolean spawnParticles) {
this.world.playSound((EntityPlayer) null, this.x, this.y, this.z, SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.BLOCKS, 4.0F, (1.0F + (this.world.rand.nextFloat() - this.world.rand.nextFloat()) * 0.2F) * 0.7F);
if (this.size >= 2.0F) {
if (this.world instanceof WorldServer) {
((WorldServer) this.world).spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D);
} else {
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
} else {
if (this.world instanceof WorldServer) {
((WorldServer) this.world).spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.x, this.y, this.z, 1, 0, 0, 0, 0.1D);
} else {
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.x, this.y, this.z, 1.0D, 0.0D, 0.0D);
}
}
if (this.shouldBreakBlocks) {
// Sponge - use 'shouldBreakBlocks' instead of 'damagesTerrain'
for (BlockPos blockpos : this.affectedBlockPositions) {
IBlockState iblockstate = this.world.getBlockState(blockpos);
Block block = iblockstate.getBlock();
if (spawnParticles) {
double d0 = (double) ((float) blockpos.getX() + this.world.rand.nextFloat());
double d1 = (double) ((float) blockpos.getY() + this.world.rand.nextFloat());
double d2 = (double) ((float) blockpos.getZ() + this.world.rand.nextFloat());
double d3 = d0 - this.x;
double d4 = d1 - this.y;
double d5 = d2 - this.z;
double d6 = (double) MathHelper.sqrt(d3 * d3 + d4 * d4 + d5 * d5);
d3 = d3 / d6;
d4 = d4 / d6;
d5 = d5 / d6;
double d7 = 0.5D / (d6 / (double) this.size + 0.1D);
d7 = d7 * (double) (this.world.rand.nextFloat() * this.world.rand.nextFloat() + 0.3F);
d3 = d3 * d7;
d4 = d4 * d7;
d5 = d5 * d7;
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_NORMAL, (d0 + this.x) / 2.0D, (d1 + this.y) / 2.0D, (d2 + this.z) / 2.0D, d3, d4, d5, new int[0]);
this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, d0, d1, d2, d3, d4, d5, new int[0]);
}
if (iblockstate.getMaterial() != Material.AIR) {
if (block.canDropFromExplosion((net.minecraft.world.Explosion) (Object) this)) {
// Sponge Start - Track the block position being destroyed
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
// We need to capture this block position if necessary
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(blockpos);
}
block.dropBlockAsItemWithChance(this.world, blockpos, this.world.getBlockState(blockpos), 1.0F / this.size, 0);
// And then un-set the captured block position
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(null);
}
}
// Sponge Start - Track the block position being destroyed
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
// We need to capture this block position if necessary
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(blockpos);
}
// Because we need to hook into forge.
SpongeImplHooks.blockExploded(block, this.world, blockpos, (net.minecraft.world.Explosion) (Object) this);
// And then un-set the captured block position
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(null);
}
// Sponge End
}
}
}
if (this.causesFire) {
for (BlockPos blockpos1 : this.affectedBlockPositions) {
if (this.world.getBlockState(blockpos1).getMaterial() == Material.AIR && this.world.getBlockState(blockpos1.down()).isFullBlock() && this.random.nextInt(3) == 0) {
// Sponge Start - Track the block position being destroyed
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
// We need to capture this block position if necessary
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(blockpos1);
}
phaseTracker.setBlockState((IMixinWorldServer) this.world, blockpos1, Blocks.FIRE.getDefaultState(), BlockChangeFlags.ALL);
// And then un-set the captured block position
if (peek.state.requiresBlockPosTracking()) {
peek.context.getCaptureBlockPos().setPos(null);
}
}
}
}
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.
the class MixinWorldServer method updateBlocks.
/**
* @author blood - July 1st, 2016
* @author gabizou - July 1st, 2016 - Update to 1.10 and cause tracking
*
* @reason Added chunk and block tick optimizations, timings, cause tracking, and pre-construction events.
*/
@SuppressWarnings("unchecked")
@Override
@Overwrite
protected void updateBlocks() {
this.playerCheckLight();
if (this.worldInfo.getTerrainType() == WorldType.DEBUG_ALL_BLOCK_STATES) {
Iterator<net.minecraft.world.chunk.Chunk> iterator1 = this.playerChunkMap.getChunkIterator();
while (iterator1.hasNext()) {
iterator1.next().onTick(false);
}
// Sponge: Add return
return;
}
// else // Sponge - Remove unnecessary else
// { //
int i = this.shadow$getGameRules().getInt("randomTickSpeed");
boolean flag = this.isRaining();
boolean flag1 = this.isThundering();
// this.profiler.startSection("pollingChunks"); // Sponge - Don't use the profiler
// Sponge - get the cause tracker
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
// Sponge: Use SpongeImplHooks for Forge
for (Iterator<net.minecraft.world.chunk.Chunk> iterator = // this.profiler.endSection()) // Sponge - don't use the profiler
SpongeImplHooks.getChunkIterator((WorldServer) (Object) this); // this.profiler.endSection()) // Sponge - don't use the profiler
iterator.hasNext(); ) {
// this.profiler.startSection("getChunk"); // Sponge - Don't use the profiler
net.minecraft.world.chunk.Chunk chunk = iterator.next();
final net.minecraft.world.World world = chunk.getWorld();
int j = chunk.x * 16;
int k = chunk.z * 16;
// this.profiler.endStartSection("checkNextLight"); // Sponge - Don't use the profiler
// Sponge - Timings
this.timings.updateBlocksCheckNextLight.startTiming();
chunk.enqueueRelightChecks();
// Sponge - Timings
this.timings.updateBlocksCheckNextLight.stopTiming();
// this.profiler.endStartSection("tickChunk"); // Sponge - Don't use the profiler
// Sponge - Timings
this.timings.updateBlocksChunkTick.startTiming();
chunk.onTick(false);
// Sponge - Timings
this.timings.updateBlocksChunkTick.stopTiming();
// Sponge start - if surrounding neighbors are not loaded, skip
if (!((IMixinChunk) chunk).areNeighborsLoaded()) {
continue;
}
// Sponge end
// this.profiler.endStartSection("thunder"); // Sponge - Don't use the profiler
// Sponge start
this.timings.updateBlocksThunder.startTiming();
// if (this.provider.canDoLightning(chunk) && flag && flag1 && this.rand.nextInt(100000) == 0) // Sponge - Add SpongeImplHooks for forge
if (this.weatherThunderEnabled && SpongeImplHooks.canDoLightning(this.provider, chunk) && flag && flag1 && this.rand.nextInt(100000) == 0) {
try (final PhaseContext<?> context = TickPhase.Tick.WEATHER.createPhaseContext().source(this).buildAndSwitch()) {
// Sponge end
this.updateLCG = this.updateLCG * 3 + 1013904223;
int l = this.updateLCG >> 2;
BlockPos blockpos = this.adjustPosToNearbyEntity(new BlockPos(j + (l & 15), 0, k + (l >> 8 & 15)));
if (this.isRainingAt(blockpos)) {
DifficultyInstance difficultyinstance = this.getDifficultyForLocation(blockpos);
// Sponge - create a transform to be used for events
final Transform<org.spongepowered.api.world.World> transform = new Transform<>(this, VecHelper.toVector3d(blockpos).toDouble());
if (world.getGameRules().getBoolean("doMobSpawning") && this.rand.nextDouble() < (double) difficultyinstance.getAdditionalDifficulty() * 0.01D) {
// Sponge Start - Throw construction events
try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(this.getWeather());
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.WEATHER);
ConstructEntityEvent.Pre constructEntityEvent = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.HORSE, transform);
SpongeImpl.postEvent(constructEntityEvent);
if (!constructEntityEvent.isCancelled()) {
// Sponge End
EntitySkeletonHorse entityhorse = new EntitySkeletonHorse((WorldServer) (Object) this);
entityhorse.setTrap(true);
entityhorse.setGrowingAge(0);
entityhorse.setPosition(blockpos.getX(), blockpos.getY(), blockpos.getZ());
this.spawnEntity(entityhorse);
// Sponge Start - Throw a construct event for the lightning
}
ConstructEntityEvent.Pre lightning = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.LIGHTNING, transform);
SpongeImpl.postEvent(lightning);
if (!lightning.isCancelled()) {
LightningEvent.Pre lightningPre = SpongeEventFactory.createLightningEventPre(frame.getCurrentCause());
if (!SpongeImpl.postEvent(lightningPre)) {
// Sponge End
this.addWeatherEffect(new EntityLightningBolt(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), true));
}
}
// Sponge - Brackets.
}
} else {
// Sponge start - Throw construction event for lightningbolts
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(this.getWeather());
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, SpawnTypes.WEATHER);
ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), EntityTypes.LIGHTNING, transform);
SpongeImpl.postEvent(event);
if (!event.isCancelled()) {
LightningEvent.Pre lightningPre = SpongeEventFactory.createLightningEventPre(frame.getCurrentCause());
if (!SpongeImpl.postEvent(lightningPre)) {
// Sponge End
this.addWeatherEffect(new EntityLightningBolt(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), true));
}
}
// Sponge - Brackets.
}
}
}
}
// Sponge - brackets
// Sponge End
}
// Sponge - Stop thunder timing
this.timings.updateBlocksThunder.stopTiming();
// Sponge - Start thunder timing
this.timings.updateBlocksIceAndSnow.startTiming();
// if (this.rand.nextInt(16) == 0) // Sponge - Rewrite to use our boolean, and forge hook
if (this.weatherIceAndSnowEnabled && SpongeImplHooks.canDoRainSnowIce(this.provider, chunk) && this.rand.nextInt(16) == 0) {
// Sponge Start - Enter weather phase for snow and ice and flooding.
try (final PhaseContext<?> context = TickPhase.Tick.WEATHER.createPhaseContext().source(this).buildAndSwitch()) {
// Sponge End
this.updateLCG = this.updateLCG * 3 + 1013904223;
int j2 = this.updateLCG >> 2;
BlockPos blockpos1 = this.getPrecipitationHeight(new BlockPos(j + (j2 & 15), 0, k + (j2 >> 8 & 15)));
BlockPos blockpos2 = blockpos1.down();
if (this.canBlockFreezeNoWater(blockpos2)) {
this.setBlockState(blockpos2, Blocks.ICE.getDefaultState());
}
if (flag && this.canSnowAt(blockpos1, true)) {
this.setBlockState(blockpos1, Blocks.SNOW_LAYER.getDefaultState());
}
if (flag && this.getBiome(blockpos2).canRain()) {
this.getBlockState(blockpos2).getBlock().fillWithRain((WorldServer) (Object) this, blockpos2);
}
}
// Sponge - brackets
}
// Sponge - Stop ice and snow timing
this.timings.updateBlocksIceAndSnow.stopTiming();
// Sponge - Start random block tick timing
this.timings.updateBlocksRandomTick.startTiming();
if (i > 0) {
for (ExtendedBlockStorage extendedblockstorage : chunk.getBlockStorageArray()) {
if (extendedblockstorage != net.minecraft.world.chunk.Chunk.NULL_BLOCK_STORAGE && extendedblockstorage.needsRandomTick()) {
for (int i1 = 0; i1 < i; ++i1) {
this.updateLCG = this.updateLCG * 3 + 1013904223;
int j1 = this.updateLCG >> 2;
int k1 = j1 & 15;
int l1 = j1 >> 8 & 15;
int i2 = j1 >> 16 & 15;
IBlockState iblockstate = extendedblockstorage.get(k1, i2, l1);
Block block = iblockstate.getBlock();
if (block.getTickRandomly()) {
// Sponge start - capture random tick
// Remove the random tick for cause tracking
// block.randomTick(this, new BlockPos(k1 + j, i2 + extendedblockstorage.getYLocation(), l1 + k), iblockstate, this.rand);
BlockPos pos = new BlockPos(k1 + j, i2 + extendedblockstorage.getYLocation(), l1 + k);
IMixinBlock spongeBlock = (IMixinBlock) block;
spongeBlock.getTimingsHandler().startTiming();
final PhaseData currentTuple = phaseTracker.getCurrentPhaseData();
final IPhaseState phaseState = currentTuple.state;
if (phaseState.alreadyCapturingBlockTicks(currentTuple.context)) {
block.randomTick(world, pos, iblockstate, this.rand);
} else {
TrackingUtil.randomTickBlock(phaseTracker, this, block, pos, iblockstate, this.rand);
}
spongeBlock.getTimingsHandler().stopTiming();
// Sponge end
}
// this.profiler.endSection(); // Sponge - Don't use the profiler
}
}
}
}
}
// Sponge - Stop random block timing
this.timings.updateBlocksRandomTick.stopTiming();
// this.profiler.endSection(); // Sponge - Don't use the profiler
// } // Sponge- Remove unecessary else
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.
the class PacketUtil method onProcessPacket.
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
public static void onProcessPacket(Packet packetIn, INetHandler netHandler) {
if (netHandler instanceof NetHandlerPlayServer) {
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
EntityPlayerMP packetPlayer = ((NetHandlerPlayServer) netHandler).player;
Sponge.getCauseStackManager().pushCause(packetPlayer);
// If true, logic was handled in Pre so return
if (firePreEvents(packetIn, packetPlayer)) {
return;
}
boolean ignoreCreative = false;
// } else
if (creativeCheck(packetIn, packetPlayer)) {
long packetDiff = System.currentTimeMillis() - lastInventoryOpenPacketTimeStamp;
// If the time between packets is small enough, mark the current packet to be ignored for our event handler.
if (packetDiff < 100) {
ignoreCreative = true;
}
}
// Don't process movement capture logic if player hasn't moved
boolean ignoreMovementCapture = false;
if (packetIn instanceof CPacketPlayer) {
CPacketPlayer movingPacket = ((CPacketPlayer) packetIn);
if (movingPacket instanceof CPacketPlayer.Rotation) {
ignoreMovementCapture = true;
} else if (packetPlayer.posX == movingPacket.x && packetPlayer.posY == movingPacket.y && packetPlayer.posZ == movingPacket.z) {
ignoreMovementCapture = true;
}
}
if (ignoreMovementCapture || (packetIn instanceof CPacketClientSettings)) {
packetIn.processPacket(netHandler);
} else {
final ItemStackSnapshot cursor = ItemStackUtil.snapshotOf(packetPlayer.inventory.getItemStack());
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
IPhaseState<? extends PacketContext<?>> packetState = TrackingPhases.PACKET.getStateForPacket(packetIn);
if (packetState == null) {
throw new IllegalArgumentException("Found a null packet phase for packet: " + packetIn.getClass());
}
PhaseContext<?> context = EMPTY;
if (!TrackingPhases.PACKET.isPacketInvalid(packetIn, packetPlayer, packetState)) {
context = packetState.createPhaseContext().source(packetPlayer).packetPlayer(packetPlayer).packet(packetIn).cursor(cursor).ignoreCreative(ignoreCreative);
TrackingPhases.PACKET.populateContext(packetIn, packetPlayer, packetState, context);
context.owner((Player) packetPlayer);
context.notifier((Player) packetPlayer);
}
try (PhaseContext<?> packetContext = context.buildAndSwitch()) {
packetIn.processPacket(netHandler);
}
if (packetIn instanceof CPacketClientStatus) {
// update the reference of player
packetPlayer = ((NetHandlerPlayServer) netHandler).player;
}
((IMixinEntityPlayerMP) packetPlayer).setPacketItem(ItemStack.EMPTY);
}
}
} else {
// client
packetIn.processPacket(netHandler);
}
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.
the class MixinWorldServer method notifyNeighborsOfStateChange.
/**
* @author gabizou - March 12th, 2016
*
* Technically an overwrite to properly track on *server* worlds.
*/
@Override
public void notifyNeighborsOfStateChange(BlockPos pos, Block blockType, boolean updateObserverBlocks) {
if (!isValid(pos)) {
return;
}
final Chunk chunk = ((IMixinChunkProviderServer) this.getChunkProvider()).getLoadedChunkWithoutMarkingActive(pos.getX() >> 4, pos.getZ() >> 4);
// Don't let neighbor updates trigger a chunk load ever
if (chunk == null) {
return;
}
final NotifyNeighborBlockEvent event = SpongeCommonEventFactory.callNotifyNeighborEvent(this, pos, NOTIFY_DIRECTIONS);
if (event == null || !event.isCancelled()) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
for (EnumFacing facing : EnumFacing.values()) {
if (event != null) {
final Direction direction = DirectionFacingProvider.getInstance().getKey(facing).get();
if (!event.getNeighbors().keySet().contains(direction)) {
continue;
}
}
phaseTracker.notifyBlockOfStateChange(this, pos.offset(facing), blockType, pos);
}
}
// Copied over to ensure observers retain functionality.
if (updateObserverBlocks) {
this.updateObservingBlocksAt(pos, blockType);
}
}
use of org.spongepowered.common.event.tracking.PhaseTracker in project SpongeCommon by SpongePowered.
the class MixinWorldServer method onUpdateWeatherEffect.
@SuppressWarnings("Duplicates")
@Override
public void onUpdateWeatherEffect(net.minecraft.entity.Entity entityIn) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final IPhaseState state = phaseTracker.getCurrentState();
if (state.alreadyCapturingEntityTicks()) {
entityIn.onUpdate();
return;
}
TrackingUtil.tickEntity(entityIn);
updateRotation(entityIn);
}
Aggregations