Search in sources :

Example 6 with ChangeBlockEvent

use of org.spongepowered.api.event.block.ChangeBlockEvent in project HuskyCrates-Sponge by codeHusky.

the class HuskyCrates method placeBlock.

@Listener(order = Order.PRE)
public void placeBlock(ChangeBlockEvent event) {
    if (forceStop) {
        return;
    }
    if (event.getCause().root() instanceof Player) {
        Player plr = (Player) event.getCause().root();
        if (event instanceof ChangeBlockEvent.Place || event instanceof ChangeBlockEvent.Break) {
            BlockType t = event.getTransactions().get(0).getOriginal().getLocation().get().getBlock().getType();
            Location<World> location = event.getTransactions().get(0).getOriginal().getLocation().get();
            // System.out.println(event instanceof ChangeBlockEvent.Break);
            if (validCrateBlocks.contains(t)) {
                if (event instanceof ChangeBlockEvent.Place) {
                    if (plr.getItemInHand(HandTypes.MAIN_HAND).isPresent()) {
                        Optional<Object> tt = plr.getItemInHand(HandTypes.MAIN_HAND).get().toContainer().get(DataQuery.of("UnsafeData", "crateID"));
                        if (tt.isPresent()) {
                            String crateID = tt.get().toString();
                            if (!plr.hasPermission("huskycrates.tester")) {
                                event.setCancelled(true);
                                return;
                            }
                            if (!crateUtilities.physicalCrates.containsKey(location))
                                crateUtilities.physicalCrates.put(location, new PhysicalCrate(location, crateID, this, false));
                            crateUtilities.physicalCrates.get(location).createHologram();
                            try {
                                DBReader.saveHuskyData();
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                            return;
                        }
                    }
                }
            } else if (event instanceof ChangeBlockEvent.Break) {
                if (crateUtilities.physicalCrates.containsKey(location)) {
                    if (!plr.hasPermission("huskycrates.tester")) {
                        event.setCancelled(true);
                        return;
                    }
                    if (!crateUtilities.physicalCrates.get(location).isEntity)
                        crateUtilities.physicalCrates.get(location).ent.remove();
                    crateUtilities.physicalCrates.remove(location);
                    crateUtilities.brokenCrates.add(location);
                    try {
                        DBReader.saveHuskyData();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
Also used : Player(org.spongepowered.api.entity.living.player.Player) SQLException(java.sql.SQLException) PhysicalCrate(com.codehusky.huskycrates.crate.PhysicalCrate) World(org.spongepowered.api.world.World) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) BlockType(org.spongepowered.api.block.BlockType) JSONObject(org.json.JSONObject) Listener(org.spongepowered.api.event.Listener)

Example 7 with ChangeBlockEvent

use of org.spongepowered.api.event.block.ChangeBlockEvent in project SpongeCommon by SpongePowered.

the class TrackingUtil method iterateChangeBlockEvents.

public static void iterateChangeBlockEvents(ImmutableList<Transaction<BlockSnapshot>>[] transactionArrays, List<ChangeBlockEvent> blockEvents, ChangeBlockEvent[] mainEvents) {
    for (BlockChange blockChange : BlockChange.values()) {
        if (blockChange == BlockChange.DECAY) {
            // Decay takes place after.
            continue;
        }
        if (!transactionArrays[blockChange.ordinal()].isEmpty()) {
            final ChangeBlockEvent event = blockChange.createEvent(Sponge.getCauseStackManager().getCurrentCause(), transactionArrays[blockChange.ordinal()]);
            mainEvents[blockChange.ordinal()] = event;
            if (event != null) {
                SpongeImpl.postEvent(event);
                blockEvents.add(event);
            }
        }
    }
    if (!transactionArrays[BlockChange.DECAY.ordinal()].isEmpty()) {
        // Needs to be placed into iterateChangeBlockEvents
        final ChangeBlockEvent event = BlockChange.DECAY.createEvent(Sponge.getCauseStackManager().getCurrentCause(), transactionArrays[BlockChange.DECAY.ordinal()]);
        mainEvents[BlockChange.DECAY.ordinal()] = event;
        if (event != null) {
            SpongeImpl.postEvent(event);
            blockEvents.add(event);
        }
    }
}
Also used : ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) BlockChange(org.spongepowered.common.world.BlockChange)

Example 8 with ChangeBlockEvent

use of org.spongepowered.api.event.block.ChangeBlockEvent 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)

Example 9 with ChangeBlockEvent

use of org.spongepowered.api.event.block.ChangeBlockEvent in project SpongeCommon by SpongePowered.

the class ExplosionState method processBlockCaptures.

@SuppressWarnings({ "unchecked" })
private void processBlockCaptures(List<BlockSnapshot> snapshots, Explosion explosion, PhaseContext<?> context) {
    if (snapshots.isEmpty()) {
        return;
    }
    ImmutableList<Transaction<BlockSnapshot>>[] transactionArrays = new ImmutableList[TrackingUtil.EVENT_COUNT];
    ImmutableList.Builder<Transaction<BlockSnapshot>>[] transactionBuilders = new ImmutableList.Builder[TrackingUtil.EVENT_COUNT];
    for (int i = 0; i < TrackingUtil.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.
        TrackingUtil.TRANSACTION_PROCESSOR.apply(transactionBuilders).accept(TrackingUtil.TRANSACTION_CREATION.apply(snapshot));
    }
    for (int i = 0; i < TrackingUtil.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()) {
        try {
            this.associateAdditionalCauses(this, 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);
        // Copied from TrackingUtil#throwMultiEventsAndCreatePost
        for (BlockChange blockChange : BlockChange.values()) {
            final ChangeBlockEvent mainEvent = mainEvents[blockChange.ordinal()];
            if (mainEvent != null) {
                Sponge.getCauseStackManager().pushCause(mainEvent);
            }
        }
        final ImmutableList<Transaction<BlockSnapshot>> transactions = transactionArrays[TrackingUtil.MULTI_CHANGE_INDEX];
        final ExplosionEvent.Post postEvent = SpongeEventFactory.createExplosionEventPost(Sponge.getCauseStackManager().getCurrentCause(), explosion, transactions);
        if (postEvent == null) {
            // Means that we have had no actual block changes apparently?
            return;
        }
        SpongeImpl.postEvent(postEvent);
        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);
                final Location<World> location = transaction.getOriginal().getLocation().orElse(null);
                if (location != null) {
                    // Cancel any block drops performed, avoids any item drops, regardless
                    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 (this.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);
                    }
                }
            }
        }
        TrackingUtil.performBlockAdditions(postEvent.getTransactions(), this, context, noCancelledTransactions);
    }
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) ExplosionEvent(org.spongepowered.api.event.world.ExplosionEvent) ArrayList(java.util.ArrayList) World(org.spongepowered.api.world.World) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) BlockChange(org.spongepowered.common.world.BlockChange) CauseStackManager(org.spongepowered.api.event.CauseStackManager) BlockPos(net.minecraft.util.math.BlockPos) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) Transaction(org.spongepowered.api.data.Transaction)

