Skip to content
Merged
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
16 changes: 4 additions & 12 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
<byte-buddy.version>1.17.5</byte-buddy.version>
<!-- More visible way how to change dependency versions -->
<paper.version>1.21.11-R0.1-SNAPSHOT</paper.version>
<bentobox.version>2.7.1-SNAPSHOT</bentobox.version>
<bentobox.version>3.17.0-SNAPSHOT</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. -->
Expand Down Expand Up @@ -114,14 +114,6 @@
</profiles>

<repositories>
<!-- jitpack first so MockBukkit snapshots resolve without hitting other repos -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots</url>
Expand All @@ -146,9 +138,9 @@
</dependency>
<!-- MockBukkit -->
<dependency>
<groupId>com.github.MockBukkit</groupId>
<artifactId>MockBukkit</artifactId>
<version>v1.21-SNAPSHOT</version>
<groupId>org.mockbukkit.mockbukkit</groupId>
<artifactId>mockbukkit-v1.21</artifactId>
<version>4.110.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
Expand Down
130 changes: 130 additions & 0 deletions src/main/java/com/wasteofplastic/invswitcher/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -676,4 +676,134 @@ private static void setTotalExperience(final Player player, final int exp)
public void saveOnShutdown() {
Bukkit.getOnlinePlayers().forEach(p -> this.storeAndSave(p, p.getWorld(), true));
}

/**
* Compute the storage key for a player and island event world, without using
* the player's current location. Used when the player is not in the target world.
* @param player - player
* @param world - the BentoBox event world
* @param island - the island involved in the event (may be null)
* @return storage key for this world/island combination
*/
String getStorageKeyForEvent(Player player, World world, Island island) {
String overworldName = getOverworldName(world);
if (!addon.getSettings().isIslandsActive()) {
return overworldName;
}
World overworld = Util.getWorld(world);
if (overworld == null) {
return overworldName;
}
int count = addon.getIslands().getNumberOfConcurrentIslands(player.getUniqueId(), overworld);
if (count <= 1) {
return overworldName;
}
// Only use island-specific key if the player owns the island
if (island != null && island.getOwner() != null && island.getOwner().equals(player.getUniqueId())) {
return overworldName + "/" + island.getUniqueId();
}
return overworldName;
}

/**
* Clears the stored inventory for a BentoBox world when the player is not currently in
* that world. Called when BentoBox fires a {@code PlayerResetInventoryEvent} while the
* player is in a non-BentoBox world so the player's current inventory is not affected.
* @param player - online player
* @param world - the BentoBox world whose stored inventory should be cleared
* @param island - the island involved in the reset (may be null)
*/
public void clearStoredInventoryForWorld(Player player, World world, Island island) {
InventoryStorage store = getInv(player);
String key = getStorageKeyForEvent(player, world, island);
String worldKey = getOverworldName(world);
Settings settings = addon.getSettings();
if (settings.isInventory()) {
String k = settings.isIslandsInventory() ? key : worldKey;
store.setInventory(k, Collections.emptyList());
}
database.saveObjectAsync(store);
}

/**
* Clears the stored ender chest for a BentoBox world when the player is not currently in
* that world. Called when BentoBox fires a {@code PlayerResetEnderChestEvent} while the
* player is in a non-BentoBox world.
* @param player - online player
* @param world - the BentoBox world whose stored ender chest should be cleared
* @param island - the island involved in the reset (may be null)
*/
public void clearStoredEnderChestForWorld(Player player, World world, Island island) {
InventoryStorage store = getInv(player);
String key = getStorageKeyForEvent(player, world, island);
String worldKey = getOverworldName(world);
Settings settings = addon.getSettings();
if (settings.isEnderChest()) {
String k = settings.isIslandsEnderChest() ? key : worldKey;
store.setEnderChest(k, Collections.emptyList());
}
database.saveObjectAsync(store);
}

/**
* Zeroes the stored experience for a BentoBox world when the player is not currently in
* that world. Called when BentoBox fires a {@code PlayerResetExpEvent} while the
* player is in a non-BentoBox world.
* @param player - online player
* @param world - the BentoBox world whose stored experience should be zeroed
* @param island - the island involved in the reset (may be null)
*/
public void clearStoredExpForWorld(Player player, World world, Island island) {
InventoryStorage store = getInv(player);
String key = getStorageKeyForEvent(player, world, island);
String worldKey = getOverworldName(world);
Settings settings = addon.getSettings();
if (settings.isExperience()) {
String k = settings.isIslandsExperience() ? key : worldKey;
store.setExp(k, 0);
}
database.saveObjectAsync(store);
}

