Search in sources :

Example 6 with LevelBridge

use of org.spongepowered.common.bridge.world.level.LevelBridge in project SpongeCommon by SpongePowered.

the class ChunkMapMixin_Tracker method tracker$startLoad.

@Redirect(method = "*", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;runPostLoad()V"), slice = @Slice(from = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/chunk/LevelChunk;setFullStatus(Ljava/util/function/Supplier;)V"), to = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ServerLevel;addAllPendingBlockEntities(Ljava/util/Collection;)V")))
private void tracker$startLoad(final LevelChunk chunk) {
    chunk.runPostLoad();
    final boolean isFake = ((LevelBridge) chunk.getLevel()).bridge$isFake();
    if (isFake) {
        return;
    }
    if (!PhaseTracker.SERVER.onSidedThread()) {
        new PrettyPrinter(60).add("Illegal Async Chunk Load").centre().hr().addWrapped("Sponge relies on knowing when chunks are being loaded as chunks add entities" + " to the parented world for management. These operations are generally not" + " threadsafe and shouldn't be considered a \"Sponge bug \". Adding/removing" + " entities from another thread to the world is never ok.").add().add(" %s : %s", "Chunk Pos", chunk.getPos().toString()).add().add(new Exception("Async Chunk Load Detected")).log(SpongeCommon.logger(), Level.ERROR);
        return;
    }
    if (PhaseTracker.getInstance().getCurrentState() == GenerationPhase.State.CHUNK_REGENERATING_LOAD_EXISTING) {
        return;
    }
    GenerationPhase.State.CHUNK_LOADING.createPhaseContext(PhaseTracker.getInstance()).source(chunk).world((ServerLevel) chunk.getLevel()).chunk(chunk).buildAndSwitch();
}
Also used : PrettyPrinter(org.spongepowered.common.util.PrettyPrinter) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 7 with LevelBridge

use of org.spongepowered.common.bridge.world.level.LevelBridge in project SpongeCommon by SpongePowered.

the class ServerPlayerMixin_Tracker method tracker$throwItemDrop.

/**
 * @author gabizou - June 4th, 2016
 * @author i509VCB - February 17th, 2020 - 1.14.4
 * @author gabizou - December 31st, 2021 - 1.16.5
 * @reason We inject a construct event for the item drop and conveniently
 * can redirect the super call.
 */
@Redirect(method = "drop", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;"))
@Nullable
private ItemEntity tracker$throwItemDrop(final Player thisPlayer, final ItemStack droppedItem, final boolean dropAround, final boolean traceItem) {
    if (droppedItem.isEmpty()) {
        return null;
    }
    if (((PlatformEntityBridge) this).bridge$isFakePlayer()) {
        return super.shadow$drop(droppedItem, dropAround, traceItem);
    }
    if (((LevelBridge) this.level).bridge$isFake()) {
        return super.shadow$drop(droppedItem, dropAround, traceItem);
    }
    final double posX1 = this.shadow$getX();
    final double posY1 = this.shadow$getEyeY() - (double) 0.3F;
    final double posZ1 = this.shadow$getZ();
    // Now the real fun begins.
    final ItemStack item;
    final ItemStackSnapshot snapshot = ItemStackUtil.snapshotOf(droppedItem);
    final List<ItemStackSnapshot> original = new ArrayList<>();
    original.add(snapshot);
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getCauseStackManager().pushCauseFrame()) {
        item = SpongeCommonEventFactory.throwDropItemAndConstructEvent((ServerPlayer) (Object) this, posX1, posY1, posZ1, snapshot, original, frame);
        if (item == null || item.isEmpty()) {
            return null;
        }
        // Here is where we would potentially perform item pre-merging (merge the item stacks with previously captured item stacks
        // and only if those stacks can be stacked (count increased). Otherwise, we'll just continue to throw the entity item.
        // For now, due to refactoring a majority of all of this code, pre-merging is disabled entirely.
        final ItemEntity itemEntity = new ItemEntity(this.level, posX1, posY1, posZ1, droppedItem);
        itemEntity.setPickUpDelay(40);
        if (traceItem) {
            itemEntity.setThrower(this.shadow$getUUID());
        }
        final Random random = this.shadow$getRandom();
        if (dropAround) {
            final float f = random.nextFloat() * 0.5F;
            final float f1 = random.nextFloat() * ((float) Math.PI * 2F);
            itemEntity.setDeltaMovement(-Mth.sin(f1) * f, 0.2F, Mth.cos(f1) * f);
        } else {
            final float f8 = Mth.sin(this.xRot * ((float) Math.PI / 180F));
            final float f2 = Mth.cos(this.xRot * ((float) Math.PI / 180F));
            final float f3 = Mth.sin(this.yRot * ((float) Math.PI / 180F));
            final float f4 = Mth.cos(this.yRot * ((float) Math.PI / 180F));
            final float f5 = this.random.nextFloat() * ((float) Math.PI * 2F);
            final float f6 = 0.02F * this.random.nextFloat();
            itemEntity.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos(f5) * (double) f6, (-f8 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin(f5) * (double) f6);
        }
        return itemEntity;
    }
}
Also used : ItemEntity(net.minecraft.world.entity.item.ItemEntity) ArrayList(java.util.ArrayList) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) Random(java.util.Random) CauseStackManager(org.spongepowered.api.event.CauseStackManager) ServerPlayer(net.minecraft.server.level.ServerPlayer) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) ItemStack(net.minecraft.world.item.ItemStack) Redirect(org.spongepowered.asm.mixin.injection.Redirect) Nullable(org.checkerframework.checker.nullness.qual.Nullable)

