Sol Reklam
Sağ Reklam

Rehber Paketleri İptal Etme ve Paket Oluşturma | ProtocolLib Kullanımı | Bölüm 2

Durum
Mesaj gönderimine kapalı.

why_shiro

Aerospace Nerd
Emekli

Discord:

why_shiro

Katılım
3 Haziran 2019
Mesajlar
235
Elmaslar
252
Puanlar
7.295
Yaş
22
Yer
Türkiye
Discord İzni
Minecraft
GrimOK
Twitter
whyshiro_
bannermctr.png



Bu makale ilk bölümün devamı niteliğindedir. Eğer ilk bölümde yapmış olduğumuz "ProtocolManager", "PacketListener" ve "PacketAdapter" farklılıkları, addPacketListener() metodu, PacketType, paketleri dinleme gibi konular hakkında bilginiz yoksa bu kurstan bir şey anlamayabilirsiniz. Bu yüzden lütfen ilk makaleyi okuduğunuza emin olunuz. İlk kursa gitmek için bana tıkla!
Bu bölümde sunucunun oyuncuya gönderdiği paketleri veya oyununun sunucuya gönderdiği paketleri iptal etmeyi ve kendi paketlerimizi oluşturmayı öğreneceğiz. ProtocolLib bittikten sonra NMS'ler üzerinden devam edeceğiz.



Bölüm 1 : Paketleri İptal Etme
Sunucunuza gelişmiş bir sohbet koruması yazmak istediğinizi varsayalım. Bunun için oyuncunun sunucuya gönderdiği Chat paketini (serverbound) dinlememiz gerekmekte. Paketimizi wiki.vg/Protocol üzerinden kontrol edelim:

1651661864168.png


Paketimiz sadece tek bir "String" değeri içermektedir. Bu yüzden container.getStrings().index(0); ile String değerini almamız gerekmekte. Bu yüzden bunu şu şekilde yapabiliriz:

Java:
String message = container.getStrings().read(0);

Sonra bu String değerimiz kötü bir kelime içeriyor mu diye kontrol etmemiz gerekiyor. Bunu küçük bir if-else ile yapabiliriz:


Java:
                if (message.contains("küfür") || message.contains("diğerKüfür")){
                    event.setCancelled(true); // Mesaj gönderimi iptal edildi
                    event.getPlayer().sendMessage("Küfür yasak!");
                }

Bu konumuz String manipülasyonu olmadığı için detaylı küfür veya website yakalamayı anlatmıyorum. Yukarıda gönderdiğimiz mesajı iptal ettik. Kodumuzun son görünümü şu şekilde olacaktır:

Java:
        protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.LOW, PacketType.Play.Client.CHAT) {

            @Override

            public void onPacketReceiving(PacketEvent event) {
                PacketContainer container = event.getPacket();

                String message = container.getStrings().read(0);

                if (message.contains("küfür") || message.contains("diğerKüfür")){
                    event.setCancelled(true);
                    event.getPlayer().sendMessage("Küfür yasak!");
                }
            }

        });




Bölüm 2 : Paketler Oluşturma
Paket oluşturma işi, dinlemede yaptığımız işe çok benzemektedir. Sadece bu sefer değerleri "read" etmektense "write" edeceğiz. Şimdi sunucuda bir patlama efekti oluşturalım. Bu bir clientbound işlemdir. Çünkü sunucu, oyuncuya sunucuda patlama olduğunu bildirecek paketler göndermektedir. Bu yüzden wiki sayfamızın Play kısmından Clientbound paketleri inceliyoruz. Oradan Explosion paketii bulup inceliyoruz:

1651662954833.png


Bu kursu yazarken bilerek Explosion paketini ele aldım. Çünkü wikide koordinalar "Float" olarak verilmiş. Ancak biz bunları yazarken Double olarak yazmalıyız. Aksi taktirde bir hatayla karşı karşıya kalacağız. Pluginimizin onEnable() metoduna yeni bir "Command Executor" oluşturuyorum ve adan komutumuzun çalışması için gereken class'ı oluşturuyorum (TestPluginCommand).

Java:
getServer().getPluginCommand("boom").setExecutor(new TestPluginCommand());

Java:
public class TestPluginCommand implements CommandExecutor {
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {



        return false;
    }
}

Ardından komutu kullanan kişinin oyuncu olduğunu doğrulamak için bir if-else kodu yazıyorum:

Java:
        if (sender instanceof Player){
            Player player = (Player) sender;
            }

Sonra da ProtocolManager objemizi oluşturuyoruz: ProtocolManager manager = ProtocolLibrary.getProtocolManager();. Bu adımları tamamladıktan sonra oyuncunun baktığı bloğu almamız gerekiyor. Spigot bize getLineOfSight() metodu sağlamakta. Bu metot oyuncunun gözünden bir çizgi çekmekte ve o çizgi içerisindeki tüm blokları almakta. Bu metot iki adet değer almaktadır:

@NotNull public List<Block> getLineOfSight(@Nullable Set<Material> transparent, int maxDistance);

