Search in sources :

Example 31 with BlockSnapshot

use of org.spongepowered.api.block.BlockSnapshot in project SpongeForge by SpongePowered.

the class MixinPlayerInteractionManager method processRightClickBlock.

/**
 * @author gabizou - May 5th, 2016
 * @reason Rewrite the firing of interact block events with forge hooks
 * Note: This is a dirty merge of Aaron's SpongeCommon writeup of the interaction events and
 * Forge's additions. There's some overlay between the two events, specifically that there
 * is a SpongeEvent thrown before the ForgeEvent, and yet both are checked in various
 * if statements.
 */
@Overwrite
public EnumActionResult processRightClickBlock(EntityPlayer player, World worldIn, ItemStack stack, EnumHand hand, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ) {
    if (this.gameType == GameType.SPECTATOR) {
        TileEntity tileentity = worldIn.getTileEntity(pos);
        if (tileentity instanceof ILockableContainer) {
            Block block = worldIn.getBlockState(pos).getBlock();
            ILockableContainer ilockablecontainer = (ILockableContainer) tileentity;
            if (ilockablecontainer instanceof TileEntityChest && block instanceof BlockChest) {
                ilockablecontainer = ((BlockChest) block).getLockableContainer(worldIn, pos);
            }
            if (ilockablecontainer != null) {
                player.displayGUIChest(ilockablecontainer);
                return EnumActionResult.SUCCESS;
            }
        } else if (tileentity instanceof IInventory) {
            player.displayGUIChest((IInventory) tileentity);
            return EnumActionResult.SUCCESS;
        }
        return EnumActionResult.PASS;
    }
    // Store reference of current player's itemstack in case it changes
    ItemStack oldStack = stack.copy();
    InteractBlockEvent.Secondary event;
    BlockSnapshot currentSnapshot = ((org.spongepowered.api.world.World) worldIn).createSnapshot(pos.getX(), pos.getY(), pos.getZ());
    event = SpongeCommonEventFactory.callInteractBlockEventSecondary(player, oldStack, VecHelper.toVector3d(pos.add(hitX, hitY, hitZ)), currentSnapshot, DirectionFacingProvider.getInstance().getKey(facing).get(), hand);
    if (!ItemStack.areItemStacksEqual(oldStack, this.player.getHeldItem(hand))) {
        SpongeCommonEventFactory.playerInteractItemChanged = true;
    }
    TileEntity tileEntity = worldIn.getTileEntity(pos);
    if (event.isCancelled()) {
        final IBlockState state = worldIn.getBlockState(pos);
        if (state.getBlock() == Blocks.COMMAND_BLOCK) {
            // CommandBlock GUI opens solely on the client, we need to force it close on cancellation
            this.player.connection.sendPacket(new SPacketCloseWindow(0));
        } else if (state.getProperties().containsKey(BlockDoor.HALF)) {
            // client to resolve this
            if (state.getValue(BlockDoor.HALF) == BlockDoor.EnumDoorHalf.LOWER) {
                this.player.connection.sendPacket(new SPacketBlockChange(worldIn, pos.up()));
            } else {
                this.player.connection.sendPacket(new SPacketBlockChange(worldIn, pos.down()));
            }
        } else if (!stack.isEmpty()) {
            // Stopping the placement of a door or double plant causes artifacts (ghosts) on the top-side of the block. We need to remove it
            if (stack.getItem() instanceof ItemDoor || (stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock().equals(Blocks.DOUBLE_PLANT))) {
                this.player.connection.sendPacket(new SPacketBlockChange(worldIn, pos.up(2)));
            }
        }
        // since we don't want to undo that
        if (tileEntity != null && this.player.openContainer instanceof ContainerPlayer) {
            this.player.closeScreen();
        }
        SpongeCommonEventFactory.interactBlockEventCancelled = true;
        return EnumActionResult.FAIL;
    }
    net.minecraft.item.Item item = stack.isEmpty() ? null : stack.getItem();
    EnumActionResult ret = item == null ? EnumActionResult.PASS : item.onItemUseFirst(player, worldIn, pos, facing, hitX, hitY, hitZ, hand);
    if (ret != EnumActionResult.PASS) {
        return ret;
    }
    boolean bypass = true;
    final ItemStack[] itemStacks = { player.getHeldItemMainhand(), player.getHeldItemOffhand() };
    for (ItemStack s : itemStacks) {
        bypass = bypass && (s.isEmpty() || s.getItem().doesSneakBypassUse(s, worldIn, pos, player));
    }
    EnumActionResult result = EnumActionResult.PASS;
    if (!player.isSneaking() || bypass || event.getUseBlockResult() == Tristate.TRUE) {
        // also, store the result instead of returning immediately
        if (event.getUseBlockResult() != Tristate.FALSE) {
            IBlockState iblockstate = worldIn.getBlockState(pos);
            Container lastOpenContainer = player.openContainer;
            result = iblockstate.getBlock().onBlockActivated(worldIn, pos, iblockstate, player, hand, facing, hitX, hitY, hitZ) ? EnumActionResult.SUCCESS : EnumActionResult.FAIL;
            // if itemstack changed, avoid restore
            if (!ItemStack.areItemStacksEqual(oldStack, this.player.getHeldItem(hand))) {
                SpongeCommonEventFactory.playerInteractItemChanged = true;
            }
            result = this.handleOpenEvent(lastOpenContainer, this.player, currentSnapshot, result);
        } else {
            this.player.connection.sendPacket(new SPacketBlockChange(this.world, pos));
            result = TristateUtil.toActionResult(event.getUseItemResult());
        }
    }
    // This handles the event not cancelled and block not activated
    if (result != EnumActionResult.SUCCESS && tileEntity != null && hand == EnumHand.MAIN_HAND) {
        this.player.closeScreen();
    }
    // store result instead of returning
    if (stack.isEmpty()) {
        result = EnumActionResult.PASS;
    } else if (player.getCooldownTracker().hasCooldown(stack.getItem())) {
        result = EnumActionResult.PASS;
    } else if (stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock() instanceof BlockCommandBlock && !player.canUseCommand(2, "")) {
        result = EnumActionResult.FAIL;
    } else {
        if ((result != EnumActionResult.SUCCESS && event.getUseItemResult() != Tristate.FALSE || result == EnumActionResult.SUCCESS && event.getUseItemResult() == Tristate.TRUE)) {
            int meta = stack.getMetadata();
            int size = stack.getCount();
            result = stack.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
            // nest isCreative check instead of calling the method twice.
            if (this.isCreative()) {
                stack.setItemDamage(meta);
                stack.setCount(size);
            }
        }
    }
    if (!ItemStack.areItemStacksEqual(player.getHeldItem(hand), oldStack) || result != EnumActionResult.SUCCESS) {
        player.openContainer.detectAndSendChanges();
    }
    return result;
// Sponge end
}
Also used : ItemDoor(net.minecraft.item.ItemDoor) BlockCommandBlock(net.minecraft.block.BlockCommandBlock) World(net.minecraft.world.World) TileEntity(net.minecraft.tileentity.TileEntity) ILockableContainer(net.minecraft.world.ILockableContainer) EnumActionResult(net.minecraft.util.EnumActionResult) ILockableContainer(net.minecraft.world.ILockableContainer) Container(net.minecraft.inventory.Container) InteractBlockEvent(org.spongepowered.api.event.block.InteractBlockEvent) SPacketCloseWindow(net.minecraft.network.play.server.SPacketCloseWindow) IInventory(net.minecraft.inventory.IInventory) TileEntityChest(net.minecraft.tileentity.TileEntityChest) IBlockState(net.minecraft.block.state.IBlockState) BlockChest(net.minecraft.block.BlockChest) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) ItemBlock(net.minecraft.item.ItemBlock) SPacketBlockChange(net.minecraft.network.play.server.SPacketBlockChange) ContainerPlayer(net.minecraft.inventory.ContainerPlayer) Block(net.minecraft.block.Block) BlockCommandBlock(net.minecraft.block.BlockCommandBlock) ItemBlock(net.minecraft.item.ItemBlock) ItemStack(net.minecraft.item.ItemStack) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 32 with BlockSnapshot