Aggregations

ChangeBlockEvent (org.spongepowered.api.event.block.ChangeBlockEvent)9 World (org.spongepowered.api.world.World)7 BlockPos (net.minecraft.util.math.BlockPos)5 Transaction (org.spongepowered.api.data.Transaction)5 ImmutableList (com.google.common.collect.ImmutableList)4 ArrayList (java.util.ArrayList)4 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)4 IMixinLocation (org.spongepowered.common.interfaces.world.IMixinLocation)4 BlockChange (org.spongepowered.common.world.BlockChange)4 StackFrame (org.spongepowered.api.event.CauseStackManager.StackFrame)3 JSONObject (org.json.JSONObject)2 BlockType (org.spongepowered.api.block.BlockType)2 Player (org.spongepowered.api.entity.living.player.Player)2 CauseStackManager (org.spongepowered.api.event.CauseStackManager)2 Listener (org.spongepowered.api.event.Listener)2 ExplosionEvent (org.spongepowered.api.event.world.ExplosionEvent)2 SpongeBlockSnapshot (org.spongepowered.common.block.SpongeBlockSnapshot)2 PhysicalCrate (com.codehusky.huskycrates.crate.PhysicalCrate)1 SQLException (java.sql.SQLException)1 BlockEvent (net.minecraftforge.event.world.BlockEvent)1