Search in sources :

Example 1 with PhaseData

use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.

the class MixinNetHandlerPlayServer method processCreativeInventoryAction.

/**
 * @author blood - June 6th, 2016
 * @author gabizou - June 20th, 2016 - Update for 1.9.4 and minor refactors.
 * @reason Since mojang handles creative packets different than survival, we need to
 * restructure this method to prevent any packets being sent to client as we will
 * not be able to properly revert them during drops.
 *
 * @param packetIn The creative inventory packet
 */
@Overwrite
public void processCreativeInventoryAction(CPacketCreativeInventoryAction packetIn) {
    PacketThreadUtil.checkThreadAndEnqueue(packetIn, (NetHandlerPlayServer) (Object) this, this.player.getServerWorld());
    if (this.player.interactionManager.isCreative()) {
        final PhaseData peek = PhaseTracker.getInstance().getCurrentPhaseData();
        final PacketContext<?> context = (PacketContext<?>) peek.context;
        final boolean ignoresCreative = context.getIgnoringCreative();
        boolean clickedOutside = packetIn.getSlotId() < 0;
        ItemStack itemstack = packetIn.getStack();
        if (!itemstack.isEmpty() && itemstack.hasTagCompound() && itemstack.getTagCompound().hasKey("BlockEntityTag", 10)) {
            NBTTagCompound nbttagcompound = itemstack.getTagCompound().getCompoundTag("BlockEntityTag");
            if (nbttagcompound.hasKey("x") && nbttagcompound.hasKey("y") && nbttagcompound.hasKey("z")) {
                BlockPos blockpos = new BlockPos(nbttagcompound.getInteger("x"), nbttagcompound.getInteger("y"), nbttagcompound.getInteger("z"));
                TileEntity tileentity = this.player.world.getTileEntity(blockpos);
                if (tileentity != null) {
                    NBTTagCompound nbttagcompound1 = new NBTTagCompound();
                    tileentity.writeToNBT(nbttagcompound1);
                    nbttagcompound1.removeTag("x");
                    nbttagcompound1.removeTag("y");
                    nbttagcompound1.removeTag("z");
                    itemstack.setTagInfo("BlockEntityTag", nbttagcompound1);
                }
            }
        }
        boolean clickedHotbar = packetIn.getSlotId() >= 1 && packetIn.getSlotId() <= 45;
        boolean itemValidCheck = itemstack.isEmpty() || itemstack.getMetadata() >= 0 && itemstack.getCount() <= 64 && !itemstack.isEmpty();
        // Sponge start - handle CreativeInventoryEvent
        if (itemValidCheck) {
            if (!ignoresCreative) {
                ClickInventoryEvent.Creative clickEvent = SpongeCommonEventFactory.callCreativeClickInventoryEvent(this.player, packetIn);
                if (clickEvent.isCancelled()) {
                    // Reset slot on client
                    if (packetIn.getSlotId() >= 0 && packetIn.getSlotId() < this.player.inventoryContainer.inventorySlots.size()) {
                        this.player.connection.sendPacket(new SPacketSetSlot(this.player.inventoryContainer.windowId, packetIn.getSlotId(), this.player.inventoryContainer.getSlot(packetIn.getSlotId()).getStack()));
                        this.player.connection.sendPacket(new SPacketSetSlot(-1, -1, ItemStack.EMPTY));
                    }
                    return;
                }
            }
            if (clickedHotbar) {
                if (itemstack.isEmpty()) {
                    this.player.inventoryContainer.putStackInSlot(packetIn.getSlotId(), ItemStack.EMPTY);
                } else {
                    this.player.inventoryContainer.putStackInSlot(packetIn.getSlotId(), itemstack);
                }
                this.player.inventoryContainer.setCanCraft(this.player, true);
            } else if (clickedOutside && this.itemDropThreshold < 200) {
                this.itemDropThreshold += 20;
                EntityItem entityitem = this.player.dropItem(itemstack, true);
                if (entityitem != null) {
                    entityitem.setAgeToCreativeDespawnTime();
                }
            }
        }
    // Sponge end
    }
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) NBTTagCompound(net.minecraft.nbt.NBTTagCompound) ClickInventoryEvent(org.spongepowered.api.event.item.inventory.ClickInventoryEvent) TileEntity(net.minecraft.tileentity.TileEntity) PacketContext(org.spongepowered.common.event.tracking.phase.packet.PacketContext) BlockPos(net.minecraft.util.math.BlockPos) SPacketSetSlot(net.minecraft.network.play.server.SPacketSetSlot) ItemStack(net.minecraft.item.ItemStack) EntityItem(net.minecraft.entity.item.EntityItem) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 2 with PhaseData

