Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

Biblioteka CMDS - komendy, menu, updater, pakiety!


Rekomendowane odpowiedzi

Opublikowano

Udostępniam API o nazwie CMDS.

Jest to prosta biblioteka stworzona pod potrzebny przeciętnego serwera.

 

Komendy

Proste API komend. Od teraz nie musisz ich zapisywać w plugin.yml!

Przykładowa komenda z użytkiem tego API

https://github.com/ShootGame/CMDS/blob/master/src/main/java/pl/themolka/cmds/internal/CmdsCommand.java

 

Porady

Wykonuj konstruktor

super(new String[] {"cmds"});
możesz użyć wiele aliasów, pierwsza komenda zawsze będzie ta główna

super(new String[] {"help", "pomoc", "?"});
Używaj metod w konstruktorze.

Ustawianie opisu komendy - super.setDescription("Opis");

Ustawianie uprawnienia na komendę (jeżeli ją ustawisz to nie musisz sprawdzać jej w handle(...)!) - super.setPermission("mojplugin.mojeuprawnienie");

Ustawianie sposobu użycia komendy (nie ustawia się całej lecz tylko jej argumenty!) - super.setUsage("[jakis argument w usage]");

 

Jeżeli chcesz, aby komenda mogła być wysyłana z konsoli użyj tej metody

@Override
public void handle(CommandSender sender, String label, String[] args) throws CommandException
Jeżeli chcesz, aby komenda mogła być wysyłana tylko przez gracza użyj tej metody

@Override
public void handle(Player player, String label, String[] args) throws CommandException
Jeżeli chcesz wysłać wiadomość do gracza o błędnie wpisanej komendzie użyj

throw new UsageException
Jeżeli chcesz wysłać wiadomość do gracza o braku uprawnień użyj

throw new PermissionException("mojpluginu.mojeiprawnienie")
Jeżeli chcesz wysłać wiadomość o błędzie, ale nie jest to błędny użytek, ani brak uprawnienia użyj

throw new CommandException("Twoja wiadomosc bledu!")
Menu

Męczą mnie tworzenie własnego inventory, listenera, rejestracja. Od teraz robisz to jak poniżej.

public class MyMenu extends Menu {
    public MyMenu() {
        super("Nazwa mojego menu", 2); // nazwa menu oraz liczba jako ilość wierszy inventory
    }

    @Override
    public void onClick(Player player, int slot, ClickType type) {
        // przy kliknięciu w inventory. player - gracz, slot - numer slotu, type - typ kliknięcia
    }

    @Override
    public void onCreate(Player player) {
        // przy tworzeniu - wykonuje sie podczas otwarcia.
    }
}
W onEnable() dodajemy

Menu.register(new MyMenu());
zaś w miejscu gdzie chcemy taki ekwipunek otworzyć używamy

Menu menu = Menu.getRegistered().get(0); // pobieranie w tym przypadku pierwszego zarejestrowanego
Menu.open(menu, player)
Updater

Po co w każdym pluginie kopiować kod updatera skoro zawsze wygląda tak samo?

 

Dwie wersje: synchroniczne - w głównym wątku serwera (pl.themolka.cmds.util.PluginUpdater), oraz asynchroniczne - w nowym wątku - zalecane (pl.themolka.cmds.util.AsyncPluginUpdater).

 

Przykładowa metoda wykorzystująca updater asynchroniczny: https://github.com/Thefilippop1PL/Anti-Bot/blob/master/src/main/java/pl/filippop1/antibot/AntiBotPlugin.java#L112

 

Pakiety

Wsparcie pakietów. Obecnie jedyny wspierany pakiet to tytuły. Wymagana wersja serwera 1.8.

Przykładowa klasa wykorzystująca pakiet: https://gist.github.com/TheMolkaPL/090cc56cc96601677256

 

Użycie na serwerze

Proste, wystarczy zainstalować plugin CMDS na Twoim serwerze.

Pobieranie: https://github.com/ShootGame/CMDS/releases

 

UWAGA! Jeżeli używasz pluginu Anti-Bot, nie musisz instalować pluginu CMDS! Jest on już zaimplementowany w pluginie!

 

@Blezur czekam na warna

#AntyBlezur


Opublikowano

Dość niepotrzebne dla zaawansowanych programistów, a jednoczesnie ciezkie do ogarniecia dla tych mniej zaawansowanych.

