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
}
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;
}
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());
}
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);
}
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());
}
Aggregations