use of org.spongepowered.api.block.BlockSnapshot in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method callBlockPlaceEvent.

public static ChangeBlockEvent.Place callBlockPlaceEvent(Event event) {
    ChangeBlockEvent.Place spongeEvent = (ChangeBlockEvent.Place) event;
    if (spongeEvent.getCause().root() instanceof Player) {
        EntityPlayer player = (EntityPlayer) spongeEvent.getCause().first(Player.class).get();
        net.minecraft.world.World world = player.world;
        final PhaseTracker phaseTracker = PhaseTracker.getInstance();
        final PhaseContext<?> currentContext = phaseTracker.getCurrentContext();
        PhaseContext<?> target = currentContext;
        if (currentContext instanceof UnwindingPhaseContext) {
            target = ((UnwindingPhaseContext) currentContext).getUnwindingContext();
        }
        PacketContext<?> context = target instanceof PacketContext<?> ? (PacketContext<?>) target : null;
        Packet<?> contextPacket = context != null ? context.getPacket() : null;
        if (contextPacket == null) {
            return spongeEvent;
        }
        if (spongeEvent.getTransactions().size() == 1) {
            BlockPos pos = VecHelper.toBlockPos(spongeEvent.getTransactions().get(0).getOriginal().getPosition());
            IBlockState state = (IBlockState) spongeEvent.getTransactions().get(0).getOriginal().getState();
            net.minecraftforge.common.util.BlockSnapshot blockSnapshot = new net.minecraftforge.common.util.BlockSnapshot(world, pos, state);
            IBlockState placedAgainst = Blocks.AIR.getDefaultState();
            EnumHand hand = EnumHand.MAIN_HAND;
            if (contextPacket instanceof CPacketPlayerTryUseItemOnBlock) {
                CPacketPlayerTryUseItemOnBlock packet = (CPacketPlayerTryUseItemOnBlock) contextPacket;
                EnumFacing facing = packet.getDirection();
                placedAgainst = blockSnapshot.getWorld().getBlockState(blockSnapshot.getPos().offset(facing.getOpposite()));
                hand = packet.getHand();
            }
            BlockEvent.PlaceEvent forgeEvent = new BlockEvent.PlaceEvent(blockSnapshot, placedAgainst, player, hand);
            ((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
            if (forgeEvent.isCanceled()) {
                spongeEvent.setCancelled(true);
            }
        } else {
            // multi
            Iterator<Transaction<BlockSnapshot>> iterator = spongeEvent.getTransactions().iterator();
            List<net.minecraftforge.common.util.BlockSnapshot> blockSnapshots = new ArrayList<>();
            while (iterator.hasNext()) {
                Transaction<BlockSnapshot> transaction = iterator.next();
                Location<World> location = transaction.getOriginal().getLocation().get();
                IBlockState state = (IBlockState) transaction.getOriginal().getState();
                BlockPos pos = new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
                net.minecraftforge.common.util.BlockSnapshot blockSnapshot = new net.minecraftforge.common.util.BlockSnapshot(world, pos, state);
                blockSnapshots.add(blockSnapshot);
            }
            IBlockState placedAgainst = Blocks.AIR.getDefaultState();
            EnumHand hand = EnumHand.MAIN_HAND;
            if (contextPacket instanceof CPacketPlayerTryUseItemOnBlock) {
                CPacketPlayerTryUseItemOnBlock packet = (CPacketPlayerTryUseItemOnBlock) contextPacket;
                EnumFacing facing = packet.getDirection();
                placedAgainst = blockSnapshots.get(0).getWorld().getBlockState(blockSnapshots.get(0).getPos().offset(facing.getOpposite()));
                hand = packet.getHand();
            }
            BlockEvent.MultiPlaceEvent forgeEvent = new BlockEvent.MultiPlaceEvent(blockSnapshots, placedAgainst, player, hand);
            ((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
            if (forgeEvent.isCanceled()) {
                spongeEvent.setCancelled(true);
            }
        }
    }
    return spongeEvent;
}
Also used : EnumFacing(net.minecraft.util.EnumFacing) ArrayList(java.util.ArrayList) UnwindingPhaseContext(org.spongepowered.common.event.tracking.phase.general.UnwindingPhaseContext) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) EnumHand(net.minecraft.util.EnumHand) BlockPos(net.minecraft.util.math.BlockPos) Player(org.spongepowered.api.entity.living.player.Player) EntityPlayer(net.minecraft.entity.player.EntityPlayer) IBlockState(net.minecraft.block.state.IBlockState) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) CPacketPlayerTryUseItemOnBlock(net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock) IMixinEventBus(org.spongepowered.mod.interfaces.IMixinEventBus) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Transaction(org.spongepowered.api.data.Transaction) EntityPlayer(net.minecraft.entity.player.EntityPlayer) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) BlockEvent(net.minecraftforge.event.world.BlockEvent) InteractBlockEvent(org.spongepowered.api.event.block.InteractBlockEvent) NotifyNeighborBlockEvent(org.spongepowered.api.event.block.NotifyNeighborBlockEvent)

Example 33 with BlockSnapshot

use of org.spongepowered.api.block.BlockSnapshot in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method createSleepingEventPre.

public static SleepingEvent.Pre createSleepingEventPre(PlayerSleepInBedEvent forgeEvent) {
    final net.minecraft.world.World world = forgeEvent.getEntity().getEntityWorld();
    if (world.isRemote) {
        return null;
    }
    final BlockPos pos = forgeEvent.getPos();
    BlockSnapshot bedSnapshot = ((World) world).createSnapshot(pos.getX(), pos.getY(), pos.getZ());
    Sponge.getCauseStackManager().pushCause(forgeEvent.getEntity());
    return SpongeEventFactory.createSleepingEventPre(Sponge.getCauseStackManager().getCurrentCause(), bedSnapshot, (org.spongepowered.api.entity.Entity) forgeEvent.getEntity());
}
Also used : IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) BlockPos(net.minecraft.util.math.BlockPos) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld)

