use of org.spongepowered.common.event.tracking.IPhaseState in project SpongeCommon by SpongePowered.
the class MixinBlockLeaves method onUpdateDecayState.
@Redirect(method = "updateTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;I)Z"))
public boolean onUpdateDecayState(net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, int flags) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final boolean isBlockAlready = phaseTracker.getCurrentState().getPhase() != TrackingPhases.BLOCK;
final IPhaseState currentState = phaseTracker.getCurrentPhaseData().state;
final boolean isWorldGen = currentState.isWorldGeneration();
try (PhaseContext<?> context = isBlockAlready && !isWorldGen ? BlockPhase.State.BLOCK_DECAY.createPhaseContext().source(LocatableBlock.builder().location(new Location<World>((World) worldIn, pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build()).buildAndSwitch() : null) {
return worldIn.setBlockState(pos, state, flags);
}
}
use of org.spongepowered.common.event.tracking.IPhaseState in project SpongeCommon by SpongePowered.
the class MixinBlockLeaves method destroy.
/**
* @author gabizou - August 2nd, 2016
* @reason Rewrite to handle both drops and the change state for leaves
* that are considered to be decaying, so the drops do not leak into
* whatever previous phase is being handled in. Since the issue is that
* the block change takes place in a different phase (more than likely),
* the drops are either "lost" or not considered for drops because the
* blocks didn't change according to whatever previous phase.
*
* @param worldIn The world in
* @param pos The position
*/
@Overwrite
private void destroy(net.minecraft.world.World worldIn, BlockPos pos) {
final IBlockState state = worldIn.getBlockState(pos);
// Sponge Start - Cause tracking
if (!((IMixinWorld) worldIn).isFake()) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final PhaseData peek = phaseTracker.getCurrentPhaseData();
final IPhaseState currentState = peek.state;
final boolean isWorldGen = currentState.isWorldGeneration();
final boolean isBlockAlready = phaseTracker.getCurrentState().getPhase() != TrackingPhases.BLOCK;
try (PhaseContext<?> context = isBlockAlready && !isWorldGen ? BlockPhase.State.BLOCK_DECAY.createPhaseContext().source(LocatableBlock.builder().location(new Location<World>((World) worldIn, pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build()).buildAndSwitch() : null) {
this.dropBlockAsItem(worldIn, pos, state, 0);
worldIn.setBlockToAir(pos);
}
return;
}
// Sponge End
this.dropBlockAsItem(worldIn, pos, state, 0);
worldIn.setBlockToAir(pos);
}
use of org.spongepowered.common.event.tracking.IPhaseState in project SpongeCommon by SpongePowered.
the class MixinEntityLivingBase method onDeath.
/**
* @author blood - May 12th, 2016
* @author gabizou - June 4th, 2016 - Update for 1.9.4 and Cause Tracker changes
*
* @reason SpongeForge requires an overwrite so we do it here instead. This handles all living entity death events
* (except players). Note should be taken that normally, there are lists for drops captured, however, the drops
* are retroactively captured by the PhaseTracker and associated through the different phases, depending on
* how they are handled, so no lists and flags on the entities themselves are needed as they are tracked through
* the {@link PhaseContext} of the current {@link IPhaseState} at which this method is called. The compatibility
* for Forge's events to throw are handled specially in SpongeForge.
*/
@Overwrite
public void onDeath(DamageSource cause) {
// Sponge Start - Call our event, and forge's event
// This will transitively call the forge event
SpongeCommonEventFactory.callDestructEntityEventDeath((EntityLivingBase) (Object) this, cause);
// Double check that the PhaseTracker is already capturing the Death phase
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
final boolean isMainThread = !this.world.isRemote || Sponge.isServerAvailable() && Sponge.getServer().isMainThread();
try (final StackFrame frame = isMainThread ? Sponge.getCauseStackManager().pushCauseFrame() : null) {
if (!this.world.isRemote) {
final PhaseData peek = phaseTracker.getCurrentPhaseData();
final IPhaseState state = peek.state;
this.tracksEntityDeaths = !phaseTracker.getCurrentState().tracksEntityDeaths() && state != EntityPhase.State.DEATH;
if (this.tracksEntityDeaths) {
Sponge.getCauseStackManager().pushCause(this);
final PhaseContext<?> context = EntityPhase.State.DEATH.createPhaseContext().setDamageSource((org.spongepowered.api.event.cause.entity.damage.source.DamageSource) cause).source(this);
this.getNotifierUser().ifPresent(context::notifier);
this.getCreatorUser().ifPresent(context::owner);
context.buildAndSwitch();
}
} else {
this.tracksEntityDeaths = false;
}
// Sponge End
if (this.dead) {
// Sponge Start - ensure that we finish the tracker if necessary
if (this.tracksEntityDeaths && !properlyOverridesOnDeathForCauseTrackerCompletion()) {
phaseTracker.completePhase(EntityPhase.State.DEATH);
}
// Sponge End
return;
}
Entity entity = cause.getTrueSource();
EntityLivingBase entitylivingbase = this.getAttackingEntity();
if (this.scoreValue >= 0 && entitylivingbase != null) {
entitylivingbase.awardKillScore((EntityLivingBase) (Object) this, this.scoreValue, cause);
}
if (entity != null) {
entity.onKillEntity((EntityLivingBase) (Object) this);
}
this.dead = true;
this.getCombatTracker().reset();
if (!this.world.isRemote) {
int i = 0;
if (entity instanceof EntityPlayer) {
i = EnchantmentHelper.getLootingModifier((EntityLivingBase) entity);
}
if (this.canDropLoot() && this.world.getGameRules().getBoolean("doMobLoot")) {
boolean flag = this.recentlyHit > 0;
this.dropLoot(flag, i, cause);
}
}
// Sponge Start - Don't send the state if this is a human. Fixes ghost items on client.
if (!((EntityLivingBase) (Object) this instanceof EntityHuman)) {
this.world.setEntityState((EntityLivingBase) (Object) this, (byte) 3);
}
if (phaseTracker != null && this.tracksEntityDeaths && !properlyOverridesOnDeathForCauseTrackerCompletion()) {
this.tracksEntityDeaths = false;
phaseTracker.completePhase(EntityPhase.State.DEATH);
}
}
// Sponge End
}
use of org.spongepowered.common.event.tracking.IPhaseState 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.IPhaseState 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