Biz burada transparent için "null" , maksimum görüş uzaklığımızı da 25 olarak belirleyeceğiz. Ardından bu aralıkta aldığımız blokları Java 8 ile gelen .stream() metodunu kullanarak filtreliyeceğiz. Son olarak bir forEach() döngüsü ile istediğimiz bloğa ulaşacağız. Eğer stream(), filter(), map() gibi fonksiyonları bilmiyorsanız daha fazla bilgi için "Java Doc"'lara bakabilirisiniz: https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html


Java:
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {

        if (sender instanceof Player){
            Player player = (Player) sender;

            ProtocolManager manager = ProtocolLibrary.getProtocolManager();

            player.getLineOfSight(null,25).stream().filter(block -> block.getType() != Material.AIR).forEach(block -> {


            });


        }

        return false;
    }

Ardından bloğumuzun lokasyonunu Location location = block.getLocation(); ile alıyoruz. Sonrasında bir PacketContainer oluşturuyoruz ancak bu sefer ProtocolManager objemizden createPacket(PacketType); fonksiyonunu kullanıyoruz:

Java:
PacketContainer container = manager.createPacket(PacketType.Play.Server.EXPLOSION);

Ardından gerekli yerleri .write(index, value) şeklinde dolduruyoruz:

Java:
                container.getDoubles().write(0,location.getX()); // X
                container.getDoubles().write(1,location.getY()); // Y
                container.getDoubles().write(2,location.getZ()); // Z

                container.getFloat().write(0,5.0f); // Büyükük
                container.getFloat().write(1,0.0f); // X ivmesi
                container.getFloat().write(2,5.0f); // Y ivmesi
                container.getFloat().write(3,0.0f); // Z ivmesi

Sonunda ise paketi oyuncuya gönderiyoruz:

Kod:
                try {
                    manager.sendServerPacket(player,container);
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

Eklentimizi çalıştırmadan önce yapmamız gereken son şey "plugin.yml" dosyasına "boom" komudunu eklemek olacaktır:

Kod:
commands:
  boom:
    description: Haha patlamalar goes brrr


Son Söz

ProtocolLib ile ilgili genel bilgiler bu kadardı. Öneriler ve yardım için Discord sunucumuza katılabilirsiniz. Herkese iyi forumlar dilerim <3

joinDiscord.png
 

Ekler

  • joinDiscord.png
    joinDiscord.png
    12 KB · Görünt.: 133

Laving

Demir Cevheri Gibiyim

Discord:

laving.

Katılım
22 Aralık 2020
Mesajlar
178
Elmaslar
55
Puanlar
4.170
Yaş
20
Minecraft
xLaving
Yine çok başarılı, eline emeğine sağlık dostum.
 

Mr_Obliviate

Bir Kömür Göründü Kaptanım!

Discord:

Mr Obliviate#0001

Katılım
19 Haziran 2020
Mesajlar
150
Elmaslar
153
Puanlar
4.420
Minecraft
Mr_Obliviate
Güzel konu olmuş detaylı ve açık. getLineOfSight() kısmında konu paket oluşturmanın biraz dışına çıkmış yazılımcıya sadece 'buraya blok listesini vericen' diyip geçmek lazım ama olsun. Üçüncü bölümünde clientside entity'leri görmeyi çok isterim.
 

why_shiro

Aerospace Nerd
Emekli

Discord:

why_shiro

Katılım
3 Haziran 2019
Mesajlar
235
Elmaslar
252
Puanlar
7.295
Yaş
22
Yer
Türkiye
Discord İzni
Minecraft
GrimOK
Twitter
whyshiro_
Güzel konu olmuş detaylı ve açık. getLineOfSight() kısmında konu paket oluşturmanın biraz dışına çıkmış yazılımcıya sadece 'buraya blok listesini vericen' diyip geçmek lazım ama olsun. Üçüncü bölümünde clientside entity'leri görmeyi çok isterim.

Yorumunuz için teşekkürler ? NMS kısmında Clientside Entity'leri anlatmayı düşünüyorum. Vize haftam geldiği için NMS ile ilgili kursu biraz erteleyeceğim :<
 

FurKqn

Medieval Roleplay
MinePass

Discord:

furkqn

Katılım
18 Temmuz 2016
Mesajlar
148
Elmaslar
56
Puanlar
13.480
Yaş
25
Yer
İstanbul
Minecraft
Furkqn
Eline sağlık, kaydettim daha sonra detaylıca inceleyeceğim.
 

Nirvanaa

Somon Balığı Selam Vermeye Geldi

Discord:

nirvanaa#0176

Katılım
3 Mayıs 2022
Mesajlar
11
Elmaslar
4
Puanlar
120
Yaş
21
Yer
Sivas
Twitter
nirvanasakinol
güzel ve sade bir şekilde anlatılmış eline emeğine sağlık
 

why_shiro

Aerospace Nerd
Emekli

Discord:

why_shiro

Katılım
3 Haziran 2019
Mesajlar
235
Elmaslar
252
Puanlar
7.295
Yaş
22
Yer
Türkiye
Discord İzni
Minecraft
GrimOK
Twitter
whyshiro_
Durum
Mesaj gönderimine kapalı.
Neden altınlarını Discord sunucumuzda kazmıyorsun? TIKLA VE KATIL!
Yukarı