Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add vault change state event #12069

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package io.papermc.paper.event.block;

import com.google.common.base.Preconditions;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Vault;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.block.BlockEvent;
import org.jetbrains.annotations.ApiStatus;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* Called when a vault block changes state.
*/
@NullMarked
public class VaultChangeStateEvent extends BlockEvent implements Cancellable {
private static final HandlerList HANDLER_LIST = new HandlerList();

private final @Nullable Player player;
private final Vault.State currentState;
private Vault.State newState;
private boolean cancelled = false;

@ApiStatus.Internal
public VaultChangeStateEvent(final Block vaultBlock, final @Nullable Player player, final Vault.State currentState, final Vault.State newState) {
super(vaultBlock);
this.player = player;
this.currentState = currentState;
this.newState = newState;
}

/**
* Gets the player associated with this state change, if applicable.
*
* @return The associated player, or {@code null} if not known.
*/
@Nullable
public Player getPlayer() {
return this.player;
}

/**
* Gets the state the vault is currently in.
*
* @return The current vault state.
*/
public Vault.State getCurrentState() {
return currentState;
}

/**
* Gets the state the vault is attempting to transition to.
*
* @return The new vault state.
*/
public Vault.State getNewState() {
return newState;
}

/**
* Sets the new state that this vault will transition into instead.
*
* @param newState The new vault state.
*/
public void setNewState(final Vault.State newState) {
Preconditions.checkArgument(newState != null, "newState must not be null");
this.newState = newState;
}

@Override
public boolean isCancelled() {
return this.cancelled;
}

@Override
public void setCancelled(final boolean cancel) {
this.cancelled = cancel;
}

@Override
public HandlerList getHandlers() {
return HANDLER_LIST;
}

public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,53 @@
--- a/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/vault/VaultBlockEntity.java
@@ -272,6 +_,11 @@
@@ -272,7 +_,12 @@
if (!list.isEmpty()) {
player.awardStat(Stats.ITEM_USED.get(stack.getItem()));
stack.consume(config.keyItem().getCount(), player);
- unlock(level, state, pos, config, serverData, sharedData, list);
+ // CraftBukkit start
+ org.bukkit.event.block.BlockDispenseLootEvent vaultDispenseLootEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDispenseLootEvent(level, pos, player, list);
+ if (vaultDispenseLootEvent.isCancelled()) return;
+ list = vaultDispenseLootEvent.getDispensedLoot().stream().map(org.bukkit.craftbukkit.inventory.CraftItemStack::asNMSCopy).toList();
+ // CraftBukkit end
unlock(level, state, pos, config, serverData, sharedData, list);
+ unlock(level, state, pos, config, serverData, sharedData, list, player); // Paper - Vault API
serverData.addToRewardedPlayers(player);
sharedData.updateConnectedPlayersWithinRange(level, pos, serverData, config, config.deactivationRange());
}
@@ -281,8 +_,31 @@
}

