Search in sources :

Example 1 with CreatorTrackedBridge

use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.

the class DamageSourceMixin method onSetExplosionSource.

@Inject(method = "explosion(Lnet/minecraft/world/level/Explosion;)Lnet/minecraft/world/damagesource/DamageSource;", at = @At("HEAD"), cancellable = true)
private static void onSetExplosionSource(@Nullable final Explosion explosion, final CallbackInfoReturnable<net.minecraft.world.damagesource.DamageSource> cir) {
    if (explosion != null) {
        final Entity entity = ((ExplosionAccessor) explosion).accessor$source();
        if (entity != null && !((LevelBridge) ((ExplosionAccessor) explosion).accessor$level()).bridge$isFake()) {
            if (explosion.getSourceMob() == null && entity instanceof CreatorTrackedBridge) {
                // check creator
                final CreatorTrackedBridge creatorBridge = (CreatorTrackedBridge) entity;
                creatorBridge.tracker$getCreatorUUID().flatMap(x -> Sponge.server().player(x)).ifPresent(player -> {
                    final IndirectEntityDamageSource damageSource = new IndirectEntityDamageSource("explosion.player", entity, (Entity) player);
                    damageSource.setScalesWithDifficulty().setExplosion();
                    cir.setReturnValue(damageSource);
                });
            }
        }
    }
}
Also used : ExplosionAccessor(org.spongepowered.common.accessor.world.level.ExplosionAccessor) LivingEntity(net.minecraft.world.entity.LivingEntity) Inject(org.spongepowered.asm.mixin.injection.Inject) Supplier(java.util.function.Supplier) CallbackInfoReturnable(org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable) CallbackInfo(org.spongepowered.asm.mixin.injection.callback.CallbackInfo) CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) DamageSourceBridge(org.spongepowered.common.bridge.world.damagesource.DamageSourceBridge) Mixin(org.spongepowered.asm.mixin.Mixin) DamageSource(net.minecraft.world.damagesource.DamageSource) ResourceKey(org.spongepowered.api.ResourceKey) IndirectEntityDamageSource(net.minecraft.world.damagesource.IndirectEntityDamageSource) Nullable(javax.annotation.Nullable) TranslatableComponent(net.minecraft.network.chat.TranslatableComponent) At(org.spongepowered.asm.mixin.injection.At) DamageSourceToTypeProvider(org.spongepowered.common.registry.provider.DamageSourceToTypeProvider) Mutable(org.spongepowered.asm.mixin.Mutable) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) Component(net.minecraft.network.chat.Component) DamageType(org.spongepowered.api.event.cause.entity.damage.DamageType) MoreObjects(com.google.common.base.MoreObjects) Sponge(org.spongepowered.api.Sponge) DamageTypes(org.spongepowered.api.event.cause.entity.damage.DamageTypes) ExplosionAccessor(org.spongepowered.common.accessor.world.level.ExplosionAccessor) Final(org.spongepowered.asm.mixin.Final) RegistryTypes(org.spongepowered.api.registry.RegistryTypes) Explosion(net.minecraft.world.level.Explosion) Entity(net.minecraft.world.entity.Entity) MemoizedSupplier(org.spongepowered.common.util.MemoizedSupplier) Shadow(org.spongepowered.asm.mixin.Shadow) LivingEntity(net.minecraft.world.entity.LivingEntity) Entity(net.minecraft.world.entity.Entity) CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) IndirectEntityDamageSource(net.minecraft.world.damagesource.IndirectEntityDamageSource) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 2 with CreatorTrackedBridge

use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.

the class IndirectEntityDamageSourceMixin method onConstruct.

@Inject(method = "<init>", at = @At("RETURN"))
private void onConstruct(final CallbackInfo callbackInfo) {
    if (this.entity != null) {
        // sources can be null
        final Entity mcEntity = this.shadow$getEntity();
        this.impl$creatorUUID = mcEntity instanceof CreatorTrackedBridge ? ((CreatorTrackedBridge) mcEntity).tracker$getCreatorUUID().orElse(null) : null;
        if (this.owner == null && this.impl$creatorUUID != null) {
            final ServerPlayer player = SpongeCommon.server().getPlayerList().getPlayer(this.impl$creatorUUID);
            if (player != null) {
                this.owner = player;
            }
        }
    }
}
Also used : Entity(net.minecraft.world.entity.Entity) CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) ServerPlayer(net.minecraft.server.level.ServerPlayer) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 3 with CreatorTrackedBridge

use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.

the class TrackingUtil method tickTileEntity.

