use of org.spongepowered.api.block.BlockSnapshot in project SpongeCommon by SpongePowered.
the class InteractEntityPacketState method unwind.
@Override
public void unwind(BasicPacketContext phaseContext) {
final EntityPlayerMP player = phaseContext.getPacketPlayer();
final CPacketUseEntity useEntityPacket = phaseContext.getPacket();
final net.minecraft.entity.Entity entity = useEntityPacket.getEntityFromWorld(player.world);
if (entity == null) {
// Something happened?
return;
}
final World spongeWorld = EntityUtil.getSpongeWorld(player);
EntityUtil.toMixin(entity).setNotifier(player.getUniqueID());
phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(blocks -> {
final PrettyPrinter printer = new PrettyPrinter(80);
printer.add("Processing Interact Entity").centre().hr();
printer.add("The blocks captured are:");
for (BlockSnapshot blockSnapshot : blocks) {
printer.add(" Block: %s", blockSnapshot);
}
printer.trace(System.err);
});
phaseContext.getCapturedEntitySupplier().acceptAndClearIfNotEmpty(entities -> {
final PrettyPrinter printer = new PrettyPrinter(80);
printer.add("Processing Interact Entity").centre().hr();
printer.add("The entities captured are:");
for (Entity capturedEntity : entities) {
printer.add(" Entity: %s", capturedEntity);
}
printer.trace(System.err);
});
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(player);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.PLACEMENT);
phaseContext.getCapturedItemsSupplier().acceptAndClearIfNotEmpty(entities -> {
final List<Entity> items = entities.stream().map(EntityUtil::fromNative).collect(Collectors.toList());
SpawnEntityEvent event = SpongeEventFactory.createSpawnEntityEvent(Sponge.getCauseStackManager().getCurrentCause(), items);
SpongeImpl.postEvent(event);
if (!event.isCancelled()) {
processSpawnedEntities(player, event);
}
});
}
phaseContext.getCapturedEntityDropSupplier().acceptIfNotEmpty(map -> {
final PrettyPrinter printer = new PrettyPrinter(80);
printer.add("Processing Interact Entity").centre().hr();
printer.add("The item stacks captured are: ");
for (Map.Entry<UUID, Collection<ItemDropData>> entry : map.asMap().entrySet()) {
printer.add(" - Entity with UUID: %s", entry.getKey());
for (ItemDropData stack : entry.getValue()) {
printer.add(" - %s", stack);
}
}
printer.trace(System.err);
});
phaseContext.getCapturedBlockSupplier().acceptAndClearIfNotEmpty(snapshots -> TrackingUtil.processBlockCaptures(snapshots, this, phaseContext));
}
use of org.spongepowered.api.block.BlockSnapshot in project SpongeCommon by SpongePowered.
the class MixinPlayerInteractionManager method processRightClickBlock.
/**
* @author Aaron1011
* @author gabizou - May 28th, 2016 - Rewritten for 1.9.4
*
* @reason Fire interact block event.
*/
@Overwrite
public EnumActionResult processRightClickBlock(EntityPlayer player, net.minecraft.world.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) {
// TODO - fire event
player.displayGUIChest(ilockablecontainer);
return EnumActionResult.SUCCESS;
}
} else if (tileentity instanceof IInventory) {
// TODO - fire event
player.displayGUIChest((IInventory) tileentity);
return EnumActionResult.SUCCESS;
}
return EnumActionResult.PASS;
}
// else { // Sponge - Remove unecessary else
// Sponge Start - Create an interact block event before something happens.
final ItemStack oldStack = stack.copy();
final BlockSnapshot currentSnapshot = ((World) worldIn).createSnapshot(pos.getX(), pos.getY(), pos.getZ());
final InteractBlockEvent.Secondary event = SpongeCommonEventFactory.callInteractBlockEventSecondary(player, oldStack, new Vector3d(pos.getX() + hitX, pos.getY() + hitY, pos.getZ() + hitZ), currentSnapshot, DirectionFacingProvider.getInstance().getKey(facing).get(), hand);
if (!ItemStack.areItemStacksEqual(oldStack, this.player.getHeldItem(hand))) {
SpongeCommonEventFactory.playerInteractItemChanged = true;
}
if (event.isCancelled()) {
final IBlockState state = (IBlockState) currentSnapshot.getState();
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 (!oldStack.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
final Item item = oldStack.getItem();
if (item instanceof ItemDoor || (item instanceof ItemBlock && ((ItemBlock) item).getBlock().equals(Blocks.DOUBLE_PLANT))) {
this.player.connection.sendPacket(new SPacketBlockChange(worldIn, pos.up(2)));
}
}
SpongeCommonEventFactory.interactBlockEventCancelled = true;
return EnumActionResult.FAIL;
}
if (!player.isSneaking() || player.getHeldItemMainhand().isEmpty() && player.getHeldItemOffhand().isEmpty()) {
// Also, store the result instead of returning immediately
if (event.getUseBlockResult() != Tristate.FALSE) {
IBlockState iblockstate = (IBlockState) currentSnapshot.getState();
Container lastOpenContainer = player.openContainer;
EnumActionResult result = iblockstate.getBlock().onBlockActivated(worldIn, pos, iblockstate, player, hand, facing, hitX, hitY, hitZ) ? EnumActionResult.SUCCESS : EnumActionResult.PASS;
// if itemstack changed, avoid restore
if (!ItemStack.areItemStacksEqual(oldStack, this.player.getHeldItem(hand))) {
SpongeCommonEventFactory.playerInteractItemChanged = true;
}
result = this.handleOpenEvent(lastOpenContainer, this.player, currentSnapshot, result);
if (result != EnumActionResult.PASS) {
return result;
}
} else {
// Need to send a block change to the client, because otherwise, they are not
// going to be told about the block change.
this.player.connection.sendPacket(new SPacketBlockChange(this.world, pos));
// it wasn't cancelled, but perform no further processing.
return EnumActionResult.FAIL;
}
// Sponge End
}
if (stack.isEmpty()) {
return EnumActionResult.PASS;
} else if (player.getCooldownTracker().hasCooldown(stack.getItem())) {
return EnumActionResult.PASS;
} else if (stack.getItem() instanceof ItemBlock) {
Block block = ((ItemBlock) stack.getItem()).getBlock();
if ((block instanceof BlockCommandBlock || block instanceof BlockStructure) && !player.canUseCommandBlock()) {
return EnumActionResult.FAIL;
}
}
// else if (this.isCreative()) { // Sponge - Rewrite this to handle an isCreative check after the result, since we have a copied stack at the top of this method.
// int j = stack.getMetadata();
// int i = stack.stackSize;
// EnumActionResult enumactionresult = stack.onItemUse(player, worldIn, pos, hand, facing, offsetX, offsetY, offsetZ);
// stack.setItemDamage(j);
// stack.stackSize = i;
// return enumactionresult;
// } else {
// return stack.onItemUse(player, worldIn, pos, hand, facing, offsetX, offsetY, offsetZ);
// }
// } // Sponge - Remove unecessary else bracket
// Sponge Start - complete the method with the micro change of resetting item damage and quantity from the copied stack.
final EnumActionResult result = stack.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
if (this.isCreative()) {
stack.setItemDamage(oldStack.getItemDamage());
stack.setCount(oldStack.getCount());
}
if (!ItemStack.areItemStacksEqual(player.getHeldItem(hand), oldStack) || result != EnumActionResult.SUCCESS) {
player.openContainer.detectAndSendChanges();
}
return result;
// Sponge end
// } // Sponge - Remove unecessary else bracket
}
use of org.spongepowered.api.block.BlockSnapshot in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method handleCollideImpactEvent.
public static boolean handleCollideImpactEvent(net.minecraft.entity.Entity projectile, @Nullable ProjectileSource projectileSource, RayTraceResult movingObjectPosition) {
final PhaseTracker phaseTracker = PhaseTracker.getInstance();
RayTraceResult.Type movingObjectType = movingObjectPosition.typeOfHit;
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(projectile);
Sponge.getCauseStackManager().addContext(EventContextKeys.PROJECTILE_SOURCE, projectileSource == null ? ProjectileSource.UNKNOWN : projectileSource);
final Optional<User> owner = phaseTracker.getCurrentPhaseData().context.getOwner();
owner.ifPresent(user -> Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, user));
Location<World> impactPoint = new Location<>((World) projectile.world, VecHelper.toVector3d(movingObjectPosition.hitVec));
boolean cancelled = false;
if (movingObjectType == RayTraceResult.Type.BLOCK) {
final BlockPos blockPos = movingObjectPosition.getBlockPos();
if (blockPos.getY() <= 0) {
return false;
}
BlockSnapshot targetBlock = ((World) projectile.world).createSnapshot(VecHelper.toVector3i(movingObjectPosition.getBlockPos()));
Direction side = Direction.NONE;
if (movingObjectPosition.sideHit != null) {
side = DirectionFacingProvider.getInstance().getKey(movingObjectPosition.sideHit).get();
}
CollideBlockEvent.Impact event = SpongeEventFactory.createCollideBlockEventImpact(Sponge.getCauseStackManager().getCurrentCause(), impactPoint, targetBlock.getState(), targetBlock.getLocation().get(), side);
cancelled = SpongeImpl.postEvent(event);
// Track impact block if event is not cancelled
if (!cancelled && owner.isPresent()) {
BlockPos targetPos = VecHelper.toBlockPos(impactPoint.getBlockPosition());
IMixinChunk spongeChunk = (IMixinChunk) projectile.world.getChunkFromBlockCoords(targetPos);
spongeChunk.addTrackedBlockPosition((Block) targetBlock.getState().getType(), targetPos, owner.get(), PlayerTracker.Type.NOTIFIER);
}
} else if (movingObjectPosition.entityHit != null) {
// entity
ArrayList<Entity> entityList = new ArrayList<>();
entityList.add((Entity) movingObjectPosition.entityHit);
CollideEntityEvent.Impact event = SpongeEventFactory.createCollideEntityEventImpact(Sponge.getCauseStackManager().getCurrentCause(), entityList, impactPoint);
cancelled = SpongeImpl.postEvent(event);
}
if (cancelled) {
// Entities such as EnderPearls call setDead during onImpact. However, if the event is cancelled
// setDead will never be called resulting in a bad state such as falling through world.
projectile.setDead();
}
return cancelled;
}
}
use of org.spongepowered.api.block.BlockSnapshot in project SpongeCommon by SpongePowered.
the class SpongeCommonEventFactory method callChangeBlockEventModifyLiquidBreak.
public static ChangeBlockEvent.Break callChangeBlockEventModifyLiquidBreak(net.minecraft.world.World worldIn, BlockPos pos, IBlockState state, int flags) {
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);
Object source = data.context.getSource(LocatableBlock.class).orElse(null);
if (source == null) {
// Fallback
source = worldIn;
}
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(source);
Sponge.getCauseStackManager().addContext(EventContextKeys.LIQUID_BREAK, (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.Break event = SpongeEventFactory.createChangeBlockEventBreak(Sponge.getCauseStackManager().getCurrentCause(), Collections.singletonList(transaction));
SpongeImpl.postEvent(event);
return event;
}
}
use of org.spongepowered.api.block.BlockSnapshot in project SpongeCommon by SpongePowered.
the class MixinBlockFalling method onIsAreaLoadedCheck.
@Redirect(method = "checkFallable", at = @At(value = "INVOKE", target = WORLD_IS_AREA_LOADED))
private boolean onIsAreaLoadedCheck(World world, BlockPos pos, BlockPos to) {
if (world.isAreaLoaded(pos, to)) {
if (!world.isRemote) {
BlockPos actualPos = pos.add(32, 32, 32);
EntityType fallingBlock = EntityTypes.FALLING_BLOCK;
Vector3d position = new Vector3d(actualPos.getX() + 0.5D, actualPos.getY(), actualPos.getZ() + 0.5D);
BlockSnapshot snapshot = ((org.spongepowered.api.world.World) world).createSnapshot(actualPos.getX(), actualPos.getY(), actualPos.getZ());
try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
Sponge.getCauseStackManager().pushCause(snapshot);
Sponge.getCauseStackManager().addContext(EventContextKeys.SPAWN_TYPE, InternalSpawnTypes.FALLING_BLOCK);
Transform<org.spongepowered.api.world.World> worldTransform = new Transform<>((org.spongepowered.api.world.World) world, position);
ConstructEntityEvent.Pre event = SpongeEventFactory.createConstructEntityEventPre(Sponge.getCauseStackManager().getCurrentCause(), fallingBlock, worldTransform);
SpongeImpl.postEvent(event);
return !event.isCancelled();
}
}
}
return false;
}
Aggregations