/**
* Removes the stored health for a BentoBox world when the player is not currently in
* that world. Called when BentoBox fires a {@code PlayerResetHealthEvent} while the
* player is in a non-BentoBox world. Removing the entry means the player will receive
* maximum health the next time they enter the world.
* @param player - online player
* @param world - the BentoBox world whose stored health should be removed
* @param island - the island involved in the reset (may be null)
*/
public void clearStoredHealthForWorld(Player player, World world, Island island) {
InventoryStorage store = getInv(player);
String key = getStorageKeyForEvent(player, world, island);
String worldKey = getOverworldName(world);
Settings settings = addon.getSettings();
if (settings.isHealth()) {
String k = settings.isIslandsHealth() ? key : worldKey;
store.getHealth().remove(k);
}
database.saveObjectAsync(store);
}

/**
* Resets the stored food level to full (20) for a BentoBox world when the player is not
* currently in that world. Called when BentoBox fires a {@code PlayerResetHungerEvent}
* while the player is in a non-BentoBox world.
* @param player - online player
* @param world - the BentoBox world whose stored food level should be reset
* @param island - the island involved in the reset (may be null)
*/
public void clearStoredFoodForWorld(Player player, World world, Island island) {
InventoryStorage store = getInv(player);
String key = getStorageKeyForEvent(player, world, island);
String worldKey = getOverworldName(world);
Settings settings = addon.getSettings();
if (settings.isFood()) {
String k = settings.isIslandsFood() ? key : worldKey;
store.setFood(k, 20);
}
database.saveObjectAsync(store);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
import com.wasteofplastic.invswitcher.InvSwitcher;

import world.bentobox.bentobox.api.events.island.IslandEnterEvent;
import world.bentobox.bentobox.api.events.player.PlayerBaseEvent;
import world.bentobox.bentobox.api.events.player.PlayerResetEnderChestEvent;
import world.bentobox.bentobox.api.events.player.PlayerResetExpEvent;
import world.bentobox.bentobox.api.events.player.PlayerResetHealthEvent;
import world.bentobox.bentobox.api.events.player.PlayerResetHungerEvent;
import world.bentobox.bentobox.api.events.player.PlayerResetInventoryEvent;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Util;

Expand Down Expand Up @@ -183,5 +189,100 @@ public void onPlayerQuit(final PlayerQuitEvent event) {
addon.getStore().removeFromCache(event.getPlayer());
}

/**
* Intercepts BentoBox's inventory reset when the player is not in the BentoBox world.
* Cancels the direct clear and instead wipes the stored inventory data for that world.
* @param event - event
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerResetInventory(PlayerResetInventoryEvent event) {
if (!shouldInterceptPlayerReset(event)) return;
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player != null) {
addon.getStore().clearStoredInventoryForWorld(player, event.getWorld(), event.getIsland());
}
}

/**
* Intercepts BentoBox's ender chest reset when the player is not in the BentoBox world.
* Cancels the direct clear and instead wipes the stored ender chest data for that world.
* @param event - event
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerResetEnderChest(PlayerResetEnderChestEvent event) {
if (!shouldInterceptPlayerReset(event)) return;
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player != null) {
addon.getStore().clearStoredEnderChestForWorld(player, event.getWorld(), event.getIsland());
}
}

/**
* Intercepts BentoBox's experience reset when the player is not in the BentoBox world.
* Cancels the direct clear and instead zeroes the stored experience for that world.
* @param event - event
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerResetExp(PlayerResetExpEvent event) {
if (!shouldInterceptPlayerReset(event)) return;
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player != null) {
addon.getStore().clearStoredExpForWorld(player, event.getWorld(), event.getIsland());
}
}

/**
* Intercepts BentoBox's health reset when the player is not in the BentoBox world.
* Cancels the direct reset and instead removes the stored health for that world
* (so the player receives max health when they next enter the world).
* @param event - event
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerResetHealth(PlayerResetHealthEvent event) {
if (!shouldInterceptPlayerReset(event)) return;
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player != null) {
addon.getStore().clearStoredHealthForWorld(player, event.getWorld(), event.getIsland());
}
}

/**
* Intercepts BentoBox's hunger reset when the player is not in the BentoBox world.
* Cancels the direct reset and instead sets stored food to full (20) for that world.
* @param event - event
*/
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerResetHunger(PlayerResetHungerEvent event) {
if (!shouldInterceptPlayerReset(event)) return;
event.setCancelled(true);
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player != null) {
addon.getStore().clearStoredFoodForWorld(player, event.getWorld(), event.getIsland());
}
}

/**
* Determines whether InvSwitcher should intercept a BentoBox player reset event.
* Returns true if the event's world is managed by InvSwitcher, the player is online,
* and the player is currently in a different world (not the event world).
* @param event - the reset event
* @return true if InvSwitcher should cancel the event and handle it itself
*/
private boolean shouldInterceptPlayerReset(PlayerBaseEvent event) {
World eventWorld = event.getWorld();
if (!addon.getWorlds().contains(eventWorld)) {
return false;
}
Player player = Bukkit.getPlayer(event.getPlayerUUID());
if (player == null) {
return false;
}
// Only intercept if the player is not currently in the event world
return !Util.sameWorld(player.getWorld(), eventWorld);
}

}
Loading
Loading