Search in sources :

Example 16 with ServerLocation

use of org.spongepowered.api.world.server.ServerLocation in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method handleCollideImpactEvent.

public static boolean handleCollideImpactEvent(final net.minecraft.world.entity.Entity projectile, @Nullable final ProjectileSource projectileSource, final HitResult movingObjectPosition) {
    final HitResult.Type movingObjectType = movingObjectPosition.getType();
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(projectile);
        frame.addContext(EventContextKeys.PROJECTILE_SOURCE, projectileSource == null ? UnknownProjectileSource.UNKNOWN : projectileSource);
        final Optional<UUID> creator = PhaseTracker.getInstance().getPhaseContext().getCreator();
        creator.ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
        final ServerLocation impactPoint = ServerLocation.of((ServerWorld) projectile.level, VecHelper.toVector3d(movingObjectPosition.getLocation()));
        boolean cancelled = false;
        if (movingObjectType == HitResult.Type.BLOCK) {
            final BlockHitResult blockMovingObjectPosition = (BlockHitResult) movingObjectPosition;
            final BlockPos blockPos = blockMovingObjectPosition.getBlockPos();
            if (blockPos.getY() <= 0) {
                return false;
            }
            final BlockSnapshot targetBlock = ((ServerWorld) projectile.level).createSnapshot(blockPos.getX(), blockPos.getY(), blockPos.getZ());
            final Direction side = DirectionFacingProvider.INSTANCE.getKey(blockMovingObjectPosition.getDirection()).get();
            final CollideBlockEvent.Impact event = SpongeEventFactory.createCollideBlockEventImpact(frame.currentCause(), impactPoint, targetBlock.state(), targetBlock.location().get(), side);
            cancelled = SpongeCommon.post(event);
            // Track impact block if event is not cancelled
            if (!cancelled && creator.isPresent()) {
                final BlockPos targetPos = VecHelper.toBlockPos(impactPoint.blockPosition());
                final LevelChunkBridge spongeChunk = (LevelChunkBridge) projectile.level.getChunkAt(targetPos);
                spongeChunk.bridge$addTrackedBlockPosition((Block) targetBlock.state().type(), targetPos, creator.get(), PlayerTracker.Type.NOTIFIER);
            }
        } else if (movingObjectType == HitResult.Type.ENTITY) {
            // entity
            final EntityHitResult entityMovingObjectPosition = (EntityHitResult) movingObjectPosition;
            final ArrayList<Entity> entityList = new ArrayList<>();
            entityList.add((Entity) entityMovingObjectPosition.getEntity());
            final CollideEntityEvent.Impact event = SpongeEventFactory.createCollideEntityEventImpact(frame.currentCause(), entityList, impactPoint);
            cancelled = SpongeCommon.post(event);
        }
        return cancelled;
    }
}
Also used : JukeboxBlockEntity(net.minecraft.world.level.block.entity.JukeboxBlockEntity) Entity(org.spongepowered.api.entity.Entity) LivingEntity(net.minecraft.world.entity.LivingEntity) ServerLocation(org.spongepowered.api.world.server.ServerLocation) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) ArrayList(java.util.ArrayList) Direction(org.spongepowered.api.util.Direction) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) EntityHitResult(net.minecraft.world.phys.EntityHitResult) BlockHitResult(net.minecraft.world.phys.BlockHitResult) EntityHitResult(net.minecraft.world.phys.EntityHitResult) HitResult(net.minecraft.world.phys.HitResult) ServerWorld(org.spongepowered.api.world.server.ServerWorld) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BlockPos(net.minecraft.core.BlockPos) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) UUID(java.util.UUID) BlockHitResult(net.minecraft.world.phys.BlockHitResult)

Example 17 with ServerLocation

use of org.spongepowered.api.world.server.ServerLocation in project SpongeCommon by SpongePowered.

the class ServerPlayerGameModeMixin_Tracker method useItemOn.

/**
 * @author Morph
 * @reason Fire interact block event.
 */
