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
Empty file added .changelog/0.1.4.2.md
Empty file.
8 changes: 8 additions & 0 deletions .changelog/0.1.4.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 0.1.4.3

## Major Changes
- Item based Currencies can now be stored in free slots inside Shulker Boxes in either the Inventory or Enderchest.

## Minor Changes

## Fixes
2 changes: 1 addition & 1 deletion Bukkit/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
<parent>
<groupId>net.tnemc</groupId>
<artifactId>TNE</artifactId>
<version>0.1.4.2</version>
<version>0.1.4.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
2 changes: 1 addition & 1 deletion Bukkit/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#General Data
name: TheNewEconomy
version: 0.1.4.2
version: 0.1.4.3
description: The original feature-packed economy plugin for Minecraft.
author: creatorfromhell
api-version: 1.13
Expand Down
184 changes: 184 additions & 0 deletions Bukkit/src/net/tnemc/bukkit/BukkitItemCalculations.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,22 @@
*/

import net.tnemc.core.currency.calculations.ItemCalculations;
import net.tnemc.core.currency.item.ItemCurrency;
import net.tnemc.item.AbstractItemStack;
import net.tnemc.plugincore.PluginCore;
import net.tnemc.plugincore.core.compatibility.log.DebugLevel;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Locale;

/**
* BukkitItemCalculations
Expand All @@ -28,4 +43,173 @@
* @since 0.1.2.0
*/
public class BukkitItemCalculations extends ItemCalculations<Inventory> {

@Override
public Collection<AbstractItemStack<Object>> tryInsertIntoContainers(final Collection<AbstractItemStack<Object>> left,
final Inventory inventory,
final ItemCurrency currency) {

if(left.isEmpty() || !currency.shulker()) {
PluginCore.log().debug("Shulker insert skip early. leftEmpty=" + left.isEmpty()
+ " shulkerEnabled=" + currency.shulker(), DebugLevel.DEVELOPER);
return left;
}

PluginCore.log().debug("Shulker insert start. inventoryType=" + inventory.getType()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Guard shulker insertion against null inventories

tryInsertIntoContainers dereferences inventory immediately, but the caller path in CalculationData.giveItemsRetry can forward a null target inventory (it already logs target=null), and platform providers like FoliaInventoryProvider#getInventory explicitly return null when the player handle is unavailable. In disconnect/race scenarios with leftover payout items, this causes a NullPointerException in the shulker pass instead of safely returning leftovers for the existing drop logic.

Useful? React with 👍 / 👎.

+ " inventorySize=" + inventory.getSize()
+ " stackCount=" + left.size(), DebugLevel.DEVELOPER);

final Collection<AbstractItemStack<Object>> remaining = new ArrayList<>();

for(final AbstractItemStack<Object> abstractStack : left) {

final ItemStack insertion = resolveInsertionStack(abstractStack);
if(insertion == null) {
PluginCore.log().debug("Shulker insert skip - unknown material: " + abstractStack.material(), DebugLevel.DEVELOPER);
remaining.add(abstractStack);
continue;
}

PluginCore.log().debug("Shulker insert processing stack. material=" + insertion.getType().name()
+ " amount=" + abstractStack.amount()
+ " hasMeta=" + insertion.hasItemMeta(), DebugLevel.DEVELOPER);

int amountLeft = abstractStack.amount();
final int originalAmount = amountLeft;
final ItemStack[] contents = inventory.getContents();
boolean sawShulker = false;
int shulkerCount = 0;

for(int slot = 0; slot < contents.length && amountLeft > 0; slot++) {

final ItemStack containerStack = contents[slot];
if(containerStack == null || !isShulkerBox(containerStack.getType())) {
continue;
}

sawShulker = true;
shulkerCount++;

final ItemMeta itemMeta = containerStack.getItemMeta();
if(!(itemMeta instanceof final BlockStateMeta blockStateMeta)) {
continue;
}

final BlockState blockState = blockStateMeta.getBlockState();
if(!(blockState instanceof final Container container)) {
PluginCore.log().debug("Shulker insert slot=" + slot + " has BlockStateMeta but not a Container state.", DebugLevel.DEVELOPER);
continue;
}

PluginCore.log().debug("Shulker insert attempting slot=" + slot
+ " shulkerInvSize=" + container.getInventory().getSize()
+ " amountLeftBefore=" + amountLeft, DebugLevel.DEVELOPER);

amountLeft = addToInventory(container.getInventory(), insertion, amountLeft);

PluginCore.log().debug("Shulker insert completed slot=" + slot
+ " amountLeftAfter=" + amountLeft, DebugLevel.DEVELOPER);

blockStateMeta.setBlockState(blockState);
containerStack.setItemMeta(blockStateMeta);
inventory.setItem(slot, containerStack);
}

if(amountLeft > 0) {
if(!sawShulker) {
PluginCore.log().debug("Shulker insert found no shulker boxes in target inventory.", DebugLevel.DEVELOPER);
} else {
PluginCore.log().debug("Shulker insert left amount after scan: " + amountLeft
+ " material: " + insertion.getType().name()
+ " shulkerCount=" + shulkerCount, DebugLevel.DEVELOPER);
}
remaining.add(abstractStack.amount(amountLeft));
} else {
PluginCore.log().debug("Shulker insert success amount=" + originalAmount
+ " material=" + insertion.getType().name()
+ " shulkerCount=" + shulkerCount, DebugLevel.DEVELOPER);
}
}

PluginCore.log().debug("Shulker insert done. remainingStacks=" + remaining.size()
+ " remainingAmount=" + remaining.stream().mapToInt(AbstractItemStack::amount).sum(), DebugLevel.DEVELOPER);

return remaining;
}

private Material resolveMaterial(final String materialName) {

final Material direct = Material.matchMaterial(materialName);
if(direct != null) {
return direct;
}

final int namespace = materialName.indexOf(':');
final String normalized = (namespace > -1)? materialName.substring(namespace + 1) : materialName;

return Material.matchMaterial(normalized.toUpperCase(Locale.ROOT));
}

private boolean isShulkerBox(final Material material) {

return material == Material.SHULKER_BOX || material.name().endsWith("_SHULKER_BOX");
}

private ItemStack resolveInsertionStack(final AbstractItemStack<Object> stack) {

final Object cached = stack.cacheLocale();
if(cached instanceof final ItemStack cachedStack) {
final ItemStack copy = cachedStack.clone();
copy.setAmount(1);
return copy;
}

final Material material = resolveMaterial(stack.material());
if(material == null) {
return null;
}
return new ItemStack(material, 1);
}

private int addToInventory(final Inventory inventory, final ItemStack insertion, final int amount) {

int amountLeft = amount;
int pass = 0;

PluginCore.log().debug("Shulker internal add start. material=" + insertion.getType().name()
+ " amount=" + amount
+ " invType=" + inventory.getType()
+ " invSize=" + inventory.getSize(), DebugLevel.DEVELOPER);

while(amountLeft > 0) {
pass++;

final int toTry = Math.min(insertion.getMaxStackSize(), amountLeft);
final ItemStack toInsert = insertion.clone();
toInsert.setAmount(toTry);

final Map<Integer, ItemStack> overflow = inventory.addItem(toInsert);
if(overflow.isEmpty()) {
PluginCore.log().debug("Shulker internal add pass=" + pass + " inserted=" + toTry + " overflow=0", DebugLevel.DEVELOPER);
amountLeft -= toTry;
continue;
}

final int leftInOverflow = overflow.values().stream().mapToInt(ItemStack::getAmount).sum();
final int inserted = toTry - leftInOverflow;
PluginCore.log().debug("Shulker internal add pass=" + pass
+ " tried=" + toTry
+ " inserted=" + inserted
+ " overflowAmount=" + leftInOverflow
+ " overflowSlots=" + overflow.keySet(), DebugLevel.DEVELOPER);
if(inserted <= 0) {
break;
}
amountLeft -= inserted;
}

PluginCore.log().debug("Shulker internal add complete. left=" + amountLeft, DebugLevel.DEVELOPER);

return amountLeft;
}
}
4 changes: 2 additions & 2 deletions BukkitEarly/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,15 @@
<dependency>
<groupId>net.tnemc</groupId>
<artifactId>BukkitCore</artifactId>
<version>0.1.4.2</version>
<version>0.1.4.3</version>
<scope>compile</scope>
</dependency>
</dependencies>

