Search in sources :

Example 6 with IMixinLocation

use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.

the class MixinTeleporter method findPortal.

@Override
public Optional<Location<World>> findPortal(Location<World> searchLocation) {
    double closest = -1.0D;
    boolean addToCache = true;
    BlockPos portalPosition = BlockPos.ORIGIN;
    // Sponge - use the chunk coords instead of block coords
    Vector3i chunkPosition = searchLocation.getChunkPosition();
    long targetPosition = ChunkPos.asLong(chunkPosition.getX(), chunkPosition.getZ());
    if (this.destinationCoordinateCache.containsKey(targetPosition)) {
        Teleporter.PortalPosition teleporter$portalposition = this.destinationCoordinateCache.get(targetPosition);
        closest = 0.0D;
        portalPosition = teleporter$portalposition;
        teleporter$portalposition.lastUpdateTime = this.world.getTotalWorldTime();
        addToCache = false;
    } else {
        BlockPos blockSearchPosition = ((IMixinLocation) (Object) searchLocation).getBlockPos();
        for (int i1 = -this.searchRadius; i1 <= this.searchRadius; ++i1) {
            BlockPos blockpos2;
            for (int j1 = -this.searchRadius; j1 <= this.searchRadius; ++j1) {
                for (BlockPos blockpos1 = blockSearchPosition.add(i1, this.world.getActualHeight() - 1 - blockSearchPosition.getY(), j1); blockpos1.getY() >= 0; blockpos1 = blockpos2) {
                    blockpos2 = blockpos1.down();
                    if (this.world.getBlockState(blockpos1).getBlock() == Blocks.PORTAL) {
                        while (this.world.getBlockState(blockpos2 = blockpos1.down()).getBlock() == Blocks.PORTAL) {
                            blockpos1 = blockpos2;
                        }
                        double distance = blockpos1.distanceSq(blockSearchPosition);
                        if (closest < 0.0D || distance < closest) {
                            closest = distance;
                            portalPosition = blockpos1;
                        }
                    }
                }
            }
        }
    }
    if (closest >= 0.0D) {
        if (addToCache) {
            this.destinationCoordinateCache.put(targetPosition, ((Teleporter) (Object) this).new PortalPosition(portalPosition, this.world.getTotalWorldTime()));
        }
        return Optional.of(new Location<World>(searchLocation.getExtent(), VecHelper.toVector3d(portalPosition)));
    }
    return Optional.empty();
}
Also used : IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) IMixinTeleporter(org.spongepowered.common.interfaces.world.IMixinTeleporter) Teleporter(net.minecraft.world.Teleporter) World(org.spongepowered.api.world.World) Vector3i(com.flowpowered.math.vector.Vector3i) BlockPos(net.minecraft.util.math.BlockPos)

Example 7 with IMixinLocation

use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.

the class MixinTeleporter method handleEntityPortalExit.