@Overwrite
public InteractionResult useItemOn(final ServerPlayer playerIn, final Level worldIn, final ItemStack stackIn, final InteractionHand handIn, final BlockHitResult blockRaytraceResultIn) {
    final BlockPos blockpos = blockRaytraceResultIn.getBlockPos();
    final BlockState blockstate = worldIn.getBlockState(blockpos);
    // Sponge start
    final BlockSnapshot snapshot = ((ServerWorld) (worldIn)).createSnapshot(VecHelper.toVector3i(blockpos));
    final Vector3d hitVec = Vector3d.from(blockRaytraceResultIn.getBlockPos().getX(), blockRaytraceResultIn.getBlockPos().getY(), blockRaytraceResultIn.getBlockPos().getZ());
    final org.spongepowered.api.util.Direction direction = DirectionFacingProvider.INSTANCE.getKey(blockRaytraceResultIn.getDirection()).get();
    final InteractBlockEvent.Secondary event = SpongeCommonEventFactory.callInteractBlockEventSecondary(playerIn, stackIn, hitVec, snapshot, direction, handIn);
    if (event.isCancelled()) {
        return InteractionResult.FAIL;
    }
    final Tristate useItem = event.useItemResult();
    final Tristate useBlock = event.useBlockResult();
    // Sponge end
    if (this.gameModeForPlayer == GameType.SPECTATOR) {
        final MenuProvider inamedcontainerprovider = blockstate.getMenuProvider(worldIn, blockpos);
        if (inamedcontainerprovider != null) {
            playerIn.openMenu(inamedcontainerprovider);
            final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos());
            final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos);
            try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
                frame.pushCause(playerIn);
                frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos));
                ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location);
                if (!InventoryEventFactory.callInteractContainerOpenEvent(playerIn)) {
                    return InteractionResult.SUCCESS;
                }
            }
            return InteractionResult.SUCCESS;
        } else {
            return InteractionResult.PASS;
        }
    } else {
        final boolean flag = !playerIn.getMainHandItem().isEmpty() || !playerIn.getOffhandItem().isEmpty();
        final boolean flag1 = playerIn.isSecondaryUseActive() && flag;
        final ItemStack copiedStack = stackIn.copy();
        if (useBlock != Tristate.FALSE && !flag1) {
            // Sponge check useBlock
            final AbstractContainerMenu lastOpenContainer = playerIn.containerMenu;
            final InteractionResult result = blockstate.use(worldIn, playerIn, handIn, blockRaytraceResultIn);
            if (result.consumesAction() && lastOpenContainer != playerIn.containerMenu) {
                final Vector3i pos = VecHelper.toVector3i(blockRaytraceResultIn.getBlockPos());
                final ServerLocation location = ServerLocation.of((ServerWorld) worldIn, pos);
                try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
                    frame.pushCause(playerIn);
                    frame.addContext(EventContextKeys.BLOCK_HIT, ((ServerWorld) (worldIn)).createSnapshot(pos));
                    ((ContainerBridge) playerIn.containerMenu).bridge$setOpenLocation(location);
                    if (!InventoryEventFactory.callInteractContainerOpenEvent(playerIn)) {
                        return InteractionResult.FAIL;
                    }
                }
            }
            if (result.consumesAction()) {
                CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack);
                return result;
            }
        }
        if (!stackIn.isEmpty() && !playerIn.getCooldowns().isOnCooldown(stackIn.getItem())) {
            // Sponge start
            if (useItem == Tristate.FALSE) {
                return InteractionResult.PASS;
            }
            // Sponge end
            final UseOnContext itemusecontext = new UseOnContext(playerIn, handIn, blockRaytraceResultIn);
            final InteractionResult result;
            if (this.isCreative()) {
                final int i = stackIn.getCount();
                result = stackIn.useOn(itemusecontext);
                stackIn.setCount(i);
            } else {
                result = stackIn.useOn(itemusecontext);
                // Sponge start - log change in hand
                final PhaseContext<@NonNull ?> context = PhaseTracker.SERVER.getPhaseContext();
                final TransactionalCaptureSupplier transactor = context.getTransactor();
                transactor.logPlayerInventoryChange(this.player, PlayerInventoryTransaction.EventCreator.STANDARD);
                this.player.inventoryMenu.broadcastChanges();
            // Sponge end
            }
            if (result.consumesAction()) {
                CriteriaTriggers.ITEM_USED_ON_BLOCK.trigger(playerIn, blockpos, copiedStack);
            }
            return result;
        } else {
            return InteractionResult.PASS;
        }
    }
}
Also used : ServerLocation(org.spongepowered.api.world.server.ServerLocation) Tristate(org.spongepowered.api.util.Tristate) ContainerBridge(org.spongepowered.common.bridge.world.inventory.container.ContainerBridge) ServerWorld(org.spongepowered.api.world.server.ServerWorld) InteractionResult(net.minecraft.world.InteractionResult) InteractBlockEvent(org.spongepowered.api.event.block.InteractBlockEvent) TransactionalCaptureSupplier(org.spongepowered.common.event.tracking.context.transaction.TransactionalCaptureSupplier) AbstractContainerMenu(net.minecraft.world.inventory.AbstractContainerMenu) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BlockPos(net.minecraft.core.BlockPos) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) UseOnContext(net.minecraft.world.item.context.UseOnContext) MenuProvider(net.minecraft.world.MenuProvider) BlockState(net.minecraft.world.level.block.state.BlockState) Vector3d(org.spongepowered.math.vector.Vector3d) Vector3i(org.spongepowered.math.vector.Vector3i) ItemStack(net.minecraft.world.item.ItemStack) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 18 with ServerLocation