<parent>
<groupId>net.tnemc</groupId>
<artifactId>TNE</artifactId>
<version>0.1.4.2</version>
<version>0.1.4.3</version>
<relativePath>../pom.xml</relativePath>
</parent>
</project>
2 changes: 1 addition & 1 deletion BukkitEarly/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#General Data
name: TheNewEconomy
version: 0.1.4.2
version: 0.1.4.3
description: The original feature-packed economy plugin for Minecraft.
author: creatorfromhell
api-version: 1.13
Expand Down
2 changes: 1 addition & 1 deletion Bungee/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,6 @@
<parent>
<groupId>net.tnemc</groupId>
<artifactId>TNE</artifactId>
<version>0.1.4.2</version>
<version>0.1.4.3</version>
</parent>
</project>
2 changes: 1 addition & 1 deletion Bungee/resources/plugin.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: TNEBungeeCore
main: net.tnemc.bungee.BungeeCore
version: 0.1.4.2
version: 0.1.4.3
author: creatorfromhell
2 changes: 1 addition & 1 deletion Core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<parent>
<groupId>net.tnemc</groupId>
<artifactId>TNE</artifactId>
<version>0.1.4.2</version>
<version>0.1.4.3</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion Core/resources/currency/USD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Item:
Shulker: true

#Should items from bundles be used in holdings calculations
Bundle: true
Bundle: false

#All configurations related to formatting.
Formatting:
Expand Down
2 changes: 1 addition & 1 deletion Core/src/net/tnemc/core/TNECore.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public abstract class TNECore extends PluginEngine {

public static final String DEFAULT_WORLD = "world-113";
public static final String coreURL = "https://tnemc.net/files/module-version.xml";
public static final String version = "0.1.4.2";
public static final String version = "0.1.4.3";
public static final String build = "RELEASE";
protected static TNECore instance;

Expand Down
Loading