static void setVaultState(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState, VaultConfig config, VaultSharedData sharedData) {
- VaultState vaultState = oldState.getValue(VaultBlock.STATE);
- VaultState vaultState1 = newState.getValue(VaultBlock.STATE);
+ // Paper start - Vault API
+ setVaultState(level, pos, oldState, newState, config,sharedData, null);
+ }
+
+ static void setVaultState(ServerLevel level, BlockPos pos, BlockState oldState, BlockState newState, VaultConfig config, VaultSharedData sharedData, @org.jspecify.annotations.Nullable Player associatedPlayer) {
+ VaultState vaultState = oldState.getValue(VaultBlock.STATE); final VaultState oldVaultState = vaultState;
+ VaultState vaultState1 = newState.getValue(VaultBlock.STATE); VaultState newVaultState = vaultState1;
+ org.bukkit.entity.Player apiAssociatedPlayer = null;
+ if (associatedPlayer != null) {
+ apiAssociatedPlayer = (org.bukkit.entity.Player) associatedPlayer.getBukkitEntity();
+ } else if (newVaultState == VaultState.ACTIVE) {
+ final Set<UUID> connectedPlayers = sharedData.getConnectedPlayers();
+ if (!connectedPlayers.isEmpty()) { // Used over sharedData#hasConnectedPlayers to ensure belows iterator#next is always okay.
+ apiAssociatedPlayer = level.getCraftServer().getPlayer(connectedPlayers.iterator().next());
+ }
+ }
+ final io.papermc.paper.event.block.VaultChangeStateEvent event = new io.papermc.paper.event.block.VaultChangeStateEvent(org.bukkit.craftbukkit.block.CraftBlock.at(level, pos), apiAssociatedPlayer, oldVaultState.toBukkitState(), newVaultState.toBukkitState());
+ if (!event.callEvent()) return;
+
+ final VaultState newEventState = VaultState.fromBukkitState(event.getNewState());
+ if (newEventState != newVaultState) {
+ newState = newState.setValue(VaultBlock.STATE, newEventState);
+ vaultState1 = newVaultState = newEventState;
+ }
+ // Paper end - Vault API
level.setBlock(pos, newState, 3);
vaultState.onTransition(level, pos, vaultState1, config, sharedData, newState.getValue(VaultBlock.OMINOUS));
}
@@ -294,6 +_,11 @@
ItemStack randomDisplayItemFromLootTable = getRandomDisplayItemFromLootTable(
level, pos, config.overrideLootTableToDisplay().orElse(config.lootTable())
Expand All @@ -24,3 +60,29 @@
sharedData.setDisplayItem(randomDisplayItemFromLootTable);
}
}
@@ -316,10 +_,24 @@
VaultSharedData sharedData,
List<ItemStack> itemsToEject
) {
+ // Paper start - Vault API
+ unlock(level, state, pos, config, serverData, sharedData, itemsToEject, null);
+ }
+ private static void unlock(
+ ServerLevel level,
+ BlockState state,
+ BlockPos pos,
+ VaultConfig config,
+ VaultServerData serverData,
+ VaultSharedData sharedData,
+ List<ItemStack> itemsToEject,
+ final @org.jspecify.annotations.Nullable Player associatedPlayer
+ ) {
+ // Paper end - Vault API
serverData.setItemsToEject(itemsToEject);
sharedData.setDisplayItem(serverData.getNextItemToEject());
serverData.pauseStateUpdatingUntil(level.getGameTime() + 14L);
- setVaultState(level, pos, state, state.setValue(VaultBlock.STATE, VaultState.UNLOCKING), config, sharedData);
+ setVaultState(level, pos, state, state.setValue(VaultBlock.STATE, VaultState.UNLOCKING), config, sharedData, associatedPlayer); // Paper - Vault API
}

private static List<ItemStack> resolveItemsToEject(ServerLevel level, VaultConfig config, BlockPos pos, Player player, ItemStack key) {
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--- a/net/minecraft/world/level/block/entity/vault/VaultState.java
+++ b/net/minecraft/world/level/block/entity/vault/VaultState.java
@@ -127,4 +_,24 @@
this.value = value;
}
}
+
+ // Paper start - Vault API
+ public org.bukkit.block.data.type.Vault.State toBukkitState() {
+ return switch (this) {
+ case INACTIVE -> org.bukkit.block.data.type.Vault.State.INACTIVE;
+ case ACTIVE -> org.bukkit.block.data.type.Vault.State.ACTIVE;
+ case UNLOCKING -> org.bukkit.block.data.type.Vault.State.UNLOCKING;
+ case EJECTING -> org.bukkit.block.data.type.Vault.State.EJECTING;
+ };
+ }
+
+ public static VaultState fromBukkitState(final org.bukkit.block.data.type.Vault.State vaultState) {
+ return switch (vaultState) {
+ case INACTIVE -> VaultState.INACTIVE;
+ case ACTIVE -> VaultState.ACTIVE;
+ case UNLOCKING -> VaultState.UNLOCKING;
+ case EJECTING -> VaultState.EJECTING;
+ };
+ }
+ // Paper end - Vault API
}
Loading