Example 34 with BlockSnapshot

use of org.spongepowered.api.block.BlockSnapshot in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method createChangeBlockEventPlace.

public static ChangeBlockEvent.Place createChangeBlockEventPlace(BlockEvent.PlaceEvent forgeEvent) {
    final BlockPos pos = forgeEvent.getPos();
    final net.minecraft.world.World world = forgeEvent.getWorld();
    if (world.isRemote) {
        return null;
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    BlockSnapshot originalSnapshot = ((IMixinBlockSnapshot) forgeEvent.getBlockSnapshot()).createSpongeBlockSnapshot();
    BlockSnapshot finalSnapshot = ((BlockState) forgeEvent.getPlacedBlock()).snapshotFor(new Location<>((World) world, VecHelper.toVector3d(pos)));
    ImmutableList<Transaction<BlockSnapshot>> blockSnapshots = new ImmutableList.Builder<Transaction<BlockSnapshot>>().add(new Transaction<>(originalSnapshot, finalSnapshot)).build();
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    EntityPlayer player = forgeEvent.getPlayer();
    if (SpongeImplHooks.isFakePlayer(player)) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
    } else if (Sponge.getCauseStackManager().getCurrentCause() == null) {
        Sponge.getCauseStackManager().pushCause(player);
    }
    if (owner != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(owner);
        }
    } else {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(player);
        }
    }
    if (notifier != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
    }
    Sponge.getCauseStackManager().addContext(EventContextKeys.PLAYER_PLACE, (World) world);
    return SpongeEventFactory.createChangeBlockEventPlace(Sponge.getCauseStackManager().getCurrentCause(), blockSnapshots);
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) Transaction(org.spongepowered.api.data.Transaction) EntityPlayer(net.minecraft.entity.player.EntityPlayer) BlockPos(net.minecraft.util.math.BlockPos) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot)