@SuppressWarnings({ "unused", "try" })
public static void tickTileEntity(final TrackedWorldBridge mixinWorldServer, final TickableBlockEntity tile) {
    checkArgument(tile instanceof BlockEntity, "ITickable %s is not a TileEntity!", tile);
    checkNotNull(tile, "Cannot capture on a null ticking tile entity!");
    final net.minecraft.world.level.block.entity.BlockEntity tileEntity = (net.minecraft.world.level.block.entity.BlockEntity) tile;
    final BlockEntityBridge mixinTileEntity = (BlockEntityBridge) tile;
    final BlockPos pos = tileEntity.getBlockPos();
    final LevelChunkBridge chunk = ((ActiveChunkReferantBridge) tile).bridge$getActiveChunk();
    if (!((TrackableBridge) tileEntity).bridge$shouldTick()) {
        return;
    }
    if (chunk == null) {
        ((ActiveChunkReferantBridge) tile).bridge$setActiveChunk((TrackedLevelChunkBridge) tileEntity.getLevel().getChunkAt(tileEntity.getBlockPos()));
    }
    final TileEntityTickContext context = TickPhase.Tick.TILE_ENTITY.createPhaseContext(PhaseTracker.SERVER).source(mixinTileEntity);
    try (final PhaseContext<?> phaseContext = context) {
        if (tile instanceof CreatorTrackedBridge) {
            // Add notifier and owner so we don't have to perform lookups during the phases and other processing
            ((CreatorTrackedBridge) tile).tracker$getNotifierUUID().ifPresent(phaseContext::notifier);
            // Allow the tile entity to validate the owner of itself. As long as the tile entity
            // chunk is already loaded and activated, and the tile entity has already loaded
            // the owner of itself.
            ((CreatorTrackedBridge) tile).tracker$getCreatorUUID().ifPresent(phaseContext::creator);
        }
        // Finally, switch the context now that we have the owner and notifier
        phaseContext.buildAndSwitch();
        try (final Timing timing = ((TimingBridge) tileEntity.getType()).bridge$timings().startTiming()) {
            tile.tick();
        }
        // otherwise the viewing players update this during their ticking
        if (tileEntity instanceof ViewableInventoryBridge) {
            final Set<ServerPlayer> players = ((ViewableInventoryBridge) tileEntity).viewableBridge$getViewers();
            if (players.size() > 0) {
                players.forEach(player -> player.containerMenu.broadcastChanges());
            }
        }
    } catch (final Exception e) {
        PhasePrinter.printExceptionFromPhase(PhaseTracker.getInstance().stack, e, context);
    }
    // We delay clearing active chunk if TE is invalidated during tick so we must remove it after
    if (tileEntity.isRemoved()) {
        ((ActiveChunkReferantBridge) tileEntity).bridge$setActiveChunk(null);
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) BlockEntityBridge(org.spongepowered.common.bridge.world.level.block.entity.BlockEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge) ViewableInventoryBridge(org.spongepowered.common.bridge.world.inventory.ViewableInventoryBridge) ServerPlayer(net.minecraft.server.level.ServerPlayer) BlockPos(net.minecraft.core.BlockPos) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) TrackedLevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.TrackedLevelChunkBridge) Timing(co.aikar.timings.Timing) TileEntityTickContext(org.spongepowered.common.event.tracking.phase.tick.TileEntityTickContext) TickableBlockEntity(net.minecraft.world.level.block.entity.TickableBlockEntity) BlockEntity(org.spongepowered.api.block.entity.BlockEntity)

Example 4 with CreatorTrackedBridge

use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method callDestructEntityEventDeath.

public static DestructEntityEvent.Death callDestructEntityEventDeath(final LivingEntity entity, @Nullable final DamageSource source, final Audience originalChannel) {
    final Component originalMessage;
    Optional<UUID> sourceCreator = Optional.empty();
    final boolean messageCancelled = false;
    if (source instanceof EntityDamageSource) {
        final EntityDamageSource damageSource = (EntityDamageSource) source;
        if (damageSource.getDirectEntity() instanceof CreatorTrackedBridge) {
            final CreatorTrackedBridge creatorBridge = (CreatorTrackedBridge) damageSource.getDirectEntity();
            if (creatorBridge != null) {
                sourceCreator = creatorBridge.tracker$getCreatorUUID();
            }
        }
    }
    originalMessage = SpongeAdventure.asAdventure(entity.getCombatTracker().getDeathMessage());
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        if (source != null) {
            frame.pushCause(source);
        }
        sourceCreator.ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
        final DestructEntityEvent.Death event = SpongeEventFactory.createDestructEntityEventDeath(frame.currentCause(), originalChannel, Optional.of(originalChannel), originalMessage, originalMessage, (Living) entity, entity.level.getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY), messageCancelled);
        SpongeCommon.post(event);
        return event;
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) DestructEntityEvent(org.spongepowered.api.event.entity.DestructEntityEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager) Component(net.kyori.adventure.text.Component) UUID(java.util.UUID) EntityDamageSource(net.minecraft.world.damagesource.EntityDamageSource)

