Skip to content

Commit

Permalink
Added Enchants filter support
Browse files Browse the repository at this point in the history
  • Loading branch information
Intybyte committed May 13, 2024
1 parent b841828 commit 654e0aa
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package io.github.thebusybiscuit.slimefun4.core.networks.cargo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;

import javax.annotation.Nonnull;

import io.github.thebusybiscuit.slimefun4.implementation.SlimefunItems;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;

import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
Expand All @@ -21,12 +25,14 @@
import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config;
import me.mrCookieSlime.Slimefun.api.BlockStorage;
import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu;
import org.bukkit.inventory.meta.ItemMeta;

/**
* The {@link ItemFilter} is a performance-optimization for our {@link CargoNet}.
* It is a snapshot of a cargo node's configuration.
*
* @author TheBusyBiscuit
* @author Vaan1310
*
* @see CargoNet
* @see CargoNetworkTask
Expand Down Expand Up @@ -54,6 +60,8 @@ class ItemFilter implements Predicate<ItemStack> {
*/
private boolean checkLore;

private boolean checkEnchants;

/**
* If an {@link ItemFilter} is marked as dirty / outdated, then it will be updated
* on the next tick.
Expand Down Expand Up @@ -112,6 +120,7 @@ public void update(@Nonnull Block b) {

this.items.clear();
this.checkLore = Objects.equals(blockData.getString("filter-lore"), "true");
this.checkEnchants = Objects.equals(blockData.getString("filter-enchant"), "true");
this.rejectOnMatch = !Objects.equals(blockData.getString("filter-type"), "whitelist");

for (int slot : slots) {
Expand Down Expand Up @@ -140,6 +149,7 @@ public void update(@Nonnull Block b) {
private void clear(boolean rejectOnMatch) {
this.items.clear();
this.checkLore = false;
this.checkEnchants = false;
this.rejectOnMatch = rejectOnMatch;
}

Expand Down Expand Up @@ -188,31 +198,114 @@ public boolean test(@Nonnull ItemStack item) {
if (potentialMatches == 0) {
// If there is no match, we can safely assume the default value
return rejectOnMatch;
} else {
/*
* If there is more than one potential match, create a wrapper to save
* performance on the ItemMeta otherwise just use the item directly.
*/
ItemStack subject = potentialMatches == 1 ? item : ItemStackWrapper.wrap(item);

/*
* If there is only one match, we won't need to create a Wrapper
* and thus only perform .getItemMeta() once
*/
for (ItemStackWrapper stack : items) {
if (SlimefunUtils.isItemSimilar(subject, stack, checkLore, false)) {
/*
* The filter has found a match, we can return the opposite
* of our default value. If we exclude items, this is where we
* would return false. Otherwise, we return true.
*/
return !rejectOnMatch;
}
}
/*
* If there is more than one potential match, create a wrapper to save
* performance on the ItemMeta otherwise just use the item directly.
*/
ItemStack subject = potentialMatches == 1 ? item : ItemStackWrapper.wrap(item);

/*
* If there is only one match, we won't need to create a Wrapper
* and thus only perform .getItemMeta() once
*/
for (ItemStackWrapper stack : items) {
boolean isSimilar = isSimilar(subject, stack, checkLore);

if (!isSimilar) {
continue;
}

if (!checkEnchants) {
/*
* The filter has found a match, we can return the opposite
* of our default value. If we exclude items, this is where we
* would return false. Otherwise, we return true.
*/
return !rejectOnMatch;
}

boolean areSameEnchant = SlimefunUtils.areSameEnchants(subject, stack);

if (checkEnchants && areSameEnchant) {
return !rejectOnMatch;
}

// If no particular item was matched, we fallback to our default value.
return rejectOnMatch;
}

// If no particular item was matched, we fallback to our default value.
return rejectOnMatch;

}

/** Internal method to check if the items are the same, {@link SlimefunUtils#isItemSimilar}
* won't work as expected in this context so this method exists until a better fix is implemented
*
* @param first First {@link ItemStack} to check
* @param second Second {@link ItemStack} to check
* @param checkLore If {@literal true} lore will be checked too
*/

private boolean isSimilar(ItemStack first, ItemStack second, boolean checkLore) {
if (first.getType() != second.getType()) {
return false;
}

//region Check Slimefun
SlimefunItem firstSFitem = SlimefunItem.getByItem(first);
SlimefunItem secondSFitem = SlimefunItem.getByItem(second);

if (firstSFitem == null ^ secondSFitem == null) {
return false;
}

if (firstSFitem != null) {
//if slimefun item compare ids
return firstSFitem.getId().equals(secondSFitem.getId());
}
//endregion

//if we don't need to check the lore we are done with the checks
if (!checkLore) {
return true;
}

//if both are null then same lore (no lore either of them)
if (!first.hasItemMeta() && !second.hasItemMeta()) {
return true;
}

ItemMeta firstMeta = first.hasItemMeta() ? first.getItemMeta() : Bukkit.getItemFactory().getItemMeta(first.getType());
ItemMeta secondMeta = second.hasItemMeta() ? second.getItemMeta() : Bukkit.getItemFactory().getItemMeta(second.getType());

return loreEquals(firstMeta.getLore(), secondMeta.getLore());
}

