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

[Bug fix] See issues [#238], [#239] for details. #240

Open
wants to merge 2 commits into
base: master
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
261 changes: 196 additions & 65 deletions src/main/java/com/griefcraft/lwc/LWC.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,14 @@
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Furnace;
import org.bukkit.block.ShulkerBox;
import org.bukkit.block.data.type.Chest;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
Expand Down Expand Up @@ -199,36 +202,29 @@ public static LWC getInstance() {
return instance;
}

/**
* Get a string representation of a block type
*
* @param id
* @return
*/

/**
* Get a string representation of a block material
*
* @param material
* @return
*/
public static String materialToString(Material material) {
if (material != null) {
String materialName = normalizeMaterialName(material);
if (material == null) {
return "";
}

// attempt to match the locale
String locale = LWC.getInstance().getPlugin().getMessageParser().parseMessage(materialName.toLowerCase());
String materialName = normalizeMaterialName(material);

// if it starts with UNKNOWN_LOCALE, use the default material name
if (locale == null) {
locale = materialName;
}
// attempt to match the locale
String locale = LWC.getInstance().getPlugin().getMessageParser().parseMessage(materialName.toLowerCase());

locale = locale.replace('_', ' ');
return StringUtil.capitalizeFirstLetter(locale);
// if it starts with UNKNOWN_LOCALE, use the default material name
if (locale == null) {
locale = materialName;
}

return "";
locale = locale.replace('_', ' ');
return StringUtil.capitalizeFirstLetter(locale);
}

/**
Expand All @@ -248,10 +244,6 @@ public static String normalizeMaterialName(Material material) {
name = "Sign";
}

if (name.contains("furnace")) {
name = "furnace";
}

if (name.endsWith("_")) {
name = name.substring(0, name.length() - 1);
}
Expand Down Expand Up @@ -442,65 +434,204 @@ public boolean canAdminProtection(Player player, Protection protection) {
return event.getAccess() == Permission.Access.ADMIN;
}

/**
* Calculate The number of items that can be deposit in a furnace-like.
*
* Fuel slot allows only fuel items.
* Result slot does not allow deposits.
*
* @param furnaceLike (Not Null) Furnace-like block.
* @param itemStack (Not Null) Item stack for deposit.
* @return Number of items that can be deposit.
*/
public int getMaxDepositAmount(Furnace furnaceLike, ItemStack itemStack) {
FurnaceInventory inventory = furnaceLike.getInventory();
ItemStack sourceSlot = inventory.getSmelting();
ItemStack fuelSlot = inventory.getFuel();

// source slot is empty, can deposit
if (sourceSlot == null) {
return itemStack.getAmount();
}

boolean isItemStackFuel = itemStack.getType().isFuel();

// source slot not empty, but can stack deposit
if (sourceSlot.getAmount() < sourceSlot.getMaxStackSize()) {
if (itemStack.isSimilar(sourceSlot)) {
return Math.min(
sourceSlot.getMaxStackSize() - sourceSlot.getAmount(),
itemStack.getAmount()
);
}
}

// can't stack deposit to source slot or source slot is full
// mean the same thing
if (fuelSlot == null) {
if (isItemStackFuel) {
return itemStack.getAmount();
}
return 0;
}
if (fuelSlot.getAmount() < fuelSlot.getMaxStackSize()) {
if (itemStack.isSimilar(fuelSlot)) {
return Math.min(
fuelSlot.getMaxStackSize() - fuelSlot.getAmount(),
itemStack.getAmount()
);
}
}

return 0;
}

/**
* Calculate The number of items that can be deposit in a container.
*
* @param block (Not Null) Container block has inventory.
* @param itemStack (Not Null) Item stack for container deposit.
* @return Number of items that can be deposit.
*/
public int getMaxDepositAmount(Block block, ItemStack itemStack) {
BlockState blockState = block.getState();

// this block has neither block status nor inventory
if (blockState == null || !(blockState instanceof InventoryHolder)) {
return 0;
}

// nesting is forbidden on shulker boxes
if (blockState instanceof ShulkerBox && itemStack.getType().toString().endsWith("SHULKER_BOX")) {
return 0;
}

Inventory inventory = ((InventoryHolder) blockState).getInventory();

// for Furnace-like blocks
if (blockState instanceof Furnace) {
return this.getMaxDepositAmount((Furnace) blockState, itemStack);
}

// has empty slot, can deposit?
if (inventory.firstEmpty() != -1) {
return itemStack.getAmount();
}

// has no empty slot, but can stack deposit?
if (itemStack.getMaxStackSize() == 1) {
// non-stackable items
return 0;
}
Map<Integer, ? extends ItemStack> sameTypeItemStacks = inventory.all(itemStack.getType());
for (ItemStack sameItemStack : sameTypeItemStacks.values()) {
if (sameItemStack.getAmount() >= sameItemStack.getMaxStackSize()) {
continue;
}
if (itemStack.isSimilar(sameItemStack)) {
return Math.min(
sameItemStack.getMaxStackSize() - sameItemStack.getAmount(),
itemStack.getAmount()
);
}
}

return 0;
}

/**
* Deposit items into an inventory chest Works with double chests.
*
*
* NOTE: Returns empty map if the entire item is deposit,
* non-empty map if a partial amount of items is deposit,
* null if item can't be deposit.
*
* @param block
* @param itemStack
* @return remaining items (if any)
* @return (Nullable) remaining items.
*/
public Map<Integer, ItemStack> depositItems(Block block, ItemStack itemStack) {
BlockState blockState;
BlockState blockState = block.getState();
// not a container, leave the item intact
if (blockState == null || !(blockState instanceof InventoryHolder)) {
return null;
}

if ((blockState = block.getState()) != null && (blockState instanceof InventoryHolder)) {
Block doubleChestBlock = null;
InventoryHolder holder = (InventoryHolder) blockState;
Block doubleChestBlock = null;
if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) {
doubleChestBlock = findAdjacentDoubleChest(block);
}

if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) {
doubleChestBlock = findAdjacentDoubleChest(block);
} else if (block.getType() == Material.FURNACE) {
Inventory inventory = holder.getInventory();
Map<Integer, ItemStack> empty = new HashMap<>();
int itemStackAmount = itemStack.getAmount();

if (inventory.getItem(0) != null && inventory.getItem(1) != null) {
if (inventory.getItem(0).getType() == itemStack.getType()
&& inventory.getItem(0)
.getMaxStackSize() >= (inventory.getItem(0).getAmount() + itemStack.getAmount())) {
// ItemStack fits on Slot 0
} else if (inventory.getItem(1).getType() == itemStack.getType()
&& inventory.getItem(1)
.getMaxStackSize() >= (inventory.getItem(1).getAmount() + itemStack.getAmount())) {
// ItemStack fits on Slot 1
} else {
return null;
}
}
}
// remove unreasonable item
if (itemStackAmount <= 0) {
return empty;
}

if (itemStack.getAmount() <= 0) {
return new HashMap<Integer, ItemStack>();
}
// reached deposit limit, leave the item intact
int canDepositAmount = getMaxDepositAmount(block, itemStack);
if (canDepositAmount == 0) {
return null;
}

Map<Integer, ItemStack> remaining = holder.getInventory().addItem(itemStack);
Inventory inventory = ((InventoryHolder) blockState).getInventory();
Map<Integer, ItemStack> remaining;

// furnace-like is special, we don't want to handle it to addItem method directly
if (blockState instanceof Furnace) {
// for furnace-like blocks
Furnace furnaceLike = (Furnace) blockState;
FurnaceInventory snapshotInventory = furnaceLike.getSnapshotInventory();

ItemStack resultSlotBackup = snapshotInventory.getResult();
// avoid addItem method stack deposit into result slot
snapshotInventory.setResult(null);

// can't deposit them all
if (canDepositAmount < itemStackAmount) {
// split item stack into 2 parts
int restAmount = itemStackAmount - canDepositAmount;
ItemStack canDepositPart = itemStack.clone();
ItemStack theRestPart = itemStack.clone();

canDepositPart.setAmount(canDepositAmount);
theRestPart.setAmount(restAmount);
// deposit can deposit part, drop the rest part into item
remaining = snapshotInventory.addItem(canDepositPart);
remaining.put(-1, theRestPart);
itemStack.setAmount(restAmount);
} else {
remaining = snapshotInventory.addItem(itemStack);
}

// we have remainders, deal with it
// restore backup and commit update
snapshotInventory.setResult(resultSlotBackup);
furnaceLike.update(true, false);
} else {
// other container block
remaining = inventory.addItem(itemStack);
}

// we have remainders, deal with it
if (remaining.size() > 0) {
int key = remaining.keySet().iterator().next();
ItemStack remainingItemStack = remaining.get(key);

// is it a double chest ?????
if (doubleChestBlock != null) {
InventoryHolder holder2 = (InventoryHolder) doubleChestBlock.getState();
remaining = holder2.getInventory().addItem(remainingItemStack);
}

// recheck remaining in the event of double chest being used
if (remaining.size() > 0) {
int key = remaining.keySet().iterator().next();
ItemStack remainingItemStack = remaining.get(key);

// is it a double chest ?????
if (doubleChestBlock != null) {
InventoryHolder holder2 = (InventoryHolder) doubleChestBlock.getState();
remaining = holder2.getInventory().addItem(remainingItemStack);
}

// recheck remaining in the event of double chest being used
if (remaining.size() > 0) {
return remaining;
}
return remaining;
}
}

return new HashMap<Integer, ItemStack>();
return empty;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/com/griefcraft/modules/flag/BaseFlagModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
import com.griefcraft.scripting.event.LWCProtectionInteractEvent;
import com.griefcraft.util.Colors;
import com.griefcraft.util.StringUtil;

import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import org.bukkit.command.CommandSender;

public class BaseFlagModule extends JavaModule {
Expand Down Expand Up @@ -85,6 +88,16 @@ public void onProtectionInteract(LWCProtectionInteractEvent event) {
flag = new Flag(type);
}

// magnet flag can't use on non-container block.
if (flag.getType() == Flag.Type.MAGNET) {
BlockState targetBlockState = protection.getBlock().getState();
if (!(targetBlockState instanceof Container)) {
lwc.sendLocale(player, "protection.interact.flag.magnet.notcontainer", "flag", StringUtil.capitalizeFirstLetter(flagName));
lwc.removeModes(player);
return;
}
}

if (shouldAdd) {
protection.addFlag(flag);
lwc.sendLocale(player, "protection.interact.flag.add", "flag", StringUtil.capitalizeFirstLetter(flagName));
Expand Down
Loading