Skip to content

Commit effa28f

Browse files
committed
Normalize plain-text item name/lore matching
1 parent 201ac4d commit effa28f

2 files changed

Lines changed: 86 additions & 17 deletions

File tree

src/main/java/cat/nyaa/nyaacore/BasicItemMatcher.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cat.nyaa.nyaacore;
22

33
import cat.nyaa.nyaacore.configuration.ISerializable;
4+
import cat.nyaa.nyaacore.utils.ItemStackUtils;
45
import org.bukkit.ChatColor;
56
import org.bukkit.enchantments.Enchantment;
67
import org.bukkit.inventory.ItemStack;
@@ -65,11 +66,13 @@ public boolean matches(ItemStack anotherItem) {
6566

6667
String baseDisplay = getDisplayName(base);
6768
String givenDisplay = getDisplayName(given);
69+
String baseDisplayPlain = ItemStackUtils.getPlainDisplayName(base);
70+
String givenDisplayPlain = ItemStackUtils.getPlainDisplayName(given);
6871
if (nameMatch == MatchingMode.EXACT && !baseDisplay.equals(givenDisplay)) return false;
69-
if (nameMatch == MatchingMode.EXACT_TEXT && !ChatColor.stripColor(baseDisplay).equals(ChatColor.stripColor(givenDisplay)))
72+
if (nameMatch == MatchingMode.EXACT_TEXT && !baseDisplayPlain.equals(givenDisplayPlain))
7073
return false;
7174
if (nameMatch == MatchingMode.CONTAINS && !givenDisplay.contains(baseDisplay)) return false;
72-
if (nameMatch == MatchingMode.CONTAINS_TEXT && !ChatColor.stripColor(givenDisplay).contains(ChatColor.stripColor(baseDisplay)))
75+
if (nameMatch == MatchingMode.CONTAINS_TEXT && !givenDisplayPlain.contains(baseDisplayPlain))
7376
return false;
7477

7578
Map<Enchantment, Integer> baseEnch = base.getEnchantments();
@@ -85,14 +88,14 @@ public boolean matches(ItemStack anotherItem) {
8588

8689
String[] baseLore = getLore(base);
8790
String[] givenLore = getLore(given);
91+
String[] baseLorePlain = ItemStackUtils.getPlainLore(base).toArray(new String[0]);
92+
String[] givenLorePlain = ItemStackUtils.getPlainLore(given).toArray(new String[0]);
8893
if (loreMatch == MatchingMode.EXACT && !Arrays.deepEquals(baseLore, givenLore)) return false;
8994
if (loreMatch == MatchingMode.CONTAINS && !containStrArr(givenLore, baseLore, false)) return false;
9095
if (loreMatch == MatchingMode.EXACT_TEXT) {
91-
for (int i = 0; i < baseLore.length; i++) baseLore[i] = ChatColor.stripColor(baseLore[i]);
92-
for (int i = 0; i < givenLore.length; i++) givenLore[i] = ChatColor.stripColor(givenLore[i]);
93-
if (!Arrays.deepEquals(baseLore, givenLore)) return false;
96+
if (!Arrays.deepEquals(baseLorePlain, givenLorePlain)) return false;
9497
}
95-
return loreMatch != MatchingMode.CONTAINS_TEXT || containStrArr(givenLore, baseLore, true);
98+
return loreMatch != MatchingMode.CONTAINS_TEXT || containStrArr(givenLorePlain, baseLorePlain, false);
9699
}
97100

98101
private String getDisplayName(ItemStack i) {

src/main/java/cat/nyaa/nyaacore/utils/ItemStackUtils.java

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,24 @@
1212
import net.minecraft.nbt.NbtOps;
1313
import net.minecraft.util.datafix.DataFixers;
1414
import net.minecraft.util.datafix.fixes.References;
15+
import net.kyori.adventure.text.Component;
16+
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
17+
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
1518
import org.bukkit.Bukkit;
19+
import org.bukkit.ChatColor;
1620
import org.bukkit.UnsafeValues;
1721
import org.bukkit.World;
1822
import org.bukkit.craftbukkit.CraftWorld;
1923
import org.bukkit.craftbukkit.inventory.CraftItemStack;
2024
import org.bukkit.inventory.ItemStack;
25+
import org.bukkit.inventory.meta.ItemMeta;
2126

2227
import java.io.*;
2328
import java.util.ArrayList;
2429
import java.util.Collections;
2530
import java.util.List;
2631
import java.util.Optional;
32+
import java.util.Objects;
2733
import java.util.stream.Collectors;
2834
import java.util.zip.Deflater;
2935
import java.util.zip.DeflaterInputStream;
@@ -91,18 +97,12 @@ public static ItemStack itemFromBinary(byte[] nbt) throws IOException {
9197
return null;
9298
}
9399

94-
// Try modern format first (GZIP compressed)
95-
if (nbt.length >= 2 && nbt[0] == (byte) 0x1f && nbt[1] == (byte) 0x8b) {
96-
try {
97-
return ItemStack.deserializeBytes(nbt);
98-
} catch (Exception e) {
99-
// If it fails, try to apply DataFixer for legacy data
100-
return deserializeWithDataFixer(nbt, true);
101-
}
100+
boolean isGzipped = isGzipCompressed(nbt);
101+
try {
102+
return deserializeWithDataFixer(nbt, isGzipped);
103+
} catch (Exception ex) {
104+
return ItemStack.deserializeBytes(nbt);
102105
}
103-
104-
// Legacy format (not GZIP) - apply DataFixer
105-
return deserializeWithDataFixer(nbt, false);
106106
}
107107

108108
/**
@@ -145,6 +145,8 @@ private static ItemStack deserializeWithDataFixer(byte[] nbt, boolean isGzipped)
145145
dynamic = dataFixer.update(References.ITEM_STACK, dynamic, dataVersion, currentDataVersion);
146146
tag = (CompoundTag) dynamic.getValue();
147147
tag.putInt("DataVersion", currentDataVersion);
148+
} else if (isGzipped) {
149+
return ItemStack.deserializeBytes(nbt);
148150
}
149151

150152
// Serialize back to bytes with GZIP and deserialize using Paper's method
@@ -157,6 +159,10 @@ private static ItemStack deserializeWithDataFixer(byte[] nbt, boolean isGzipped)
157159
}
158160
}
159161

162+
private static boolean isGzipCompressed(byte[] nbt) {
163+
return nbt.length >= 2 && nbt[0] == (byte) 0x1f && nbt[1] == (byte) 0x8b;
164+
}
165+
160166
@Deprecated
161167
public static ItemStack itemFromBinary(byte[] nbt, int offset, int len) {
162168
return ItemStack.deserializeBytes(nbt);
@@ -285,4 +291,64 @@ public static String itemToJson(ItemStack itemStack) throws RuntimeException {
285291
public static Object asNMSCopy(ItemStack itemStack) {
286292
return CraftItemStack.asNMSCopy(itemStack);
287293
}
294+
295+
public static boolean isSimilarPlainText(ItemStack base, ItemStack given) {
296+
if (base == null || given == null) return false;
297+
if (!Objects.equals(base.getType(), given.getType())) return false;
298+
String baseName = getPlainDisplayName(base);
299+
String givenName = getPlainDisplayName(given);
300+
if (!Objects.equals(baseName, givenName)) return false;
301+
List<String> baseLore = getPlainLore(base);
302+
List<String> givenLore = getPlainLore(given);
303+
return Objects.equals(baseLore, givenLore);
304+
}
305+
306+
public static String getPlainDisplayName(ItemStack item) {
307+
if (item == null) return "";
308+
ItemMeta meta = item.getItemMeta();
309+
if (meta == null) return "";
310+
if (meta.hasDisplayName()) {
311+
Component name = meta.displayName();
312+
if (name != null) {
313+
return PlainTextComponentSerializer.plainText().serialize(name);
314+
}
315+
return plainTextFromString(meta.getDisplayName());
316+
}
317+
return "";
318+
}
319+
320+
public static List<String> getPlainLore(ItemStack item) {
321+
if (item == null) return Collections.emptyList();
322+
ItemMeta meta = item.getItemMeta();
323+
if (meta == null || !meta.hasLore()) return Collections.emptyList();
324+
List<Component> componentLore = meta.lore();
325+
if (componentLore != null) {
326+
List<String> plain = new ArrayList<>(componentLore.size());
327+
for (Component line : componentLore) {
328+
plain.add(PlainTextComponentSerializer.plainText().serialize(line));
329+
}
330+
return plain;
331+
}
332+
List<String> legacyLore = meta.getLore();
333+
if (legacyLore == null) return Collections.emptyList();
334+
List<String> plain = new ArrayList<>(legacyLore.size());
335+
for (String line : legacyLore) {
336+
plain.add(plainTextFromString(line));
337+
}
338+
return plain;
339+
}
340+
341+
private static String plainTextFromString(String text) {
342+
if (text == null || text.isEmpty()) return "";
343+
String trimmed = text.trim();
344+
if ((trimmed.startsWith("{") && trimmed.endsWith("}")) || (trimmed.startsWith("[") && trimmed.endsWith("]"))) {
345+
try {
346+
Component component = GsonComponentSerializer.gson().deserialize(trimmed);
347+
return PlainTextComponentSerializer.plainText().serialize(component);
348+
} catch (Exception ignored) {
349+
// Fall back to legacy handling.
350+
}
351+
}
352+
return ChatColor.stripColor(text);
353+
}
288354
}

0 commit comments

Comments
 (0)