/** Checks if the 2 lore passed are the same
*
* @param loreA First list to check
* @param loreB Second list to check
* @return {@literal true} if the contents of the 2 lists are the same, {@literal false} otherwise
*/
private boolean loreEquals(List<String> loreA, List<String> loreB) {
//SlimefunUtils doesn't support null values
if (loreA == null && loreB == null) {
return true;
}

if (loreA == null || loreB == null) {
return false;
}

if (loreA.size() != loreB.size())
return false;

for (int i = 0; i < loreA.size(); i++) {
if (!loreA.get(i).equals(loreB.get(i))) {
return false;
}
}

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.ItemStack;

import io.github.bakedlibs.dough.items.CustomItemStack;
Expand Down Expand Up @@ -37,6 +38,7 @@ abstract class AbstractFilterNode extends AbstractCargoNode {
protected static final int[] SLOTS = { 19, 20, 21, 28, 29, 30, 37, 38, 39 };
private static final String FILTER_TYPE = "filter-type";
private static final String FILTER_LORE = "filter-lore";
private static final String FILTER_ENCHANT = "filter-enchant";

@ParametersAreNonnullByDefault
protected AbstractFilterNode(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, @Nullable ItemStack recipeOutput) {
Expand Down Expand Up @@ -74,6 +76,7 @@ protected void onPlace(BlockPlaceEvent e) {
BlockStorage.addBlockInfo(b, "index", "0");
BlockStorage.addBlockInfo(b, FILTER_TYPE, "whitelist");
BlockStorage.addBlockInfo(b, FILTER_LORE, String.valueOf(true));
BlockStorage.addBlockInfo(b, FILTER_ENCHANT, String.valueOf(false));
BlockStorage.addBlockInfo(b, "filter-durability", String.valueOf(false));
}

Expand Down Expand Up @@ -125,6 +128,24 @@ protected void updateBlockMenu(BlockMenu menu, Block b) {
});
}

String enchants = BlockStorage.getLocationInfo(b.getLocation(), FILTER_ENCHANT);

if (!BlockStorage.hasBlockInfo(b) || enchants == null || enchants.equals(String.valueOf(true))) {
menu.replaceExistingItem(34, new CustomItemStack(Material.MAP, "&7Include Enchants: &2\u2714", "", "&e> Click to toggle whether the Enchants have to match"));
menu.addMenuClickHandler(34, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, FILTER_ENCHANT, String.valueOf(false));
updateBlockMenu(menu, b);
return false;
});
} else {
menu.replaceExistingItem(34, new CustomItemStack(Material.MAP, "&7Include Enchants: &4\u2718", "", "&e> Click to toggle whether the Enchants have to match"));
menu.addMenuClickHandler(34, (p, slot, item, action) -> {
BlockStorage.addBlockInfo(b, FILTER_ENCHANT, String.valueOf(true));
updateBlockMenu(menu, b);
return false;
});
}

addChannelSelector(b, menu, 41, 42, 43);
markDirty(loc);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
public class AdvancedCargoOutputNode extends AbstractFilterNode {

private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 22, 23, 24, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 22, 23, 24, 26, 27, 31, 32, 33, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };

@ParametersAreNonnullByDefault
public AdvancedCargoOutputNode(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

public class CargoInputNode extends AbstractFilterNode {

private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 22, 23, 26, 27, 31, 32, 33, 34, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };
private static final int[] BORDER = { 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 18, 22, 23, 26, 27, 31, 32, 33, 35, 36, 40, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 };

private static final String ROUND_ROBIN_MODE = "round-robin";
private static final String SMART_FILL_MODE = "smart-fill";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
package io.github.thebusybiscuit.slimefun4.utils;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.*;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;

import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
Expand All @@ -26,6 +19,7 @@
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;

import io.github.bakedlibs.dough.common.CommonPatterns;
import io.github.bakedlibs.dough.items.ItemMetaSnapshot;
Expand Down Expand Up @@ -424,6 +418,48 @@ public static boolean isItemSimilar(@Nullable ItemStack item, @Nullable ItemStac
}
}

public static boolean areSameEnchants(ItemStack first, ItemStack second) {

if (!first.hasItemMeta() && !second.hasItemMeta()) {
return true;
}

if (!first.hasItemMeta() || !second.hasItemMeta() ) {
return false;
}

ItemMeta firstM = first.getItemMeta();
ItemMeta secondM = second.getItemMeta();

if (!(firstM instanceof EnchantmentStorageMeta || secondM instanceof EnchantmentStorageMeta)) {
return true;
}

EnchantmentStorageMeta stEnch = (EnchantmentStorageMeta) firstM;
EnchantmentStorageMeta ndEnch = (EnchantmentStorageMeta) secondM;

Map<Enchantment, Integer> enchantsFirst = stEnch.getStoredEnchants();
Map<Enchantment, Integer> enchantsSecond = ndEnch.getStoredEnchants();

return enchantsFirst.equals(enchantsSecond);
/*
if (enchantsFirst.size() != enchantsSecond.size()) {
return false;
}
for (var enchantment : enchantsFirst.entrySet()) {
// Check if the levels of the enchantments are equal
if (!Objects.equals(enchantment.getValue(), enchantsSecond.get(enchantment.getKey()))) {
return false;
}
}
Bukkit.getLogger().info("enchants complete");
return true;*/
}

private static @Nonnull Optional<DistinctiveItem> getDistinctiveItem(@Nonnull String id) {
SlimefunItem slimefunItem = SlimefunItem.getById(id);
if (slimefunItem instanceof DistinctiveItem distinctive) {
Expand Down

0 comments on commit 654e0aa

Please sign in to comment.