use of org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect in project SpongeCommon by SpongePowered.
the class ChunkPipeline method processChange.
@Nullable
public BlockState processChange(final PhaseContext<?> context, final BlockState currentState, final BlockState proposedState, final BlockPos pos, final int limit) {
if (this.chunkEffects.isEmpty()) {
return null;
}
final ServerLevel serverWorld = this.serverWorld.get();
final int oldOpacity = currentState.getLightBlock(serverWorld, pos);
final SpongeBlockChangeFlag flag = this.transaction.getBlockChangeFlag();
@Nullable final BlockEntity existing = this.chunkSupplier.get().getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
PipelineCursor formerState = new PipelineCursor(currentState, oldOpacity, pos, existing, (Entity) null, limit);
for (final ResultingTransactionBySideEffect effect : this.chunkEffects) {
try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) {
final EffectResult result = effect.effect.processSideEffect(this, formerState, proposedState, flag, limit);
if (result.hasResult) {
return result.resultingState;
}
if (formerState.drops.isEmpty() && !result.drops.isEmpty()) {
formerState = new PipelineCursor(currentState, oldOpacity, pos, existing, null, result.drops, limit);
}
}
}
// if we've gotten here, means something is wrong, we didn't build our effects right.
return null;
}
use of org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect in project SpongeCommon by SpongePowered.
the class WorldPipeline method processEffects.
public boolean processEffects(final PhaseContext<?> context, final BlockState currentState, final BlockState newProposedState, final BlockPos pos, @Nullable final Entity destroyer, final SpongeBlockChangeFlag flag, final int limit) {
if (this.worldEffects.isEmpty()) {
return false;
}
final ServerLevel serverWorld = Objects.requireNonNull(this.serverWorld).get();
// Keep track of the existing block entity prior to processing the chunk pipeline
// and the reasoning is that in several cases where the block entity that is being removed
// will no longer be available. This could be avoided by having the "previous cursor" returned
// from ChunkPipeline, but alas.... that's a refactor for another time.
@Nullable final BlockEntity existing = this.chunkSupplier.get().getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
// We have to get the "old state" from
@Nullable final BlockState oldState = this.chunkPipeline.processChange(context, currentState, newProposedState, pos, limit);
if (oldState == null) {
return false;
}
final int oldOpacity = oldState.getLightBlock(serverWorld, pos);
PipelineCursor formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, destroyer, limit);
for (final ResultingTransactionBySideEffect effect : this.worldEffects) {
try (final EffectTransactor ignored = context.getTransactor().pushEffect(effect)) {
final EffectResult result = effect.effect.processSideEffect(this, formerState, newProposedState, flag, limit);
if (result.hasResult) {
return result.resultingState != null;
}
if (formerState.drops.isEmpty() && !result.drops.isEmpty()) {
formerState = new PipelineCursor(oldState, oldOpacity, pos, existing, formerState.destroyer, result.drops, limit);
}
}
}
// if we've gotten here, means something is wrong, we didn't build our effects right.
return false;
}
use of org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect in project SpongeCommon by SpongePowered.
the class ServerPlayerGameModeMixin_Forge_Tracker method forgeTracker$pushTransactionAndEffect.
// @formatter:on
@Redirect(method = "destroyBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;mineBlock(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)V"))
private void forgeTracker$pushTransactionAndEffect(final ItemStack itemStack, final Level level, final BlockState state, final BlockPos pos, final Player player) {
final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
final TransactionalCaptureSupplier transactor = context.getTransactor();
// Log the prepare drops here because Forge rewrites
// this method to call mine block before calling destroy block
// and mods will possibly already have performed modifications on
// the block before we can capture it in level.destroy.
transactor.logBlockDrops(level, pos, state, level.getBlockEntity(pos));
itemStack.mineBlock(level, state, pos, player);
// Needs to get logged as a sideeffect under the BlockChange
try (EffectTransactor ignored = context.getTransactor().pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()))) {
transactor.logPlayerInventoryChange(this.player, PlayerInventoryTransaction.EventCreator.STANDARD);
this.player.inventoryMenu.broadcastChanges();
}
}
use of org.spongepowered.common.event.tracking.context.transaction.ResultingTransactionBySideEffect in project SpongeCommon by SpongePowered.
the class ServerPlayerGameModeMixin_Vanilla_Tracker method vanillaTracker$onMineBlock.
// @formatter:on
@Redirect(method = "destroyBlock", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;mineBlock(Lnet/minecraft/world/level/Level;Lnet/minecraft/world/level/block/state/BlockState;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/entity/player/Player;)V"))
public void vanillaTracker$onMineBlock(final ItemStack itemStack, final Level param0, final BlockState param1, final BlockPos param2, final Player param3) {
final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
final TransactionalCaptureSupplier transactor = context.getTransactor();
itemStack.mineBlock(param0, param1, param2, param3);
// Needs to get logged as a sideeffect under the BlockChange
try (final EffectTransactor ignored = context.getTransactor().pushEffect(new ResultingTransactionBySideEffect(InventoryEffect.getInstance()))) {
transactor.logPlayerInventoryChange(this.player, PlayerInventoryTransaction.EventCreator.STANDARD);
this.player.inventoryMenu.broadcastChanges();
}
}
Aggregations