ItemStack Karşılaştırması

java10

kız çava bana kahve yap
Mesajlar
513
En iyi cevaplar
0
Beğeniler
586
Puanları
1,090
Ruh hali
canım sıkıldı ve iki itemstack in aynı olup olmadığını test etmek için method yazdım faydalı olucaktır gui ile uğraşan arkadaşlara, algoritması biraz saçma gelebilir belki daha sağlıklısını yaparsınız ama gece 1 de benden bu kadar .-.
PHP:
public static boolean ItemStackKarsilastirma(ItemStack is1, ItemStack is2) {
        if (is1 != null && is2 != null) {
            if ((!is1.hasItemMeta() && !is2.hasItemMeta()) || (is1.hasItemMeta() && is2.hasItemMeta())) {
                ItemMeta m1 = is1.getItemMeta();
                ItemMeta m2 = is2.getItemMeta();
                if ((!m1.hasDisplayName() && !m2.hasDisplayName()) || (m1.hasDisplayName() && m2.hasDisplayName())) {
                    if (m1.hasDisplayName() && m2.hasDisplayName()) {
                        if (!Objects.equals(m1.getDisplayName(), m2.getDisplayName())) {
                            return false;
                        }
                    }
                } else {
                    return false;
                }
                if ((m1.hasLore() && m2.hasLore()) || (!m1.hasLore() && m2.hasLore())) {
                    if (m1.hasLore() && m2.hasLore()) {
                        List<String> lore1 = m2.getLore();
                        List<String> lore2 = m2.getLore();
                        if (lore1.size() != lore2.size()) {
                            return false;
                        }
                        int size = lore1.size();
                        for (int i = 0; i < size; i++) {
                            if (!Objects.equals(lore1.get(i), lore2.get(i))) {
                                return false;
                            }
                        }
                    }
                } else {
                    return false;
                }
                if ((m1.hasEnchants() && m2.hasEnchants()) || (!m1.hasEnchants() && !m2.hasEnchants())) {
                    if (m1.hasEnchants() && m2.hasEnchants()) {
                        Enchantment[] set1 = (Enchantment[]) m1.getEnchants().keySet().toArray();
                        Enchantment[] set2 = (Enchantment[]) m2.getEnchants().keySet().toArray();
                        if (set1.length != set2.length) {
                            return false;
                        }
                        int count = 0;
                        for (int a = 0; a < set1.length; a++) {
                            for (int b = 0; b < set2.length; b++) {
                                if (!Objects.equals(set1[a], set2[b])) continue;
                                count++;
                            }
                        }
                        if (count != set1.length) {
                            return false;
                        }
                    }
                } else {
                    return false;
                }
                if ((m1.getItemFlags().isEmpty() && m2.getItemFlags().isEmpty()) || (!m1.getItemFlags().isEmpty() && !m2.getItemFlags().isEmpty())) {
                    if (!m1.getItemFlags().isEmpty() && !m2.getItemFlags().isEmpty()) {
                        if (m1.getItemFlags().size() == m2.getItemFlags().size()) {
                            ItemFlag[] if1 = (ItemFlag[]) m1.getItemFlags().toArray();
                            ItemFlag[] if2 = (ItemFlag[]) m2.getItemFlags().toArray();
                            int count = 0;
                            for (int a = 0; a < if1.length; a++) {
                                for (int b = 0; b < if2.length; b++) {
                                    if (!Objects.equals(if1[a], if2[b])) continue;
                                    count++;
                                }
                            }
                            if (count != if1.length) {
                                return false;
                            }
                        } else {
                            return false;
                        }
                    }
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } else {
            return false;
        }
        return true;
    }
o kadar if i kim geçer ki :D
test edildi*

Etiketler: @KilllerDragons , @S4RP , @Za_ion101 , @Elfen , @Atomy , @Onurbey034 , @Spygrand , @ByAehn , @GodofMilker , @Frodox , @ShortPallMall , @MCTDark , @Depth
 


Son düzenleme:

Depth

Zombi Katili
Mesajlar
193
En iyi cevaplar
0
Beğeniler
78
Puanları
300
Aslında hiç fena olmamış.
 

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,417
En iyi cevaplar
0
Beğeniler
1,541
Puanları
3,070
O kadar uğraşmadan sadece şöyle yapsan olmaz mıydı? Enchant, item flag veya lore sırası farkı olur mu bilmiyorum, ve bazı iflerdeki amacını tam anlayamadım. Ama bu şekilde de işe yarayacağını düşünüyorum:
Kod:
public static boolean ItemStackKarsilastirma(ItemStack is1, ItemStack is2) {
        if (is1 == null || is2 == null) return false;
        if (is1.getType() != is2.getType()) return false;
        if (is1.hasItemMeta() != is2.hasItemMeta()) return false;
        if (is1.hasItemMeta()) {
            ItemMeta m1 = is1.getItemMeta();
            ItemMeta m2 = is2.getItemMeta();

            if (m1.hasDisplayName() != m2.hasDisplayName()) return false;
            if (m1.hasDisplayName() && (!m1.getDisplayName().equals(m2.getDisplayName()))) return false;

            if (m1.hasLore() && (m1.getLore() != m2.getLore())) return false;

            if (m1.hasEnchants() && (m1.getEnchants() != m2.getEnchants())) return false;

            if (m1.getItemFlags() != m2.getItemFlags()) return false;
        }
        return true;
    }

Ayrıca bu yazdığımızla direk "is1.isSimilar(is2)" veya "is1.getItemMeta() == is2.getItemMeta()" kullanılarak yapılması arasında bir fark göremedim.

Edit: Type eşitliğini koymayı ikimiz de unutmuşuz galiba :D
 
Son düzenleme:

GodofMilker

Nether Yerlisi
Mesajlar
2,191
En iyi cevaplar
0
Beğeniler
2,570
Puanları
6,620
isSimilar zaten bunları yapmıyor mu ayol :(
 

java10

kız çava bana kahve yap
Mesajlar
513
En iyi cevaplar
0
Beğeniler
586
Puanları
1,090
Ruh hali
aslında direk öyle yapmıştım fakat şu sorunla karşılaştım, enchants lore ve itemflags ların yerleri değişebiliyor ve her zaman false döndürüyor

isSimilar zaten bunları yapmıyor mu ayol :(
onu bilmiyordum yeni bişi öğrendik yine saolasın.
 

amiral

Taş Madencisi
Mesajlar
65
En iyi cevaplar
0
Beğeniler
165
Puanları
240
Ruh hali
O kadar uğraşmadan sadece şöyle yapsan olmaz mıydı? Enchant, item flag veya lore sırası farkı olur mu bilmiyorum, ve bazı iflerdeki amacını tam anlayamadım. Ama bu şekilde de işe yarayacağını düşünüyorum:
Kod:
public static boolean ItemStackKarsilastirma(ItemStack is1, ItemStack is2) {
        if (is1 == null || is2 == null) return false;
        if (is1.getType() != is2.getType()) return false;
        if (is1.hasItemMeta() != is2.hasItemMeta()) return false;
        if (is1.hasItemMeta()) {
            ItemMeta m1 = is1.getItemMeta();
            ItemMeta m2 = is2.getItemMeta();

            if (m1.hasDisplayName() != m2.hasDisplayName()) return false;
            if (m1.hasDisplayName() && (!m1.getDisplayName().equals(m2.getDisplayName()))) return false;

            if (m1.hasLore() && (m1.getLore() != m2.getLore())) return false;

            if (m1.hasEnchants() && (m1.getEnchants() != m2.getEnchants())) return false;

            if (m1.getItemFlags() != m2.getItemFlags()) return false;
        }
        return true;
    }

Ayrıca bu yazdığımızla direk "is1.isSimilar(is2)" veya "is1.getItemMeta() == is2.getItemMeta()" kullanılarak yapılması arasında bir fark göremedim.

Edit: Type eşitliğini koymayı ikimiz de unutmuşuz galiba :D
Java'ya yeni başlayan arkadaşlardan da sıklıkla aldığım bir soru aslında tartıştığınız olay, buradan da açıklayalım isterseniz. Öncelikle işin temeli olarak bu verilerin fiziksel bellekte saklandığını bilmenizde fayda var ayrıca unutmamak gerek ki diğer bütün OOP diller gibi Java içinde de kompleks sınıf yapıları yapmak mevcut, hatta ItemStack bunun güzel bir örneği olabilir bile. Birçok yazılım dilindeki gibi Java da size kendi metotlarınızı oluşturma imkanı sağlar, bu dil içerisindeki her sınıfın da "Object" sınıfının alt üyesi olduğunu hepiniz zaten biliyordur. Bundan ötürü her sınıf aslında "equals()" metoduna sahiptir, bu metot çok kısa tanımıyla sizin içine koyduğunuz karşılaştırmaları yapmak için size sunulmuş şahane bir karşılaştırma metodudur zira bu metot her sınıfta vardır!

Asıl soruya gelecek olursak "==" operatörü ile bu "equals()" veya "isSimilar()" metodunun farkı nedir? Java'nın size sunduğu standart karşılaştırma operatörlerinden biri olan "==" aslında verilerin fiziksel bellekteki referanslarına göre geri dönüş yapar, oysa ki bahsettiğimiz diğer metotlar doğrudan içine girdiğiniz karşılaştırmaları yapar ve ona göre geri dönüş yapar. Bu çok kritiktir zira her ne kadar ilkel veya İngilizce hali ile "primitive" verilerde fark edilmese dahi kompleks sınıf yapılarında içindeki verileri aynı ama aslında farklı iki objeyi karşılaştırırken standart operatör direkt fiziksel belleğe bakacağından size sürekli "false" döndürecektir. Bu yüzden kendi sınıflarınıza özel eşitlik kontrol etme ve karşılaştırma metodları yapmanız kaçınılmaz olacaktır.
Kod:
String foo = new String("abc");
String bar = new String("abc");

if (foo == bar)
// False (The objects are not the same)

bar = foo;

if (foo == bar)
// True (Now the objects are the same)
Kod:
String foo = new String("abc");
String bar = new String("abc");

if (foo.equals(bar))
// True (The objects are identical but not same)
Konuya gelirsek zaten bahsedilmiş ama bu yaptığınız karşılaştırmayı yapan metod zaten mevcuttur.

https://hub.spigotmc.org/stash/proj.../java/org/bukkit/inventory/ItemStack.java#311
https://hub.spigotmc.org/stash/proj.../java/org/bukkit/inventory/ItemStack.java#331
 
Son düzenleme:

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,417
En iyi cevaplar
0
Beğeniler
1,541
Puanları
3,070
Java'ya yeni başlayan arkadaşlardan da sıklıkla aldığım bir soru aslında tartıştığınız olay, buradan da açıklayalım isterseniz. Öncelikle işin temeli olarak bu verilerin fiziksel bellekte saklandığını bilmenizde fayda var ayrıca unutmamak gerek ki diğer bütün OOP diller gibi Java içinde de kompleks sınıf yapıları yapmak mevcut, hatta ItemStack bunun güzel bir örneği olabilir bile. Birçok yazılım dilindeki gibi Java da size kendi metotlarınızı oluşturma imkanı sağlar, bu dil içerisindeki her sınıfın da "Object" sınıfının alt üyesi olduğunu hepiniz zaten biliyordur. Bundan ötürü her sınıf aslında "equals()" metoduna sahiptir, bu metot çok kısa tanımıyla sizin içine koyduğunuz karşılaştırmaları yapmak için size sunulmuş şahane bir karşılaştırma metodudur zira bu metot her sınıfta vardır!

Asıl soruya gelecek olursak "==" operatörü ile bu "equals()" veya "isSimilar()" metodunun farkı nedir? Java'nın size sunduğu standart karşılaştırma operatörlerinden biri olan "==" aslında verilerin fiziksel bellekteki referanslarına göre geri dönüş yapar, oysa ki bahsettiğimiz diğer metotlar doğrudan içine girdiğiniz karşılaştırmaları yapar ve ona göre geri dönüş yapar. Bu çok kritiktir zira her ne kadar ilkel veya İngilizce hali ile "primitive" verilerde fark edilmese dahi kompleks sınıf yapılarında içindeki verileri aynı ama aslında farklı iki objeyi karşılaştırırken standart operatör direkt fiziksel belleğe bakacağından size sürekli "false" döndürecektir. Bu yüzden kendi sınıflarınıza özel eşitlik kontrol etme ve karşılaştırma metodları yapmanız kaçınılmaz olacaktır.
Kod:
String foo = new String("abc");
String bar = new String("abc");

if (foo == bar)
// False (The objects are not the same)

bar = foo;

if (foo == bar)
// True (Now the objects are the same)
Kod:
String foo = new String("abc");
String bar = new String("abc");

if (foo.equals(bar))
// True (The objects are identical but not same)
Konuya gelirsek zaten bahsedilmiş ama bu yaptığınız karşılaştırmayı yapan metod zaten mevcuttur.

https://hub.spigotmc.org/stash/proj.../java/org/bukkit/inventory/ItemStack.java#311
https://hub.spigotmc.org/stash/proj.../java/org/bukkit/inventory/ItemStack.java#331
Bu kadar büyük bir yazının benle ilgisini pek anlayamadım ama neyse :D
 

Whoisthatinblack

Taş Madencisi
Mesajlar
70
En iyi cevaplar
0
Beğeniler
85
Puanları
280
Konuyu hortlatıyor gibi olabilirim fakat buradaki metodların hiç biri NBT'yi hesaba katmıyor ve gereksiz / eksik satırlar içeriyorlar. Dolayısı ile CraftBukkit ve Bukkit'in kaynak kodlarını inceleyerek ItemStack'in equals metodunda dikkate alınmayanları kendim karşılaştırdım ve bu metodu oluşturdum:

Kod:
public final static boolean equals(ItemStack item, ItemStack itemTwo) {
    net.minecraft.server.v1_12_R1.ItemStack itemN = CraftItemStack.asNMSCopy(item);
    net.minecraft.server.v1_12_R1.ItemStack itemTwoN = CraftItemStack.asNMSCopy(itemTwo);

    return item.equals(itemTwo)
        && itemN.hasTag() ? (itemTwoN.hasTag() && itemN.getTag().equals(itemTwoN.getTag()))
             : itemTwoN.hasTag()
        && item.getData().equals(itemTwo.getData())
        && item.getMaxStackSize() == itemTwo.getMaxStackSize();
}
 
Son düzenleme:

GodofMilker

Nether Yerlisi
Mesajlar
2,191
En iyi cevaplar
0
Beğeniler
2,570
Puanları
6,620
Konuyu hortlatıyor gibi olabilirim fakat buradaki metodların hiç biri NBT'yi hesaba katmıyor ve gereksiz / eksik satırlar içeriyorlar. Dolayısı ile CraftBukkit ve Bukkit'in kaynak kodlarını inceleyerek ItemStack'in equals metodunda dikkate alınmayanları kendim karşılaştırdım ve bu metodu oluşturdum:

Kod:
public final static boolean equals(ItemStack item, ItemStack itemTwo) {
    net.minecraft.server.v1_12_R1.ItemStack itemN = CraftItemStack.asNMSCopy(item);
    net.minecraft.server.v1_12_R1.ItemStack itemTwoN = CraftItemStack.asNMSCopy(itemTwo);

    return item.equals(itemTwo)
        && itemN.hasTag() ? (itemTwoN.hasTag() && itemN.getTag().equals(itemTwoN.getTag()))
             : itemTwoN.hasTag()
        && item.getData().equals(itemTwo.getData())
        && item.getMaxStackSize() == itemTwo.getMaxStackSize();
}
Sanırsam bukkitin kendi metodu katıyor :c
 

MegaCrafter

Obsidyen Madencisi
Mesajlar
1,417
En iyi cevaplar
0
Beğeniler
1,541
Puanları
3,070
Konuyu hortlatıyor gibi olabilirim fakat buradaki metodların hiç biri NBT'yi hesaba katmıyor ve gereksiz / eksik satırlar içeriyorlar. Dolayısı ile CraftBukkit ve Bukkit'in kaynak kodlarını inceleyerek ItemStack'in equals metodunda dikkate alınmayanları kendim karşılaştırdım ve bu metodu oluşturdum:

Kod:
public final static boolean equals(ItemStack item, ItemStack itemTwo) {
    net.minecraft.server.v1_12_R1.ItemStack itemN = CraftItemStack.asNMSCopy(item);
    net.minecraft.server.v1_12_R1.ItemStack itemTwoN = CraftItemStack.asNMSCopy(itemTwo);

    return item.equals(itemTwo)
        && itemN.hasTag() ? (itemTwoN.hasTag() && itemN.getTag().equals(itemTwoN.getTag()))
             : itemTwoN.hasTag()
        && item.getData().equals(itemTwo.getData())
        && item.getMaxStackSize() == itemTwo.getMaxStackSize();
}
Bence NBT'yi hesaba katmaya pek gerek yok. Çünkü zaten itemstack karşılaştırmasının temel amacı oyuncunun envanterinde benim oluşturduğum itemin olup olmadığına bakmamdır. (Benim oluşturduğum itemle mi sağ tıklamış vs.) Ve item oluştururken kodlarda kimsenin NBT'yi değiştirmeye uğraşacağını pek sanmıyorum.

(Aslında daha doğrusu NBT'de bizim kontrol ettiklerimiz dışında neler var tam bilmediğim için böyle söylüyorum. Dispenser'ların içlerindeki itemleri tuttuğunu veya Command block'ların içlerindeki komutları tuttuğunu falan biliyorum tabi. Eğer kayda değebilecek bir özelliği varsa tabi bir şey diyemem.)
 

java10

kız çava bana kahve yap
Mesajlar
513
En iyi cevaplar
0
Beğeniler
586
Puanları
1,090
Ruh hali
bi bakıma nbt yide işin içine katmak mantıklı, saol bilgilendirme için @Whoisthatinblack
 

Whoisthatinblack

Taş Madencisi
Mesajlar
70
En iyi cevaplar
0
Beğeniler
85
Puanları
280
Sanırsam bukkitin kendi metodu katıyor :c
Hayır, kaynak kodunu incelersen görebilirsin ki: Equals metodu isSimilar metodunu kullanıyor, isSimilar ItemFactory'e, ItemFactory'de seni CraftItemFactory'e yönlendiriyor. CraftItemFactory'de, CraftMetaItem'ın şu metoduyla eşyaların metalarını karşılaştırıyor. Yazmak için yazmayalım lütfen.

Bence NBT'yi hesaba katmaya pek gerek yok. Çünkü zaten itemstack karşılaştırmasının temel amacı oyuncunun envanterinde benim oluşturduğum itemin olup olmadığına bakmamdır. (Benim oluşturduğum itemle mi sağ tıklamış vs.) Ve item oluştururken kodlarda kimsenin NBT'yi değiştirmeye uğraşacağını pek sanmıyorum.

(Aslında daha doğrusu NBT'de bizim kontrol ettiklerimiz dışında neler var tam bilmediğim için böyle söylüyorum. Dispenser'ların içlerindeki itemleri tuttuğunu veya Command block'ların içlerindeki komutları tuttuğunu falan biliyorum tabi. Eğer kayda değebilecek bir özelliği varsa tabi bir şey diyemem.)
Ben sistemlerimin pek çoğunda NBT kullanıyorum, eşyaların üzerinde attribute, custom enchant saklamak; bir eşyayı benzerlerinden ayırt etmek (özellikle gui üzerinde) için daha iyisi yok gibi.
Ayrıca bu, istediğim zaman sadece eşya üzerindeki UUID değerini kontrol etmemi ve eşyanın ismini, lore unu vs. özelleştirilebilir olarak bırakmamı sağlıyor. Eşyanın ismi, datası ve hatta type ı değişse bile o eşyanın benim aradığım eşya olduğunu bilebiliyorum.
Durum böyle olunca NBT'yi kontrol etmek zorundayım bence sende etmelisin, belki eklentini kullanacak kişi NBT ile uğraşıyor veya NBT ile uğraşan bir eklenti barındırıyor olabilir.
 

Üst