Example 8 with LevelBridge

use of org.spongepowered.common.bridge.world.level.LevelBridge in project SpongeCommon by SpongePowered.

the class LivingEntityMixin_Tracker method tracker$enterDeathPhase.

/**
 * @author i509VCB
 * @author gabizou
 *
 * @reason We can enter in to the entity drops transaction here which will
 * successfully batch the side effects (this is effectively a singular side
 * effect/transaction instead of a pipeline) to perform some things around
 * the entity's death. This successfully records the transactions associated
 * with this entity entering into the death state.
 */
@Redirect(method = "baseTick()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;tickDeath()V"))
private void tracker$enterDeathPhase(final LivingEntity livingEntity) {
    final PhaseTracker instance = PhaseTracker.SERVER;
    if (!instance.onSidedThread()) {
        this.shadow$tickDeath();
        return;
    }
    if (((LevelBridge) this.level).bridge$isFake()) {
        this.shadow$tickDeath();
        return;
    }
    final PhaseContext<@NonNull ?> context = instance.getPhaseContext();
    if (!context.doesBlockEventTracking()) {
        this.shadow$tickDeath();
        return;
    }
    try (final EffectTransactor ignored = context.getTransactor().ensureEntityDropTransactionEffect((LivingEntity) (Object) this)) {
        this.shadow$tickDeath();
    }
}
Also used : PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) EffectTransactor(org.spongepowered.common.event.tracking.context.transaction.EffectTransactor) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Example 9 with LevelBridge

use of org.spongepowered.common.bridge.world.level.LevelBridge in project SpongeCommon by SpongePowered.

the class EntityActivationRange method activateEntities.

/**
 * Find what entities are in range of the players in the world and set
 * active if in range.
 *
 * @param world The world to perform activation checks in
 */
public static void activateEntities(final ServerLevel world) {
    if (((LevelBridge) world).bridge$isFake()) {
        return;
    }
    for (final ServerPlayer player : world.players()) {
        int maxRange = 0;
        for (final Integer range : EntityActivationRange.maxActivationRanges.values()) {
            if (range > maxRange) {
                maxRange = range;
            }
        }
        maxRange = Math.min((((ServerWorld) world).properties().viewDistance() << 4) - 8, maxRange);
        ((ActivationCapabilityBridge) player).activation$setActivatedTick(SpongeCommon.server().getTickCount());
        final AABB aabb = EntityActivationRange.maxBB;
        EntityActivationRange.growBb(aabb, player.getBoundingBox(), maxRange, 256, maxRange);
        final int i = Mth.floor(aabb.minX / 16.0D);
        final int j = Mth.floor(aabb.maxX / 16.0D);
        final int k = Mth.floor(aabb.minZ / 16.0D);
        final int l = Mth.floor(aabb.maxZ / 16.0D);
        for (int i1 = i; i1 <= j; ++i1) {
            for (int j1 = k; j1 <= l; ++j1) {
                final LevelChunk chunk = world.getChunkSource().getChunkNow(i1, j1);
                if (chunk != null) {
                    EntityActivationRange.activateChunkEntities(player, chunk);
                }
            }
        }
    }
}
Also used : ServerWorld(org.spongepowered.api.world.server.ServerWorld) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) ActivationCapabilityBridge(org.spongepowered.common.bridge.activation.ActivationCapabilityBridge) ServerPlayer(net.minecraft.server.level.ServerPlayer) AABB(net.minecraft.world.phys.AABB)

Example 10 with LevelBridge

use of org.spongepowered.common.bridge.world.level.LevelBridge in project SpongeCommon by SpongePowered.

the class LevelChunkMixin_Tracker method bridge$createChunkPipeline.

/**
 * Technically a full overwrite for {@link LevelChunk#setBlockState(BlockPos, BlockState, boolean)}
 * and due to Sponge's hijacking of {@link ServerLevel#setBlock(BlockPos, BlockState, int)},
 * it needs to be able to record transactions when necessary. This implementation allows for us to
 * further specify the types of transactions and what proxies are needing to set up where.
 *
 * @param pos The position changing
 * @param newState The new state
 * @param currentState The current state - passed in from either chunk or world
 * @param flag The sponge change flag, converted from an int to a proper struct
 * @return The changed block state if not null
 * @author gabizou - January 13th, 2020 - Minecraft 1.14.3
 */