private void handleEntityPortalExit(Entity entityIn, Location<World> portalLocation, float rotationYaw) {
    BlockPos blockPos = ((IMixinLocation) (Object) portalLocation).getBlockPos();
    double xTarget = portalLocation.getX() + 0.5D;
    double yTarget = portalLocation.getY() + 0.5D;
    double zTarget = portalLocation.getZ() + 0.5D;
    BlockPattern.PatternHelper blockpattern$patternhelper = Blocks.PORTAL.createPatternHelper(this.world, blockPos);
    boolean flag1 = blockpattern$patternhelper.getForwards().rotateY().getAxisDirection() == EnumFacing.AxisDirection.NEGATIVE;
    double d2 = blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X ? (double) blockpattern$patternhelper.getFrontTopLeft().getZ() : (double) blockpattern$patternhelper.getFrontTopLeft().getX();
    yTarget = blockpattern$patternhelper.getFrontTopLeft().getY() + 1 - entityIn.getLastPortalVec().y * blockpattern$patternhelper.getHeight();
    if (flag1) {
        ++d2;
    }
    if (blockpattern$patternhelper.getForwards().getAxis() == EnumFacing.Axis.X) {
        zTarget = d2 + (1.0D - entityIn.getLastPortalVec().x) * blockpattern$patternhelper.getWidth() * blockpattern$patternhelper.getForwards().rotateY().getAxisDirection().getOffset();
    } else {
        xTarget = d2 + (1.0D - entityIn.getLastPortalVec().x) * blockpattern$patternhelper.getWidth() * blockpattern$patternhelper.getForwards().rotateY().getAxisDirection().getOffset();
    }
    float f = 0.0F;
    float f1 = 0.0F;
    float f2 = 0.0F;
    float f3 = 0.0F;
    if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection()) {
        f = 1.0F;
        f1 = 1.0F;
    } else if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection().getOpposite()) {
        f = -1.0F;
        f1 = -1.0F;
    } else if (blockpattern$patternhelper.getForwards().getOpposite() == entityIn.getTeleportDirection().rotateY()) {
        f2 = 1.0F;
        f3 = -1.0F;
    } else {
        f2 = -1.0F;
        f3 = 1.0F;
    }
    double d3 = entityIn.motionX;
    double d4 = entityIn.motionZ;
    entityIn.motionX = d3 * f + d4 * f3;
    entityIn.motionZ = d3 * f2 + d4 * f1;
    entityIn.rotationYaw = rotationYaw - entityIn.getTeleportDirection().getOpposite().getHorizontalIndex() * 90 + blockpattern$patternhelper.getForwards().getHorizontalIndex() * 90;
    entityIn.setLocationAndAngles(xTarget, yTarget, zTarget, entityIn.rotationYaw, entityIn.rotationPitch);
}
Also used : IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) BlockPattern(net.minecraft.block.state.pattern.BlockPattern) BlockPos(net.minecraft.util.math.BlockPos)

Example 8 with IMixinLocation

use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.

the class RandomBlockPopulator method populate.

@Override
public void populate(org.spongepowered.api.world.World world, Extent extent, Random random) {
    Vector3i min = extent.getBlockMin();
    Vector3i size = extent.getBlockSize();
    int n = this.count.getFlooredAmount(random);
    Location<World> chunkMin = new Location<World>(world, min.getX(), min.getY(), min.getZ());
    for (int i = 0; i < n; i++) {
        Location<World> pos = chunkMin.add(random.nextInt(size.getX()), this.height.getFlooredAmount(random), random.nextInt(size.getZ()));
        if (this.check.test(pos)) {
            world.setBlock(pos.getBlockPosition(), this.state);
            // Liquids force a block update tick so they may flow during world gen
            try {
                ((WorldServer) world).immediateBlockTick(((IMixinLocation) (Object) pos).getBlockPos(), (IBlockState) this.state, random);
            } catch (IllegalArgumentException e) {
            // ignore
            }
        }
    }
}
Also used : Vector3i(com.flowpowered.math.vector.Vector3i) WorldServer(net.minecraft.world.WorldServer) World(org.spongepowered.api.world.World) Location(org.spongepowered.api.world.Location) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation)

Example 9 with IMixinLocation

use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeForge by SpongePowered.

the class SpongeForgeEventFactory method callNeighborNotifyEvent.

public static NotifyNeighborBlockEvent callNeighborNotifyEvent(Event event) {
    NotifyNeighborBlockEvent spongeEvent = (NotifyNeighborBlockEvent) event;
    LocatableBlock locatableBlock = spongeEvent.getCause().first(LocatableBlock.class).orElse(null);
    TileEntity tileEntitySource = spongeEvent.getCause().first(TileEntity.class).orElse(null);
    Location<World> sourceLocation = null;
    IBlockState state = null;
    if (locatableBlock != null) {
        Location<World> location = locatableBlock.getLocation();
        sourceLocation = location;
        state = (IBlockState) locatableBlock.getBlockState();
    } else if (tileEntitySource != null) {
        sourceLocation = tileEntitySource.getLocation();
        state = (IBlockState) sourceLocation.getBlock();
    } else {
        // should never happen but just in case it does
        return spongeEvent;
    }
    EnumSet<EnumFacing> facings = EnumSet.noneOf(EnumFacing.class);
    for (Map.Entry<Direction, BlockState> mapEntry : spongeEvent.getNeighbors().entrySet()) {
        if (mapEntry.getKey() != Direction.NONE) {
            facings.add(DirectionFacingProvider.getInstance().get(mapEntry.getKey()).get());
        }
    }
    if (facings.isEmpty()) {
        return spongeEvent;
    }
    BlockPos pos = ((IMixinLocation) (Object) sourceLocation).getBlockPos();
    net.minecraft.world.World world = (net.minecraft.world.World) sourceLocation.getExtent();
    // TODO - the boolean forced redstone bit needs to be set properly
    final NeighborNotifyEvent forgeEvent = new NeighborNotifyEvent(world, pos, state, facings, false);
    ((IMixinEventBus) MinecraftForge.EVENT_BUS).post(forgeEvent, true);
    if (forgeEvent.isCanceled()) {
        spongeEvent.setCancelled(true);
    }
    return spongeEvent;
}
Also used : IBlockState(net.minecraft.block.state.IBlockState) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) EnumFacing(net.minecraft.util.EnumFacing) World(org.spongepowered.api.world.World) IMixinWorld(org.spongepowered.common.interfaces.world.IMixinWorld) Direction(org.spongepowered.api.util.Direction) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) IMixinEventBus(org.spongepowered.mod.interfaces.IMixinEventBus) NotifyNeighborBlockEvent(org.spongepowered.api.event.block.NotifyNeighborBlockEvent) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) NeighborNotifyEvent(net.minecraftforge.event.world.BlockEvent.NeighborNotifyEvent) LocatableBlock(org.spongepowered.api.world.LocatableBlock) BlockPos(net.minecraft.util.math.BlockPos) Map(java.util.Map)

