Merge remote-tracking branch 'origin/master'

Former-commit-id: 6670b483c4aa5e9dbdda40fd14b920d24db95ceb
This commit is contained in:
Ghost_chu committed 2020-04-06 13:45:23 +08:00
commit 8ff43260c7
1 file changed
+493 -2
@@ -19,6 +19,15 @@ import java.util.*;
@AllArgsConstructor
public class QuickShopItemMatcherImpl implements ItemMatcher {
private QuickShop plugin;
private ItemMetaMatcher itemMetaMatcher;
public QuickShopItemMatcherImpl() {
plugin = QuickShop.getInstance();
itemMetaMatcher=new ItemMetaMatcher(plugin.getConfig().getConfigurationSection("matcher.item"));
}
/**
* Gets the ItemMatcher provider name
*
@@ -47,9 +56,491 @@ public class QuickShopItemMatcherImpl implements ItemMatcher {
* @param givenStack The ItemStack will test matches with original itemstack.
* @return The result of tests
*/
@Override
public boolean matches(@Nullable ItemStack requireStack, @Nullable ItemStack givenStack) {
public boolean matches(@Nullable ItemStack[] requireStack, @Nullable ItemStack[] givenStack) {
if (requireStack == null && givenStack == null) {
return true;
}
if (requireStack == null || givenStack == null) {
return false;
}
if (requireStack.length != givenStack.length) {
return false;
}
//For performance, we just check really equals in each index,check isn't contain or match will cost n^n time in most
for (int i = 0; i < requireStack.length; i++) {
//IDEA bug, ignore NPE tips
//noinspection ConstantConditions
if ((requireStack[i] != null) && (givenStack[i] != null) &&
(requireStack[i].getAmount() != givenStack[i].getAmount())) {
return false;
}
if (!matches(requireStack[i], givenStack[i])) {
return false;
}
}
return true;
}
/**
* Compares two items to each other. Returns true if they match. Rewrite it to use more faster
* hashCode.
*
* @param requireStack The first item stack
* @param givenStack The second item stack
* @return true if the itemstacks match. (Material, durability, enchants, name)
*/
public boolean matches(@Nullable ItemStack requireStack, @Nullable ItemStack givenStack) {
if (requireStack == null && givenStack == null) {
return true;
}
if (requireStack == null || givenStack == null) {
Util.debugLog(
"Match failed: A stack is null: "
+ "requireStack["
+ requireStack
+ "] givenStack["
+ givenStack
+ "]");
return false; // One of them is null (Can't be both, see above)
}
requireStack = requireStack.clone();
requireStack.setAmount(1);
givenStack = givenStack.clone();
givenStack.setAmount(1);
switch (plugin.getConfig().getInt("matcher.work-type")) {
case 1:
return requireStack.isSimilar(givenStack);
case 2:
return requireStack.equals(givenStack);
}
if (!typeMatches(requireStack, givenStack)) {
return false;
}
// if (requireStack.hasItemMeta() != givenStack.hasItemMeta()) {
// Util.debugLog("Meta not matched");
// return false;
if (requireStack.hasItemMeta()) {
if (!givenStack.hasItemMeta()) {
return false;
}
return itemMetaMatcher.matches(requireStack, givenStack);
}
return true;
}
private boolean typeMatches(ItemStack requireStack, ItemStack givenStack) {
return requireStack.getType().equals(givenStack.getType());
}
private static class ItemMetaMatcher {
interface Matcher {
boolean match(ItemMeta meta1, ItemMeta meta2);
}
private final List<Matcher> matcherList = new LinkedList<>();
private void addIfEnable(ConfigurationSection itemMatcherConfig, String path, Matcher matcher) {
if (itemMatcherConfig.getBoolean(path)) {
matcherList.add(matcher);
}
}
public ItemMetaMatcher(ConfigurationSection itemMatcherConfig) {
addIfEnable(itemMatcherConfig, "damage", (meta1, meta2) -> {
// if (!(meta1 instanceof Damageable)) {
// return true; //No damage need to check.
// }
// if(!(meta2 instanceof Damageable)){
// return false;
// }
try {
Damageable damage1 = (Damageable) meta1;
Damageable damage2 = (Damageable) meta2;
// Check them damages, if givenDamage >= requireDamage, allow it.
return damage2.getDamage() <= damage1.getDamage();
} catch (Throwable th) {
th.printStackTrace();
return true;
}
});
addIfEnable(itemMatcherConfig, "repaircost", (meta1, meta2) -> {
if (!(meta1 instanceof Repairable)) {
return true;
}
if (!(meta2 instanceof Repairable)) {
return false;
}
Repairable repairable1 = (Repairable) meta1;
Repairable repairable2 = (Repairable) meta2;
if (repairable1.hasRepairCost() != repairable2.hasRepairCost()) {
return false;
}
if (repairable1.hasRepairCost()) {
return repairable2.getRepairCost() <= repairable1.getRepairCost();
}
return true;
});
addIfEnable(itemMatcherConfig, "displayname", ((meta1, meta2) -> {
if (!meta1.hasDisplayName()) {
return true;
} else {
if (!meta2.hasDisplayName()) {
return false;
}
return meta1.getDisplayName().equals(meta2.getDisplayName());
}
}));
// We didn't touch the loresMatches because many plugin use this check item.
addIfEnable(itemMatcherConfig, "lores", ((meta1, meta2) -> {
if (meta1.hasLore() != meta2.hasLore()) {
return false;
}
if (!meta1.hasLore()) {
return true; // No lores need to be checked.
}
List<String> lores1 = meta1.getLore();
List<String> lores2 = meta2.getLore();
return Arrays.deepEquals(
Objects.requireNonNull(lores1).toArray(), Objects.requireNonNull(lores2).toArray());
}));
addIfEnable(itemMatcherConfig, "enchs", ((meta1, meta2) -> {
if (meta1.hasEnchants()) {
if (!meta2.hasEnchants()) {
return false;
}
Map<Enchantment, Integer> enchMap1 = meta1.getEnchants();
Map<Enchantment, Integer> enchMap2 = meta2.getEnchants();
if (!Util.mapMatches(enchMap1, enchMap2)) {
return false;
}
}
if ((meta1 instanceof EnchantmentStorageMeta)) {
if (!(meta2 instanceof EnchantmentStorageMeta)) {
return false;
}
Map<Enchantment, Integer> stor1 = ((EnchantmentStorageMeta) meta1).getStoredEnchants();
Map<Enchantment, Integer> stor2 = ((EnchantmentStorageMeta) meta2).getStoredEnchants();
return Util.mapMatches(stor1, stor2);
}
return true;
}));
addIfEnable(itemMatcherConfig, "potions", ((meta1, meta2) -> {
if ((meta1 instanceof PotionMeta) != (meta2 instanceof PotionMeta)) {
return false;
}
if (!(meta1 instanceof PotionMeta)) {
return true; // No potion meta needs to be checked.
}
PotionMeta potion1 = (PotionMeta) meta1;
PotionMeta potion2 = (PotionMeta) meta2;
if (potion1.hasColor()) {
if (!potion2.hasColor()) {
return false;
} else {
if (!Objects.requireNonNull(potion1.getColor()).equals(potion2.getColor())) {
return false;
}
}
}
if (potion1.hasCustomEffects()) {
if (!potion2.hasCustomEffects()) {
return false;
}
if (!Arrays.deepEquals(
potion1.getCustomEffects().toArray(), potion2.getCustomEffects().toArray())) {
return false;
}
// if
// (!Util.listMatches(potion1.getCustomEffects(),potion2.getCustomEffects())) {
// return false;
// }
}
PotionData data1 = potion1.getBasePotionData();
PotionData data2 = potion2.getBasePotionData();
if (data2.equals(data1)) {
return true;
}
if (!data2.getType().equals(data1.getType())) {
return false;
}
if (data1.isExtended()) {
if (!data2.isExtended()) {
return false;
}
}
if (data1.isUpgraded()) {
//noinspection RedundantIfStatement
if (!data2.isUpgraded()) {
return false;
}
}
return true;
}));
addIfEnable(itemMatcherConfig, "attributes", (meta1, meta2) -> { // requireStack doen't need require must have AM, skipping..
if (!meta1.hasAttributeModifiers()) {
return true;
} else {
// If require AM but hadn't, the item not matched.
if (!meta2.hasAttributeModifiers()) {
return false;
}
Set<Attribute> set1 = Objects.requireNonNull(meta1.getAttributeModifiers()).keySet();
Set<Attribute> set2 = Objects.requireNonNull(meta2.getAttributeModifiers()).keySet();
for (Attribute att : set1) {
if (!set2.contains(att)) {
return false;
} else if (!meta1
.getAttributeModifiers()
.get(att)
.equals(meta2.getAttributeModifiers().get(att))) {
return false;
}
}
return true;
}
});
addIfEnable(itemMatcherConfig, "itemflags", ((meta1, meta2) -> {
if (meta1.getItemFlags().isEmpty()) {
return true;
} else {
if (meta2.getItemFlags().isEmpty()) {
return false;
}
return Arrays.deepEquals(meta1.getItemFlags().toArray(), meta2.getItemFlags().toArray());
}
}));
addIfEnable(itemMatcherConfig, "custommodeldata", ((meta1, meta2) -> {
try {
if (!meta1.hasCustomModelData()) {
return true;
} else {
if (!meta2.hasCustomModelData()) {
return false;
}
return meta1.getCustomModelData() == meta2.getCustomModelData();
}
} catch (NoSuchMethodError err) {
// Ignore, for 1.13 compatibility
return true;
}
}));
addIfEnable(itemMatcherConfig, "book", ((meta1, meta2) -> {
if (!(meta1 instanceof BookMeta)) {
return true;
}
if (!(meta2 instanceof BookMeta)) {
return false;
}
BookMeta book1 = (BookMeta) meta1;
BookMeta book2 = (BookMeta) meta2;
if (book1.hasTitle()) {
if (!book2.hasTitle()) {
return false;
}
if (!Objects.equals(book1.getTitle(), book2.getTitle())) {
return false;
}
}
if (book1.hasPages()) {
if (!book2.hasPages()) {
return false;
}
if (!book1.getPages().equals(book2.getPages())) {
return false;
}
}
if (book1.hasAuthor()) {
if (!book2.hasAuthor()) {
return false;
}
if (!Objects.equals(book1.getAuthor(), book2.getAuthor())) {
return false;
}
}
if (book1.hasGeneration()) {
if (!book2.hasGeneration()) {
return false;
}
return Objects.equals(book1.getGeneration(), book2.getGeneration());
}
return true;
}));
addIfEnable(itemMatcherConfig, "banner", ((meta1, meta2) -> {
if ((meta1 instanceof BannerMeta) != (meta2 instanceof BannerMeta)) {
return false;
}
if (!(meta1 instanceof BannerMeta)) {
return true;
}
BannerMeta bannerMeta1 = (BannerMeta) meta1;
BannerMeta bannerMeta2 = (BannerMeta) meta2;
if (bannerMeta1.numberOfPatterns() != bannerMeta2.numberOfPatterns()) {
return false;
}
return Util.listMatches(bannerMeta1.getPatterns(), bannerMeta2.getPatterns());
}));
addIfEnable(itemMatcherConfig, "skull", (meta1, meta2) -> {
if ((meta1 instanceof SkullMeta) != (meta2 instanceof SkullMeta)) {
return false;
}
if (!(meta1 instanceof SkullMeta)) {
return true;
}
//getOwningPlayer will let server query playerProfile in server thread
//Causing huge lag, so using String instead
String player1 = ((SkullMeta) meta1).getOwner();
String player2 = ((SkullMeta) meta2).getOwner();
if (player1 == null) {
return true;
}
return player1.equalsIgnoreCase(player2);
});
addIfEnable(itemMatcherConfig, "map", (meta1, meta2) -> {
if ((meta1 instanceof MapMeta) != (meta2 instanceof MapMeta)) {
return false;
}
if (!(meta1 instanceof MapMeta)) {
return true;
}
MapMeta mapMeta1 = ((MapMeta) meta1);
MapMeta mapMeta2 = ((MapMeta) meta2);
if (!mapMeta1.hasMapView() || mapMeta1.getMapView() == null) {
return true;
}
if (!mapMeta1.getMapView().equals(mapMeta2.getMapView())) {
return false;
}
if (!mapMeta1.hasColor() || mapMeta1.getColor() == null) {
return true;
}
if (!mapMeta1.getColor().equals(mapMeta2.getColor())) {
return false;
}
if (!mapMeta1.hasLocationName() || mapMeta1.getLocationName() == null) {
return true;
}
return mapMeta1.getLocationName().equals(mapMeta2.getLocationName());
});
addIfEnable(itemMatcherConfig, "firework", (meta1, meta2) -> {
if ((meta1 instanceof FireworkMeta) != (meta2 instanceof FireworkMeta)) {
return false;
}
if (!(meta1 instanceof FireworkMeta)) {
return true;
}
FireworkMeta fireworkMeta1 = ((FireworkMeta) meta1);
FireworkMeta fireworkMeta2 = ((FireworkMeta) meta2);
if (!fireworkMeta1.hasEffects()) {
return true;
}
if (!fireworkMeta1.getEffects().equals(fireworkMeta2.getEffects())) {
return false;
}
return fireworkMeta1.getPower() == fireworkMeta2.getPower();
});
addIfEnable(itemMatcherConfig, "leatherArmor", ((meta1, meta2) -> {
if ((meta1 instanceof LeatherArmorMeta) != (meta2 instanceof LeatherArmorMeta)) {
return false;
}
if (!(meta1 instanceof LeatherArmorMeta)) {
return true;
}
return ((LeatherArmorMeta) meta1).getColor().equals(((LeatherArmorMeta) meta2).getColor());
}));
addIfEnable(itemMatcherConfig, "fishBucket", (meta1, meta2) -> {
if ((meta1 instanceof TropicalFishBucketMeta) != (meta2 instanceof TropicalFishBucketMeta)) {
return false;
}
if (!(meta1 instanceof TropicalFishBucketMeta)) {
return true;
}
TropicalFishBucketMeta fishBucketMeta1 = ((TropicalFishBucketMeta) meta1);
TropicalFishBucketMeta fishBucketMeta2 = ((TropicalFishBucketMeta) meta2);
if (!fishBucketMeta1.hasVariant()) {
return true;
}
return fishBucketMeta2.hasVariant() && fishBucketMeta1.getPattern() == fishBucketMeta2.getPattern()
&& fishBucketMeta1.getBodyColor().equals(fishBucketMeta2.getBodyColor())
&& fishBucketMeta1.getPatternColor().equals(fishBucketMeta2.getPatternColor());
});
addIfEnable(itemMatcherConfig, "suspiciousStew", ((meta1, meta2) -> {
if ((meta1 instanceof SuspiciousStewMeta) != (meta2 instanceof SuspiciousStewMeta)) {
return false;
}
if (!(meta1 instanceof SuspiciousStewMeta)) {
return true;
}
SuspiciousStewMeta stewMeta1 = ((SuspiciousStewMeta) meta1);
SuspiciousStewMeta stewMeta2 = ((SuspiciousStewMeta) meta2);
if (!stewMeta1.hasCustomEffects()) {
return true;
}
return stewMeta1.getCustomEffects().equals(stewMeta2.getCustomEffects());
}));
addIfEnable(itemMatcherConfig, "shulkerBox", ((meta1, meta2) -> {
//https://www.spigotmc.org/threads/getting-the-inventory-of-a-shulker-box-itemstack.212369
if ((meta1 instanceof BlockStateMeta) != (meta2 instanceof BlockStateMeta)) {
return false;
}
if (!(meta1 instanceof BlockStateMeta)) {
return true;
}
if ((((BlockStateMeta) meta1).getBlockState() instanceof ShulkerBox) != ((BlockStateMeta) meta2).getBlockState() instanceof ShulkerBox) {
return false;
}
if (!(((BlockStateMeta) meta1).getBlockState() instanceof ShulkerBox)) {
return true;
}
return QuickShop.getInstance().getItemMatcher().matches(((ShulkerBox) ((BlockStateMeta) meta1).getBlockState()).getInventory().getContents(), ((ShulkerBox) ((BlockStateMeta) meta2).getBlockState()).getInventory().getContents());
}));
}
boolean matches(ItemStack requireStack, ItemStack givenStack) {
if (requireStack.hasItemMeta() != givenStack.hasItemMeta()) {
return false;
}
if (!requireStack.hasItemMeta()) {
return true; // Passed check. no meta need to check.
}
ItemMeta meta1 = requireStack.getItemMeta();
ItemMeta meta2 = givenStack.getItemMeta();
for (Matcher matcher : matcherList) {
if (!matcher.match(meta1, meta2)) {
return false;
}
}
return true;
}
private boolean rootMatches(ItemMeta meta1, ItemMeta meta2) {
return (meta1.hashCode() == meta2.hashCode());
}
}
}