use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.

the class MixinWorldServer method onUpdateTick.

// This ticks pending updates to blocks, Requires mixin for NextTickListEntry so we use the correct tracking
@SuppressWarnings("unchecked")
@Redirect(method = "tickUpdates", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;updateTick(Lnet/minecraft/world/World;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/state/IBlockState;Ljava/util/Random;)V"))
private void onUpdateTick(Block block, net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, Random rand) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData phaseData = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = phaseData.state;
    if (phaseState.alreadyCapturingBlockTicks(phaseData.context) || phaseState.ignoresBlockUpdateTick(phaseData)) {
        block.updateTick(worldIn, pos, state, rand);
        return;
    }
    IMixinBlock spongeBlock = (IMixinBlock) block;
    spongeBlock.getTimingsHandler().startTiming();
    TrackingUtil.updateTickBlock(this, block, pos, state, rand);
    spongeBlock.getTimingsHandler().stopTiming();
}
Also used : IMixinBlock(org.spongepowered.common.interfaces.block.IMixinBlock) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 3 with PhaseData

use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.

the class MixinWorldServer method onAddBlockEvent.

@Redirect(method = "addBlockEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/WorldServer$ServerBlockEventList;add(Ljava/lang/Object;)Z", remap = false))
private boolean onAddBlockEvent(WorldServer.ServerBlockEventList list, Object obj, BlockPos pos, Block blockIn, int eventId, int eventParam) {
    final BlockEventData blockEventData = (BlockEventData) obj;
    IMixinBlockEventData blockEvent = (IMixinBlockEventData) blockEventData;
    // This is very common with pistons as they add block events while blocks are being notified.
    if (blockIn instanceof BlockPistonBase) {
        // We only fire pre events for pistons
        if (SpongeCommonEventFactory.handlePistonEvent(this, list, obj, pos, blockIn, eventId, eventParam)) {
            return false;
        }
        blockEvent.setCaptureBlocks(false);
    // TODO BLOCK_EVENT flag
    } else if (SpongeCommonEventFactory.callChangeBlockEventPre(this, pos).isCancelled()) {
        return false;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData currentPhase = phaseTracker.getCurrentPhaseData();
    final IPhaseState phaseState = currentPhase.state;
    if (phaseState.ignoresBlockEvent()) {
        return list.add((BlockEventData) obj);
    }
    final PhaseContext<?> context = currentPhase.context;
    final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(this, pos.getX(), pos.getY(), pos.getZ())).state(this.getBlock(pos.getX(), pos.getY(), pos.getZ())).build();
    blockEvent.setTickBlock(locatable);
    phaseState.addNotifierToBlockEvent(context, this, pos, blockEvent);
    return list.add((BlockEventData) obj);
}
Also used : IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) PhaseData(org.spongepowered.common.event.tracking.PhaseData) BlockPistonBase(net.minecraft.block.BlockPistonBase) IPhaseState(org.spongepowered.common.event.tracking.IPhaseState) LocatableBlock(org.spongepowered.api.world.LocatableBlock) IMixinBlockEventData(org.spongepowered.common.interfaces.block.IMixinBlockEventData) BlockEventData(net.minecraft.block.BlockEventData) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 4 with PhaseData

use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method handleCollideBlockEvent.