Example 10 with IMixinLocation

use of org.spongepowered.common.interfaces.world.IMixinLocation in project SpongeCommon by SpongePowered.

the class TrackingUtil method processBlockCaptures.

/**
 * Processes the given list of {@link BlockSnapshot}s and creates and throws and processes
 * the {@link ChangeBlockEvent}s as appropriately determined based on the {@link BlockChange}
 * for each snapshot. If any transactions are invalid or events cancelled, this event
 * returns {@code false} to signify a transaction was cancelled. This return value
 * is used for portal creation.
 *
 * @param snapshots The snapshots to process
 * @param state The phase state that is being processed, used to handle marking notifiers
 *  and block owners
 * @param context The phase context, only used by the phase for handling processes.
 * @return True if no events or transactions were cancelled
 */
@SuppressWarnings({ "unchecked" })
public static boolean processBlockCaptures(List<BlockSnapshot> snapshots, IPhaseState<?> state, PhaseContext<?> context) {
    if (snapshots.isEmpty()) {
        return false;
    }
    ImmutableList<Transaction<BlockSnapshot>>[] transactionArrays = new ImmutableList[EVENT_COUNT];
    ImmutableList.Builder<Transaction<BlockSnapshot>>[] transactionBuilders = new ImmutableList.Builder[EVENT_COUNT];
    for (int i = 0; i < EVENT_COUNT; i++) {
        transactionBuilders[i] = new ImmutableList.Builder<>();
    }
    final List<ChangeBlockEvent> blockEvents = new ArrayList<>();
    for (BlockSnapshot snapshot : snapshots) {
        // This processes each snapshot to assign them to the correct event in the next area, with the
        // correct builder array entry.
        TRANSACTION_PROCESSOR.apply(transactionBuilders).accept(TRANSACTION_CREATION.apply(snapshot));
    }
    for (int i = 0; i < EVENT_COUNT; i++) {
        // Build each event array
        transactionArrays[i] = transactionBuilders[i].build();
    }
    // Clear captured snapshots after processing them
    context.getCapturedBlocksOrEmptyList().clear();
    final ChangeBlockEvent[] mainEvents = new ChangeBlockEvent[BlockChange.values().length];
    // case in point for WorldTick event listeners since the players are captured non-deterministically
    try (CauseStackManager.StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        if (context.getNotifier().isPresent()) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.NOTIFIER, context.getNotifier().get());
        }
        if (context.getOwner().isPresent()) {
            Sponge.getCauseStackManager().addContext(EventContextKeys.OWNER, context.getOwner().get());
        }
        try {
            state.associateAdditionalCauses(state, context);
        } catch (Exception e) {
        // TODO - this should be a thing to associate additional objects in the cause, or context, but for now it's just a simple
        // try catch to avoid bombing on performing block changes.
        }
        // Creates the block events accordingly to the transaction arrays
        // Needs to throw events
        iterateChangeBlockEvents(transactionArrays, blockEvents, mainEvents);
        // We create the post event and of course post it in the method, regardless whether any transactions are invalidated or not
        final ChangeBlockEvent.Post postEvent = throwMultiEventsAndCreatePost(transactionArrays, blockEvents, mainEvents);
        if (postEvent == null) {
            // Means that we have had no actual block changes apparently?
            return false;
        }
        final List<Transaction<BlockSnapshot>> invalid = new ArrayList<>();
        boolean noCancelledTransactions = true;
        // transactions of the preceeding block events)
        for (ChangeBlockEvent blockEvent : blockEvents) {
            // Need to only check if the event is cancelled, If it is, restore
            if (blockEvent.isCancelled()) {
                noCancelledTransactions = false;
                // Don't restore the transactions just yet, since we're just marking them as invalid for now
                for (Transaction<BlockSnapshot> transaction : Lists.reverse(blockEvent.getTransactions())) {
                    transaction.setValid(false);
                }
            }
        }
        // Finally check the post event
        if (postEvent.isCancelled()) {
            // Of course, if post is cancelled, just mark all transactions as invalid.
            noCancelledTransactions = false;
            for (Transaction<BlockSnapshot> transaction : postEvent.getTransactions()) {
                transaction.setValid(false);
            }
        }
        // Because after, we will restore all the invalid transactions in reverse order.
        for (Transaction<BlockSnapshot> transaction : postEvent.getTransactions()) {
            if (!transaction.isValid()) {
                invalid.add(transaction);
                // Cancel any block drops performed, avoids any item drops, regardless
                final Location<World> location = transaction.getOriginal().getLocation().orElse(null);
                if (location != null) {
                    final BlockPos pos = ((IMixinLocation) (Object) location).getBlockPos();
                    context.getBlockItemDropSupplier().removeAllIfNotEmpty(pos);
                    context.getBlockEntitySpawnSupplier().removeAllIfNotEmpty(pos);
                    context.getBlockEntitySpawnSupplier().removeAllIfNotEmpty(pos);
                }
            }
        }
        if (!invalid.isEmpty()) {
            // We need to set this value and return it to signify that some transactions were cancelled
            noCancelledTransactions = false;
            // or the events were cancelled), again in reverse order of which they were received.
            for (Transaction<BlockSnapshot> transaction : Lists.reverse(invalid)) {
                transaction.getOriginal().restore(true, BlockChangeFlags.NONE);
                if (state.tracksBlockSpecificDrops()) {
                    // Cancel any block drops or harvests for the block change.
                    // This prevents unnecessary spawns.
                    final Location<World> location = transaction.getOriginal().getLocation().orElse(null);
                    if (location != null) {
                        final BlockPos pos = ((IMixinLocation) (Object) location).getBlockPos();
                        context.getBlockDropSupplier().removeAllIfNotEmpty(pos);
                    }
                }
            }
        }
        return performBlockAdditions(postEvent.getTransactions(), state, context, noCancelledTransactions);
    }
}
Also used : StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) ImmutableList(com.google.common.collect.ImmutableList) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) ArrayList(java.util.ArrayList) World(org.spongepowered.api.world.World) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) Transaction(org.spongepowered.api.data.Transaction) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BlockPos(net.minecraft.util.math.BlockPos)

Aggregations

IMixinLocation (org.spongepowered.common.interfaces.world.IMixinLocation)19 BlockPos (net.minecraft.util.math.BlockPos)17 World (org.spongepowered.api.world.World)16 ArrayList (java.util.ArrayList)8 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)7 ImmutableList (com.google.common.collect.ImmutableList)5 IBlockState (net.minecraft.block.state.IBlockState)5 Transaction (org.spongepowered.api.data.Transaction)5 ChangeBlockEvent (org.spongepowered.api.event.block.ChangeBlockEvent)4 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)4 EntityLivingBase (net.minecraft.entity.EntityLivingBase)3 EntityItem (net.minecraft.entity.item.EntityItem)3 EntityPlayer (net.minecraft.entity.player.EntityPlayer)3 WorldServer (net.minecraft.world.WorldServer)3 Player (org.spongepowered.api.entity.living.player.Player)3 CauseStackManager (org.spongepowered.api.event.CauseStackManager)3 Location (org.spongepowered.api.world.Location)3 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)3 Vector3i (com.flowpowered.math.vector.Vector3i)2 Collection (java.util.Collection)2