Executor komend jest calkiem przydatny.

Nie trzeba sie meczyc z tym zje*anym domyslnym... rejestrowac w plugin.yml...

 

 

 

~ntsw

wow, bo wcale nie ma kolo twojego postu twojego nicku ;>

Opublikowano

­Można to zrobić w 2 klasach. Nie wiem po cholerę ich aż tyle, i po co wgrywanie tego na serwer, wystarczy dać 2 kody do githuba i gotowe xD

 

Proste, ale może być dla początkujących, z racji nawet tego że nie ma poradników o executorze (przynajmniej na polskiej scenie bajkita)

 

Pozdrawiam i życzę dalszych sukcesów.

Moja oficjalna strona! :)

http://socketbyte.pl/ 

Opublikowano

Proste, ale może być dla początkujących, z racji nawet tego że nie ma poradników o executorze (przynajmniej na polskiej scenie bajkita)

 

Pozdrawiam i życzę dalszych sukcesów.

Spokojnie, mam w planach nagranie tutów na YouTube do tej biblioteki :)

#AntyBlezur


Opublikowano

Wszystko ładnie opisane itd, ale mam jedno pytanie, po co to ? Przecież to jest wogóle niepotrzebne ? Nie widzę sensu tego używania. Oczywiście wielki plus za czas poświęcony nad tym,ale jakoś to do mnie nie trafia ;/

CAMDNAx.png

Opublikowano

Wszystko ładnie opisane itd, ale mam jedno pytanie, po co to ? Przecież to jest wogóle niepotrzebne ? Nie widzę sensu tego używania. Oczywiście wielki plus za czas poświęcony nad tym,ale jakoś to do mnie nie trafia ;/

Executor wcale nie jest 100 razy wygodniejszy od tego defaultowego ktory wymaga rejestracje komend w plugin.yml

Opublikowano

Executor wcale nie jest 100 razy wygodniejszy od tego defaultowego ktory wymaga rejestracje komend w plugin.yml

Ale nic wiekszego to on nie wnosi :/

CAMDNAx.png

Opublikowano

Wszystko ładnie opisane itd, ale mam jedno pytanie, po co to ? Przecież to jest wogóle niepotrzebne ? Nie widzę sensu tego używania. Oczywiście wielki plus za czas poświęcony nad tym,ale jakoś to do mnie nie trafia ;/

Nie wkurza cię to zawszę, że trzeba rejestrować komendy w plugin.yml i getCommand(x).setExecutor? klasa z komendą (org.bukkit.command.CommandExecutor) wykonuje się jako boolean przez co musisz returnować true (jeżeli false to wydrukuje ci usage z plugin.yml, ale czy ktoś tego używa?)?

 

Teraz tylko rejestrujesz raz całą klasę i masz dostęp do wszystkiego. API robi wszystko sam, sprawdza sendera czy nie jest Playerem, uprawnienie, buduje usage, drukuje błędy, itd, itp.

 

Nie nudzi Cię to, że zawsze jak robisz przykładowo updater to ZAWSZE kopiujesz kod? Title na które nie ma API w 1.8 wymaga wysłania pakietu. Jeżeli będziesz go używać to jednocześnie musisz importować NMS, przez co plugin jest bardzo wrażliwy na wersje. Oczywiście możesz używać refleksji i Class.forName, ale to napiszesz tylko raz, a potem tylko to zawsze kopiujesz. Teraz tylko Packet.sendPacket(jakiś pakiet); i już. Bez wrażliwości na kod, w jednej linijce.

#AntyBlezur


Opublikowano

­Karny k***s za refleksje.

127449624.jpg

https://github.com/ShootGame/CMDS/blob/master/src/main/java/pl/themolka/cmds/packet/Packet.java#L65-L83

 

Tak to mozna co najwyżej robić benchmark procesora i inne sposoby marnowania mocy.

Za każdym razem pobierane od nowa... to zlaguje wszystko, jak będzie zbyt mocno używane + jest po prostu wolne.

 

A tak to.... dupy nie urwa, komendy nie mają żadnych ciekawych możliwości itd itp ;/

 

 

PS: lubie to że commandexecutor zwraca booleana, bo mam fajną metodę zwracajacą zawsze true.

return Msg.HELP.send(sender);