Example 35 with BlockSnapshot

use of org.spongepowered.api.block.BlockSnapshot in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method createChangeBlockEventPlace.

public static ChangeBlockEvent.Place createChangeBlockEventPlace(BlockEvent.MultiPlaceEvent forgeEvent) {
    final net.minecraft.world.World world = forgeEvent.getWorld();
    if (world.isRemote) {
        return null;
    }
    ImmutableList.Builder<Transaction<BlockSnapshot>> builder = new ImmutableList.Builder<Transaction<BlockSnapshot>>();
    for (net.minecraftforge.common.util.BlockSnapshot blockSnapshot : forgeEvent.getReplacedBlockSnapshots()) {
        final BlockPos snapshotPos = blockSnapshot.getPos();
        BlockSnapshot originalSnapshot = ((IMixinBlockSnapshot) blockSnapshot).createSpongeBlockSnapshot();
        BlockSnapshot finalSnapshot = ((World) world).createSnapshot(snapshotPos.getX(), snapshotPos.getY(), snapshotPos.getZ());
        builder.add(new Transaction<>(originalSnapshot, finalSnapshot));
    }
    final PhaseTracker phaseTracker = PhaseTracker.getInstance();
    final PhaseData data = phaseTracker.getCurrentPhaseData();
    User owner = data.context.getOwner().orElse(null);
    User notifier = data.context.getNotifier().orElse(null);
    EntityPlayer player = forgeEvent.getPlayer();
    if (SpongeImplHooks.isFakePlayer(player)) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.FAKE_PLAYER, EntityUtil.toPlayer(player));
    } else if (Sponge.getCauseStackManager().getCurrentCause() == null) {
        Sponge.getCauseStackManager().pushCause(player);
    }
    if (owner != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, owner);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(owner);
        }
    } else {
        Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, (User) player);
        if (Sponge.getCauseStackManager().getCurrentCause() == null) {
            Sponge.getCauseStackManager().pushCause(player);
        }
    }
    if (notifier != null) {
        Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, notifier);
    }
    return SpongeEventFactory.createChangeBlockEventPlace(Sponge.getCauseStackManager().getCurrentCause(), builder.build());
}
Also used : PhaseData(org.spongepowered.common.event.tracking.PhaseData) User(org.spongepowered.api.entity.living.player.User) ImmutableList(com.google.common.collect.ImmutableList) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Transaction(org.spongepowered.api.data.Transaction) EntityPlayer(net.minecraft.entity.player.EntityPlayer) BlockPos(net.minecraft.util.math.BlockPos) IMixinBlockSnapshot(org.spongepowered.mod.interfaces.IMixinBlockSnapshot)

Aggregations

BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)144 World (org.spongepowered.api.world.World)64 Listener (org.spongepowered.api.event.Listener)61 Location (org.spongepowered.api.world.Location)27 BlockState (org.spongepowered.api.block.BlockState)21 BlockPos (net.minecraft.util.math.BlockPos)20 Entity (org.spongepowered.api.entity.Entity)20 CauseStackManager (org.spongepowered.api.event.CauseStackManager)19 Region (br.net.fabiozumbi12.RedProtect.Sponge.Region)18 IBlockState (net.minecraft.block.state.IBlockState)18 Transaction (org.spongepowered.api.data.Transaction)17 BlockType (org.spongepowered.api.block.BlockType)15 Direction (org.spongepowered.api.util.Direction)15 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)14 Vector3d (com.flowpowered.math.vector.Vector3d)13 ArrayList (java.util.ArrayList)13 ChangeBlockEvent (org.spongepowered.api.event.block.ChangeBlockEvent)13 Player (org.spongepowered.api.entity.living.player.Player)12 User (org.spongepowered.api.entity.living.player.User)11 LocatableBlock (org.spongepowered.api.world.LocatableBlock)11