Example 5 with CreatorTrackedBridge

use of org.spongepowered.common.bridge.CreatorTrackedBridge in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method handleCollideBlockEvent.

public static boolean handleCollideBlockEvent(final Block block, final Level world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState state, final net.minecraft.world.entity.Entity entity, final Direction direction, final CollisionType type) {
    if (world.isClientSide() || pos.getY() <= 0) {
        return false;
    }
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        frame.pushCause(entity);
        if (entity instanceof CreatorTrackedBridge) {
            final CreatorTrackedBridge spongeEntity = (CreatorTrackedBridge) entity;
            spongeEntity.tracker$getCreatorUUID().ifPresent(user -> frame.addContext(EventContextKeys.CREATOR, user));
        }
        // TODO: Add target side support
        final ServerLocation loc = ServerLocation.of((ServerWorld) world, VecHelper.toVector3d(pos));
        final CollideBlockEvent event;
        switch(type) {
            case MOVE:
                event = SpongeEventFactory.createCollideBlockEventMove(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case FALL:
                event = SpongeEventFactory.createCollideBlockEventFall(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case STEP_ON:
                event = SpongeEventFactory.createCollideBlockEventStepOn(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            case INSIDE:
                event = SpongeEventFactory.createCollideBlockEventInside(frame.currentCause(), (BlockState) state, loc, direction);
                break;
            default:
                throw new IllegalArgumentException("Unknown type " + type);
        }
        final boolean cancelled = SpongeCommon.post(event);
        if (!cancelled) {
            final EntityBridge spongeEntity = (EntityBridge) entity;
            if (!pos.equals(spongeEntity.bridge$getLastCollidedBlockPos())) {
                final PhaseContext<?> context = PhaseTracker.getInstance().getPhaseContext();
                context.applyNotifierIfAvailable(notifier -> {
                    LevelChunkBridge spongeChunk = ((ActiveChunkReferantBridge) entity).bridge$getActiveChunk();
                    if (spongeChunk == null) {
                        spongeChunk = (LevelChunkBridge) world.getChunkAt(pos);
                    }
                    spongeChunk.bridge$addTrackedBlockPosition(block, pos, notifier, PlayerTracker.Type.NOTIFIER);
                });
            }
        }
        return cancelled;
    }
}
Also used : CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) BlockState(org.spongepowered.api.block.BlockState) ServerLocation(org.spongepowered.api.world.server.ServerLocation) CauseStackManager(org.spongepowered.api.event.CauseStackManager) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)

Aggregations

CreatorTrackedBridge (org.spongepowered.common.bridge.CreatorTrackedBridge)14 Entity (net.minecraft.world.entity.Entity)5 LevelChunkBridge (org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge)5 ServerPlayer (net.minecraft.server.level.ServerPlayer)4 Entity (org.spongepowered.api.entity.Entity)4 Timing (co.aikar.timings.Timing)3 BlockPos (net.minecraft.core.BlockPos)3 TickableBlockEntity (net.minecraft.world.level.block.entity.TickableBlockEntity)3 BlockEntity (org.spongepowered.api.block.entity.BlockEntity)3 Inject (org.spongepowered.asm.mixin.injection.Inject)3 ActiveChunkReferantBridge (org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge)3 UUID (java.util.UUID)2 ServerboundInteractPacket (net.minecraft.network.protocol.game.ServerboundInteractPacket)2 DamageSource (net.minecraft.world.damagesource.DamageSource)2 EntityDamageSource (net.minecraft.world.damagesource.EntityDamageSource)2 LivingEntity (net.minecraft.world.entity.LivingEntity)2 CauseStackManager (org.spongepowered.api.event.CauseStackManager)2 TimingBridge (org.spongepowered.common.bridge.TimingBridge)2 LevelBridge (org.spongepowered.common.bridge.world.level.LevelBridge)2 EntityTickContext (org.spongepowered.common.event.tracking.phase.tick.EntityTickContext)2