@Override
@NonNull
public ChunkPipeline bridge$createChunkPipeline(final BlockPos pos, final BlockState newState, final BlockState currentState, final SpongeBlockChangeFlag flag, final int limit) {
    final boolean isFake = ((LevelBridge) this.level).bridge$isFake();
    if (isFake) {
        throw new IllegalStateException("Cannot call ChunkBridge.bridge$buildChunkPipeline in non-Server managed worlds");
    }
    // int i = pos.getX() & 15;
    final int xPos = pos.getX() & 15;
    // int j = pos.getY();
    final int yPos = pos.getY();
    // int k = pos.getZ() & 15;
    final int zPos = pos.getZ() & 15;
    // Sponge - get the moving flag from our flag construct
    LevelChunkSection chunksection = this.sections[yPos >> 4];
    if (chunksection == LevelChunkMixin_Tracker.EMPTY_SECTION) {
        if (newState.isAir()) {
            return ChunkPipeline.nullReturn((LevelChunk) (Object) this, (ServerLevel) this.level);
        }
        chunksection = new LevelChunkSection(yPos >> 4 << 4);
        this.sections[yPos >> 4] = chunksection;
    }
    // Sponge Start - Build out the BlockTransaction
    final PhaseContext<@NonNull ?> context = PhaseTracker.getInstance().getPhaseContext();
    @Nullable final BlockEntity existing = this.shadow$getBlockEntity(pos, LevelChunk.EntityCreationType.CHECK);
    // Build a transaction maybe?
    final WeakReference<ServerLevel> ref = new WeakReference<>((ServerLevel) this.level);
    final SpongeBlockSnapshot snapshot = TrackingUtil.createPooledSnapshot(currentState, pos, flag, limit, existing, () -> Objects.requireNonNull(ref.get(), "ServerWorld dereferenced"), Optional::empty, Optional::empty);
    // Pulled up from below
    final ChangeBlock transaction = context.createTransaction(snapshot, newState, flag);
    snapshot.blockChange = context.associateBlockChangeWithSnapshot(newState, currentState);
    if (((BlockStateBridge) snapshot.state()).bridge$hasTileEntity() && (snapshot.blockChange == BlockChange.BREAK || snapshot.blockChange == BlockChange.MODIFY)) {
        transaction.queuedRemoval = existing;
    }
    final ChunkPipeline.Builder builder = ChunkPipeline.builder().kickOff(transaction).chunk((LevelChunk) (Object) this).chunkSection(chunksection).world((ServerLevel) this.level);
    // Populate the effects
    transaction.populateChunkEffects(builder);
    return builder.build();
}
Also used : ServerLevel(net.minecraft.server.level.ServerLevel) Optional(java.util.Optional) ChangeBlock(org.spongepowered.common.event.tracking.context.transaction.block.ChangeBlock) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) LevelChunkSection(net.minecraft.world.level.chunk.LevelChunkSection) WeakReference(java.lang.ref.WeakReference) Nullable(org.checkerframework.checker.nullness.qual.Nullable) ChunkPipeline(org.spongepowered.common.event.tracking.context.transaction.pipeline.ChunkPipeline) BlockEntity(net.minecraft.world.level.block.entity.BlockEntity) MonotonicNonNull(org.checkerframework.checker.nullness.qual.MonotonicNonNull) NonNull(org.checkerframework.checker.nullness.qual.NonNull)

Aggregations

LevelBridge (org.spongepowered.common.bridge.world.level.LevelBridge)20 Inject (org.spongepowered.asm.mixin.injection.Inject)5 Redirect (org.spongepowered.asm.mixin.injection.Redirect)5 Entity (net.minecraft.world.entity.Entity)4 LivingEntity (net.minecraft.world.entity.LivingEntity)3 ItemEntity (net.minecraft.world.entity.item.ItemEntity)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)3 EffectTransactor (org.spongepowered.common.event.tracking.context.transaction.EffectTransactor)3 ArrayList (java.util.ArrayList)2 ServerLevel (net.minecraft.server.level.ServerLevel)2 ServerPlayer (net.minecraft.server.level.ServerPlayer)2 ItemStack (net.minecraft.world.item.ItemStack)2 BlockEntity (net.minecraft.world.level.block.entity.BlockEntity)2 Nullable (org.checkerframework.checker.nullness.qual.Nullable)2 ItemStackSnapshot (org.spongepowered.api.item.inventory.ItemStackSnapshot)2 ServerWorld (org.spongepowered.api.world.server.ServerWorld)2 CreatorTrackedBridge (org.spongepowered.common.bridge.CreatorTrackedBridge)2 MoreObjects (com.google.common.base.MoreObjects)1 WeakReference (java.lang.ref.WeakReference)1