i fajniej tak wygląda, od razu z returnem.

 

 

EDIT: Takie porównanie czasowe, co by nie było że to drobne róznice i nic nie warte optymalizacje

 

Kod dla ciekawskich:

 

 

package com.example.helloworld;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Ref
{
    private static final Class<?> CLAZZ;
    private static final Method[] METHODS = new Method[10];

    static
    {
        try
        {
            CLAZZ = Class.forName("com.example.helloworld.priv.Priv");
            for (int i = 0; i < 10; i++)
            {
                METHODS[i] = CLAZZ.getDeclaredMethod("m" + i);
                METHODS[i].setAccessible(true);
            }
        } catch (final Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws Exception
    {
        long[] times = new long[1_000_000];
        for (int k = 0; k < 1_000_000; k++)
        {
            final long s = System.nanoTime();
            METHODS[k % 10].invoke(null);
            final long e = System.nanoTime();
            times[k] = (e - s);
        }
        System.out.println("Cache: Full: " + Arrays.stream(times).sum());
        System.out.println("Cache: Avg " + Arrays.stream(times).average().getAsDouble());
    }

    public static void main_old(String[] args) throws Exception
    {
        long[] times = new long[1_000_000];
        for (int k = 0; k < 1_000_000; k++)
        {
            final long s = System.nanoTime();
            final Method m = Class.forName("com.example.helloworld.priv.Priv").getDeclaredMethod("m" + (k % 10));
            m.setAccessible(true);
            m.invoke(null);
            final long e = System.nanoTime();
            times[k] = (e - s);
        }
        System.out.println("NoCache: Full: " + Arrays.stream(times).sum());
        System.out.println("NoCache: Avg " + Arrays.stream(times).average().getAsDouble());
    }
}

package com.example.helloworld.priv;

class Priv
{
    private static void m1()
    {
    }

    private static void m2()
    {
    }

    private static void m3()
    {
    }

    private static void m4()
    {
    }

    private static void m5()
    {
    }

    private static void m6()
    {
    }

    private static void m7()
    {
    }

    private static void m8()
    {
    }

    private static void m9()
    {
    }

    private static void m0()
    {
    }
}

 

 

Metoda "main_old" która działa jak u ciebie, "na żywca"

Wykonała się w 1825436936ns (1.83 sekundy)

średnio po 1825ns (pierwsze wykonania często zajmują wielokrotnie więcej czasu z powodu tego jak działa JIT)

 

Metoda "main" dla której wcześniej (tam statycznie) przygotowywane są wszystkie potrzebne metody...

Wykonała się w 113333951ns (0.11 sekundy!)

Średnio po: 113ns

 

Twój kod jest ponad 16x wolniejszy od poprawnego, 16x...

 

 

EDIT2:

A ten sam kod, ale po usunięciu refleksji, co oczywiście wymagało dodanie switch-a, do wykonania jednej z 10 metod (i zrobieniu ich publicznymi)

 

 

    public static void main(String[] args) throws Exception
    {
        long[] times = new long[1_000_000];
        for (int k = 0; k < 1_000_000; k++)
        {
            final long s = System.nanoTime();
            final int j = k % 10;
            switch (j)
            {
                case 0:
                    Priv.m0();
                    break;
                case 1:
                    Priv.m1();
                    break;
                case 2:
                    Priv.m2();
                    break;
                case 3:
                    Priv.m3();
                    break;
                case 4:
                    Priv.m4();
                    break;
                case 5:
                    Priv.m5();
                    break;
                case 6:
                    Priv.m6();
                    break;
                case 7:
                    Priv.m7();
                    break;
                case 8:
                    Priv.m8();
                    break;
                case 9:
                    Priv.m9();
                    break;
            }
            final long e = System.nanoTime();
            times[k] = (e - s);
        }
        System.out.println("Normal: Full: " + Arrays.stream(times).sum());
        System.out.println("Normal: Avg " + Arrays.stream(times).average().getAsDouble());
    } 

 

 

Wykonał się w 62216688ns (0.06 sekundy)

średnio po 62ns

 

Czyli 1.8 x szybciej od poprawnych refleksji i jakieś 29x szybciej od twojego kodu.

 

 

 

PS: tak, powinieniem się teraz uczyć na sprawdzian z zawodowych.

1438614356923701010629.png

 

  • 1 miesiąc temu...

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...