public static boolean handleCollideBlockEvent(Block block, net.minecraft.world.World world, BlockPos pos, IBlockState state, net.minecraft.entity.Entity entity, Direction direction) {
    if (pos.getY() <= 0) {
        return false;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    try (StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(entity);
        if (!(entity instanceof EntityPlayer)) {
            IMixinEntity spongeEntity = (IMixinEntity) entity;
            Optional<User> user = spongeEntity.getCreatorUser();
            if (user.isPresent()) {
                Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, user.get());
            }
        }
        // TODO: Add target side support
        CollideBlockEvent event = SpongeEventFactory.createCollideBlockEvent(Sponge.getCauseStackManager().getCurrentCause(), (BlockState) state, new Location<>((World) world, VecHelper.toVector3d(pos)), direction);
        boolean cancelled = SpongeImpl.postEvent(event);
        if (!cancelled) {
            IMixinEntity spongeEntity = (IMixinEntity) entity;
            if (!pos.equals(spongeEntity.getLastCollidedBlockPos())) {
                final PhaseData peek = phaseTracker.getCurrentPhaseData();
                final Optional<User> notifier = peek.context.getNotifier();
                if (notifier.isPresent()) {
                    IMixinChunk spongeChunk = (IMixinChunk) world.getChunkFromBlockCoords(pos);
                    spongeChunk.addTrackedBlockPosition(block, pos, notifier.get(), PlayerTracker.Type.NOTIFIER);
                }
            }
        }
        return cancelled;
    }
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) User(org.spongepowered.api.entity.living.player.User) PhaseData(org.spongepowered.common.event.tracking.PhaseData) IMixinChunk(org.spongepowered.common.interfaces.IMixinChunk) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) EntityPlayer(net.minecraft.entity.player.EntityPlayer) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) World(org.spongepowered.api.world.World) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent)

Example 5 with PhaseData

use of org.spongepowered.common.event.tracking.PhaseData in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method callChangeBlockEventModifyLiquidMix.

public static ChangeBlockEvent.Modify callChangeBlockEventModifyLiquidMix(net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, @Nullable Object source) {
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    BlockState fromState = BlockUtil.fromNative(worldIn.getBlockState(pos));
    BlockState toState = BlockUtil.fromNative(state);
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    if (source == null) {
        // If source is null the source is the block itself
        source = LocatableBlock.builder().state(fromState).world(((World) worldIn)).position(pos.getX(), pos.getY(), pos.getZ()).build();
    }
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(source);
        Sponge.getCauseStackManager().addContext(EventContextKeys.LIQUID_MIX, (World) worldIn);
        if (owner != null) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
        }
        if (notifier != null) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
        }
        WorldProperties world = ((World) worldIn).getProperties();
        Vector3i position = new Vector3i(pos.getX(), pos.getY(), pos.getZ());
        Transaction<BlockSnapshot> transaction = new Transaction<>(BlockSnapshot.builder().blockState(fromState).world(world).position(position).build(), BlockSnapshot.builder().blockState(toState).world(world).position(position).build());
        ChangeBlockEvent.Modify event = SpongeEventFactory.createChangeBlockEventModify(Sponge.getCauseStackManager().getCurrentCause(), Collections.singletonList(transaction));
        SpongeImpl.postEvent(event);
        return event;
    }
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) SlotTransaction(org.spongepowered.api.item.inventory.transaction.SlotTransaction) Transaction(org.spongepowered.api.data.Transaction) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Vector3i(com.flowpowered.math.vector.Vector3i) WorldProperties(org.spongepowered.api.world.storage.WorldProperties)

Aggregations

PhaseData (org.spongepowered.common.event.tracking.PhaseData)30 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)22 BlockPos (net.minecraft.util.math.BlockPos)13 IPhaseState (org.spongepowered.common.event.tracking.IPhaseState)10 User (org.spongepowered.api.entity.living.player.User)9 IBlockState (net.minecraft.block.state.IBlockState)8 EntityPlayer (net.minecraft.entity.player.EntityPlayer)8 World (org.spongepowered.api.world.World)8 Overwrite (org.spongepowered.asm.mixin.Overwrite)8 CauseStackManager (org.spongepowered.api.event.CauseStackManager)6 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)6 ItemStack (net.minecraft.item.ItemStack)5 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)5 Transaction (org.spongepowered.api.data.Transaction)5 BlockState (org.spongepowered.api.block.BlockState)4 Inject (org.spongepowered.asm.mixin.injection.Inject)4 Redirect (org.spongepowered.asm.mixin.injection.Redirect)4 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)4 IMixinWorld (org.spongepowered.common.interfaces.world.IMixinWorld)4 Block (net.minecraft.block.Block)3