use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class PlayerInteractionHandler method handleBlockPlacing.
public void handleBlockPlacing(MessagePlayInPlayerBlockPlacement message) {
final HandType handType = message.getHandType();
// the main hand message.
if (handType == HandTypes.OFF_HAND) {
return;
}
// Try the action of the hotbar item first
final AbstractSlot hotbarSlot = this.player.getInventory().getHotbar().getSelectedSlot();
final AbstractSlot offHandSlot = this.player.getInventory().getOffhand();
// The offset can round up to 1, causing
// an incorrect clicked block location
final Vector3d pos2 = message.getClickOffset();
final double dx = Math.min(pos2.getX(), 0.999);
final double dy = Math.min(pos2.getY(), 0.999);
final double dz = Math.min(pos2.getZ(), 0.999);
final Location<World> clickedLocation = new Location<>(this.player.getWorld(), message.getPosition().toDouble().add(dx, dy, dz));
final Direction face = message.getFace();
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.pushCause(this.player);
// Add context
frame.addContext(ContextKeys.INTERACTION_FACE, face);
frame.addContext(ContextKeys.INTERACTION_LOCATION, clickedLocation);
frame.addContext(ContextKeys.BLOCK_LOCATION, new Location<>(clickedLocation.getExtent(), message.getPosition()));
frame.addContext(ContextKeys.PLAYER, this.player);
final BehaviorContextImpl context = new BehaviorContextImpl(causeStack);
final BehaviorContext.Snapshot snapshot = context.pushSnapshot();
if (!this.player.get(Keys.IS_SNEAKING).orElse(false)) {
final BlockState blockState = this.player.getWorld().getBlock(message.getPosition());
final LanternBlockType blockType = (LanternBlockType) blockState.getType();
frame.addContext(ContextKeys.BLOCK_TYPE, blockState.getType());
frame.addContext(ContextKeys.USED_BLOCK_STATE, blockState);
BehaviorContext.Snapshot snapshot1 = context.pushSnapshot();
// Try first with the main hand
hotbarSlot.peek().ifPresent(stack -> frame.addContext(ContextKeys.USED_ITEM_STACK, stack));
frame.addContext(ContextKeys.USED_SLOT, hotbarSlot);
frame.addContext(ContextKeys.INTERACTION_HAND, HandTypes.MAIN_HAND);
BehaviorResult result = context.process(blockType.getPipeline().pipeline(InteractWithBlockBehavior.class), (ctx, behavior) -> behavior.tryInteract(blockType.getPipeline(), ctx));
if (!result.isSuccess()) {
context.popSnapshot(snapshot1);
snapshot1 = context.pushSnapshot();
// Try again with the off hand
offHandSlot.peek().ifPresent(stack -> frame.addContext(ContextKeys.USED_ITEM_STACK, stack));
frame.addContext(ContextKeys.USED_SLOT, offHandSlot);
frame.addContext(ContextKeys.INTERACTION_HAND, HandTypes.OFF_HAND);
result = context.process(blockType.getPipeline().pipeline(InteractWithBlockBehavior.class), (ctx, behavior) -> behavior.tryInteract(blockType.getPipeline(), ctx));
}
if (result.isSuccess()) {
snapshot1 = context.pushSnapshot();
// We can still continue, doing other operations
if (result == BehaviorResult.CONTINUE) {
handleMainHandItemInteraction(context, snapshot1);
}
context.accept();
return;
}
context.popSnapshot(snapshot1);
snapshot1 = context.pushSnapshot();
if (result.isSuccess()) {
snapshot1 = context.pushSnapshot();
// We can still continue, doing other operations
if (result == BehaviorResult.CONTINUE) {
handleOffHandItemInteraction(context, snapshot1);
}
context.accept();
return;
}
context.popSnapshot(snapshot1);
}
handleItemInteraction(context, snapshot);
}
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class PlayerInteractionHandler method handleFinishItemInteraction0.
private void handleFinishItemInteraction0(AbstractSlot slot, HandType handType) {
final Optional<ItemStack> handItem = slot.peek();
if (handItem.isPresent()) {
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.pushCause(this.player);
frame.addContext(ContextKeys.PLAYER, this.player);
if (handItem.isPresent()) {
final LanternItemType itemType = (LanternItemType) handItem.get().getType();
frame.addContext(ContextKeys.USED_ITEM_STACK, handItem.get());
frame.addContext(ContextKeys.USED_SLOT, slot);
frame.addContext(ContextKeys.INTERACTION_HAND, handType);
frame.addContext(ContextKeys.ITEM_TYPE, itemType);
final BehaviorContextImpl context = new BehaviorContextImpl(causeStack);
if (context.process(itemType.getPipeline().pipeline(FinishUsingItemBehavior.class), (ctx, behavior) -> behavior.tryUse(itemType.getPipeline(), ctx)).isSuccess()) {
context.accept();
}
}
}
}
resetItemUseTime();
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class PlayerInteractionHandler method handleItemInteraction.
public void handleItemInteraction(MessagePlayInPlayerUseItem message) {
// Prevent duplicate messages
final long time = System.currentTimeMillis();
if (this.lastInteractionTime != -1L && time - this.lastInteractionTime < 40) {
return;
}
this.lastInteractionTime = time;
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
final BehaviorContextImpl context = new BehaviorContextImpl(causeStack);
frame.pushCause(this.player);
frame.addContext(ContextKeys.PLAYER, this.player);
final BehaviorContext.Snapshot snapshot = context.pushSnapshot();
if (!handleItemInteraction(context, snapshot)) {
if (!this.player.get(LanternKeys.CAN_DUAL_WIELD).orElse(false)) {
return;
}
final AbstractSlot offHandSlot = this.player.getInventory().getOffhand();
final Optional<ItemStack> handItem = offHandSlot.peek();
if (handItem.isPresent()) {
final DualWieldProperty property = handItem.get().getProperty(DualWieldProperty.class).orElse(null);
// noinspection ConstantConditions
if (property != null && property.getValue()) {
/*
final Vector3d position = this.player.getPosition().add(0, this.player.get(Keys.IS_SNEAKING).get() ? 1.54 : 1.62, 0);
final Optional<BlockRayHit<LanternWorld>> hit = BlockRay.from(this.player.getWorld(), position)
.direction(this.player.getDirectionVector())
.distanceLimit(5)
// Is this supposed to be inverted?
.skipFilter(Predicates.not(BlockRay.onlyAirFilter()))
.build()
.end();
if (hit.isPresent() && hit.get().getLocation().getBlock().getType() != BlockTypes.AIR) {
return;
}
*/
this.player.getConnection().send(new MessagePlayOutEntityAnimation(this.player.getNetworkId(), 3));
this.player.triggerEvent(SwingHandEntityEvent.of(HandTypes.OFF_HAND));
/*
final CooldownTracker cooldownTracker = this.player.getCooldownTracker();
cooldownTracker.set(handItem.get().getType(), 15);
*/
}
}
}
}
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class LanternEntity method heal.
/**
* Heals the entity for the specified amount.
*
* <p>Will not heal them if they are dead and will not set
* them above their maximum health.</p>
*
* @param amount The amount to heal for
* @param source The healing source
*/
public boolean heal(double amount, HealingSource source) {
if (isDead()) {
return false;
}
final MutableBoundedValue<Double> health = getValue(Keys.HEALTH).orElse(null);
if (health == null || health.get() >= health.getMaxValue()) {
return false;
}
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.pushCause(source);
frame.addContext(LanternEventContextKeys.HEALING_TYPE, source.getHealingType());
final HealEntityEvent event = SpongeEventFactory.createHealEntityEvent(frame.getCurrentCause(), new ArrayList<>(), this, amount);
Sponge.getEventManager().post(event);
if (event.isCancelled()) {
return false;
}
amount = event.getFinalHealAmount();
if (amount > 0) {
offer(Keys.HEALTH, Math.min(health.get() + amount, health.getMaxValue()));
}
}
return true;
}
use of org.lanternpowered.server.event.CauseStack in project LanternServer by LanternPowered.
the class LanternItem method pulse.
@Override
public void pulse(int deltaTicks) {
super.pulse(deltaTicks);
int pickupDelay = get(Keys.PICKUP_DELAY).orElse(0);
int despawnDelay = get(Keys.DESPAWN_DELAY).orElse(NO_DESPAWN_DELAY);
final int oldPickupDelay = pickupDelay;
final int oldDespawnDelay = despawnDelay;
if (pickupDelay != NO_PICKUP_DELAY && pickupDelay > 0) {
pickupDelay--;
}
if (despawnDelay != NO_DESPAWN_DELAY && despawnDelay > 0) {
despawnDelay--;
}
if (this.counter++ % 20 == 0) {
final CombineData data = combineItemStacks(pickupDelay, despawnDelay);
if (data != null) {
pickupDelay = data.pickupDelay;
despawnDelay = data.despawnDelay;
}
}
if (this.counter % 10 == 0 && pickupDelay != NO_PICKUP_DELAY && pickupDelay <= 0) {
tryToPickupItems();
}
if (pickupDelay != oldPickupDelay) {
offer(Keys.PICKUP_DELAY, pickupDelay);
}
if (despawnDelay != oldDespawnDelay) {
offer(Keys.DESPAWN_DELAY, despawnDelay);
}
if (despawnDelay <= 0) {
final CauseStack causeStack = CauseStack.current();
try (CauseStack.Frame frame = causeStack.pushCauseFrame()) {
frame.pushCause(this);
// Throw the expire entity event
final ExpireEntityEvent.TargetItem event = SpongeEventFactory.createExpireEntityEventTargetItem(causeStack.getCurrentCause(), this);
Sponge.getEventManager().post(event);
// Remove the item, also within this context
remove();
}
// A death animation/particle?
getWorld().spawnParticles(EffectHolder.DEATH_EFFECT, getBoundingBox().get().getCenter());
} else {
pulsePhysics();
}
}
Aggregations