use of org.spongepowered.api.world.server.ServerLocation in project SpongeCommon by SpongePowered.

the class ExplosionMixin method explode.

/**
 * @author gabizou
 * @author zidane
 * @reason Fire ExplosionEvent.Detonate
 */
@Overwrite
public void explode() {
    // Sponge Start - Do not run calculation logic on client thread
    if (this.level.isClientSide) {
        return;
    }
    // Sponge Start - If the explosion should not break blocks, don't bother calculating it on server thread
    if (this.impl$shouldBreakBlocks) {
        final Set<BlockPos> set = Sets.newHashSet();
        final int i = 16;
        for (int j = 0; j < 16; ++j) {
            for (int k = 0; k < 16; ++k) {
                for (int l = 0; l < 16; ++l) {
                    if (j == 0 || j == 15 || k == 0 || k == 15 || l == 0 || l == 15) {
                        double d0 = (double) ((float) j / 15.0F * 2.0F - 1.0F);
                        double d1 = (double) ((float) k / 15.0F * 2.0F - 1.0F);
                        double d2 = (double) ((float) l / 15.0F * 2.0F - 1.0F);
                        final double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2);
                        d0 = d0 / d3;
                        d1 = d1 / d3;
                        d2 = d2 / d3;
                        float f = this.radius * (0.7F + this.level.random.nextFloat() * 0.6F);
                        double d4 = this.x;
                        double d6 = this.y;
                        double d8 = this.z;
                        for (final float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
                            final BlockPos blockpos = new BlockPos(d4, d6, d8);
                            final BlockState blockstate = this.level.getBlockState(blockpos);
                            final FluidState fluidstate = this.level.getFluidState(blockpos);
                            Optional<Float> optional = this.damageCalculator.getBlockExplosionResistance((net.minecraft.world.level.Explosion) (Object) this, this.level, blockpos, blockstate, fluidstate);
                            if (optional.isPresent()) {
                                f -= (optional.get() + 0.3F) * 0.3F;
                            }
                            if (f > 0.0F && this.damageCalculator.shouldBlockExplode((net.minecraft.world.level.Explosion) (Object) this, this.level, blockpos, blockstate, f)) {
                                set.add(blockpos);
                            }
                            d4 += d0 * (double) 0.3F;
                            d6 += d1 * (double) 0.3F;
                            d8 += d2 * (double) 0.3F;
                        }
                    }
                }
            }
        }
        this.toBlow.addAll(set);
    }
    // Sponge End
    final float f3 = this.radius * 2.0F;
    final int k1 = Mth.floor(this.x - (double) f3 - 1.0D);
    final int l1 = Mth.floor(this.x + (double) f3 + 1.0D);
    final int i2 = Mth.floor(this.y - (double) f3 - 1.0D);
    final int i1 = Mth.floor(this.y + (double) f3 + 1.0D);
    final int j2 = Mth.floor(this.z - (double) f3 - 1.0D);
    final int j1 = Mth.floor(this.z + (double) f3 + 1.0D);
    // Sponge Start - Only query for entities if we're to damage them
    final List<Entity> list = this.impl$shouldDamageEntities ? this.level.getEntities(this.source, new AABB((double) k1, (double) i2, (double) j2, (double) l1, (double) i1, (double) j1)) : Collections.emptyList();
    if (ShouldFire.EXPLOSION_EVENT_DETONATE) {
        final List<ServerLocation> blockPositions = new ArrayList<>(this.toBlow.size());
        final List<org.spongepowered.api.entity.Entity> entities = new ArrayList<>(list.size());
        for (final BlockPos pos : this.toBlow) {
            blockPositions.add(ServerLocation.of((org.spongepowered.api.world.server.ServerWorld) this.level, pos.getX(), pos.getY(), pos.getZ()));
        }
        for (final Entity entity : list) {
            // Make sure to check the entity is immune first.
            if (!entity.ignoreExplosion()) {
                entities.add((org.spongepowered.api.entity.Entity) entity);
            }
        }
        final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
        final ExplosionEvent.Detonate detonate = SpongeEventFactory.createExplosionEventDetonate(cause, blockPositions, entities, (Explosion) this, (org.spongepowered.api.world.server.ServerWorld) this.level);
        SpongeCommon.post(detonate);
        // Clear the positions so that they can be pulled from the event
        this.toBlow.clear();
        if (detonate.isCancelled()) {
            return;
        }
        if (this.impl$shouldBreakBlocks) {
            for (final ServerLocation worldLocation : detonate.affectedLocations()) {
                this.toBlow.add(VecHelper.toBlockPos(worldLocation));
            }
        }
        // Clear the list of entities so they can be pulled from the event.
        list.clear();
        if (this.impl$shouldDamageEntities) {
            for (final org.spongepowered.api.entity.Entity entity : detonate.entities()) {
                try {
                    list.add((Entity) entity);
                } catch (final Exception e) {
                // Do nothing, a plugin tried to use the wrong entity somehow.
                }
            }
        }
    }
    // Sponge End
    final Vec3 vec3d = new Vec3(this.x, this.y, this.z);
    for (int k2 = 0; k2 < list.size(); ++k2) {
        final Entity entity = list.get(k2);
        if (!entity.ignoreExplosion()) {
            final double d12 = (double) (Mth.sqrt(entity.distanceToSqr(vec3d)) / f3);
            if (d12 <= 1.0D) {
                double d5 = entity.getX() - this.x;
                double d7 = entity.getEyeY() - this.y;
                double d9 = entity.getZ() - this.z;
                final double d13 = (double) Mth.sqrt(d5 * d5 + d7 * d7 + d9 * d9);
                if (d13 != 0.0D) {
                    d5 = d5 / d13;
                    d7 = d7 / d13;
                    d9 = d9 / d13;
                    final double d14 = (double) net.minecraft.world.level.Explosion.getSeenPercent(vec3d, entity);
                    final double d10 = (1.0D - d12) * d14;
                    entity.hurt(this.shadow$getDamageSource(), (float) ((int) ((d10 * d10 + d10) / 2.0D * 7.0D * (double) f3 + 1.0D)));
                    double d11 = d10;
                    if (entity instanceof LivingEntity) {
                        d11 = ProtectionEnchantment.getExplosionKnockbackAfterDampener((LivingEntity) entity, d10);
                    }
                    // Sponge Start - Honor our knockback value from event
                    entity.setDeltaMovement(entity.getDeltaMovement().add(d5 * d11 * this.impl$knockback, d7 * d11 * this.impl$knockback, d9 * d11 * this.impl$knockback));
                    if (entity instanceof Player) {
                        final Player playerentity = (Player) entity;
                        if (!playerentity.isSpectator() && (!playerentity.isCreative() || !playerentity.abilities.flying)) {
                            this.hitPlayers.put(playerentity, new Vec3(d5 * d10 * this.impl$knockback, d7 * d10 * this.impl$knockback, d9 * d10 * this.impl$knockback));
                        }
                    }
                // Sponge End
                }
            }
        }
    }
}
Also used : LivingEntity(net.minecraft.world.entity.LivingEntity) Entity(net.minecraft.world.entity.Entity) ServerLocation(org.spongepowered.api.world.server.ServerLocation) ExplosionEvent(org.spongepowered.api.event.world.ExplosionEvent) ArrayList(java.util.ArrayList) LivingEntity(net.minecraft.world.entity.LivingEntity) Cause(org.spongepowered.api.event.Cause) Vec3(net.minecraft.world.phys.Vec3) BlockPos(net.minecraft.core.BlockPos) Player(net.minecraft.world.entity.player.Player) Explosion(org.spongepowered.api.world.explosion.Explosion) BlockState(net.minecraft.world.level.block.state.BlockState) AABB(net.minecraft.world.phys.AABB) FluidState(net.minecraft.world.level.material.FluidState) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 19 with ServerLocation

