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