use of org.spongepowered.api.world.server.ServerLocation in project SpongeCommon by SpongePowered.

the class BaseFireBlockMixin method impl$spongeRedirectForFireDamage.

@Redirect(method = "entityInside", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private boolean impl$spongeRedirectForFireDamage(final Entity self, final DamageSource source, final float damage, final BlockState blockState, final Level world, final BlockPos blockPos, final Entity entity) {
    if (self.level.isClientSide) {
        // Short Circuit
        return self.hurt(source, damage);
    }
    try {
        final ServerLocation location = ServerLocation.of((ServerWorld) world, blockPos.getX(), blockPos.getY(), blockPos.getZ());
        final DamageSource fire = MinecraftBlockDamageSource.ofFire("inFire", location, true);
        ((DamageSourceBridge) fire).bridge$setFireSource();
        return self.hurt(DamageSource.IN_FIRE, damage);
    } finally {
        // Since "source" is already the DamageSource.IN_FIRE object, we can re-use it to re-assign.
        ((DamageSourceBridge) source).bridge$setFireSource();
    }
}
Also used : DamageSource(net.minecraft.world.damagesource.DamageSource) MinecraftBlockDamageSource(org.spongepowered.common.util.MinecraftBlockDamageSource) DamageSourceBridge(org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 20 with ServerLocation

use of org.spongepowered.api.world.server.ServerLocation in project SpongeCommon by SpongePowered.

the class MagmaBlockMixin method impl$swapDamageSourceForMagma.

@Redirect(method = "stepOn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;hurt(Lnet/minecraft/world/damagesource/DamageSource;F)Z"))
private boolean impl$swapDamageSourceForMagma(Entity entity, DamageSource source, float damage, Level world, BlockPos pos, Entity original) {
    if (!world.isClientSide) {
        try {
            final ServerLocation location = ServerLocation.of((ServerWorld) world, pos.getX(), pos.getY(), pos.getZ());
            final DamageSource hotFloor = MinecraftBlockDamageSource.ofFire("hotFloor", location, false);
            ((DamageSourceBridge) (Object) hotFloor).bridge$setHotFloorSource();
            return entity.hurt(DamageSource.HOT_FLOOR, damage);
        } finally {
            ((DamageSourceBridge) source).bridge$setHotFloorSource();
        }
    }
    return entity.hurt(source, damage);
}
Also used : DamageSource(net.minecraft.world.damagesource.DamageSource) MinecraftBlockDamageSource(org.spongepowered.common.util.MinecraftBlockDamageSource) DamageSourceBridge(org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge) ServerLocation(org.spongepowered.api.world.server.ServerLocation) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Aggregations

ServerLocation (org.spongepowered.api.world.server.ServerLocation)34 ServerWorld (org.spongepowered.api.world.server.ServerWorld)12 Component (net.kyori.adventure.text.Component)9 Cause (org.spongepowered.api.event.Cause)9 CauseStackManager (org.spongepowered.api.event.CauseStackManager)8 ArrayList (java.util.ArrayList)7 Optional (java.util.Optional)7 Sponge (org.spongepowered.api.Sponge)7 Entity (org.spongepowered.api.entity.Entity)7 Redirect (org.spongepowered.asm.mixin.injection.Redirect)7 Vector3d (org.spongepowered.math.vector.Vector3d)7 Collection (java.util.Collection)6 List (java.util.List)6 BlockPos (net.minecraft.core.BlockPos)6 DamageSource (net.minecraft.world.damagesource.DamageSource)6 Nullable (org.checkerframework.checker.nullness.qual.Nullable)6 ServerPlayer (org.spongepowered.api.entity.living.player.server.ServerPlayer)6 HashMap (java.util.HashMap)5 Map (java.util.Map)5 ServerLevel (net.minecraft.server.level.ServerLevel)5