Skocz do zawartości

Kormic

Zasłużony
  • Ilość zawartości

    11015
  • Rejestracja

  • Ostatnia wizyta

  • Wygrane w rankingu

    231

Treść opublikowana przez Kormic

  1. Dokładnie tak. Pokażę przykład, aby rozwiać wszelkie wątpliwości. command /testcommand: trigger: # Kod komendy otwierający GUI... on inventory click: # Kod wyzwalany przy kliknięciu w dowolnym GUI... Proszę zwrócić uwagę na to, że listener jest wywoływany przy każdym kliknięciu w dowolne GUI. Należy więc sprawdzić nazwę GUI, w które gracz klika. Nie chcemy przecież sytuacji, aby przy kliknięciu slotu 0 w dowolnym GUI ktoś był banowany na serwerze. if name of clicked inventory is "&6Nazwa GUI": # Dalszy kod... Dodam, że porównywanie klikniętego slotu do liczby nie zawsze musi działać. Sugeruję tutaj użycie wyrażenia 'index of clicked slot'. if index of clicked slot is 0: # Dalszy kod... Dzięki tej niewielkiej zmianie Skript będzie miał absolutną pewność, że pytamy o indeks (numer) slotu, nie o jego zawartość. Można co prawda wstawić instrukcję wykonywania komendy w listenerze zdarzenia 'on inventory click' (po uprzednim sprawdzeniu czy to jest odpowiednie GUI oraz czy został kliknięty odpowiedni slot), jednakże istnieje lepsze rozwiązanie. Może Pan skorzystać z efektu 'ban', który znajduje się w samym Skript. Jeśli Pan chce widzieć w konsoli gdy ktoś kogoś banuje w owym GUI, może Pan wysłać wiadomość do konsoli. send "Gracz %{_banned}% został zbanowany przez %player%." to console Pojawia się tu jeszcze problem związany z koniecznością wiedzy o jakiego gracza chodzi przy klikaniu w GUI. Musi Pan więc zapisać graczowi, który użył komendy /pun zmienną przechowującą gracza, którego chce zbanować. Tutaj również pokażę przykład. command /pun <player>: trigger: # Otwieranie GUI... set {punishingPlayer::%uuid of player%} to arg on inventory click: # Sprawdzanie GUI i indeksu slotu... ban {punishingPlayer::%uuid of player%} due to "Złe zachowanie." Jeśli Pan czuje taką potrzebę, przy zamknięciu tego GUI (listener zdarzenia 'on inventory close' i sprawdzenie nazwy GUI) może Pan czyścić zmienną przechowującą karanego gracza. clear {punishingPlayer::%uuid of player%} Na koniec dodam, że kwadratowe nawiasy przy argumencie oznaczają jego opcjonalność - bez jego podania komenda zadziała, a argument 1. przyjmie wartość '<none>'. Wtedy musi Pan sprawdzić czy argument jest ustawiony ('if arg-1 is set') i jakoś to obsłużyć. Prościej jednak jest po prostu usunąć te kwadratowe nawiasy, wtedy podanie argumentu jest wymagane. Pozdrawiam.
  2. Gdziekolwiek w tym pliku (może być nawet w innym skrypcie), byleby poza kodem komendy. Jeśli chodzi o dokumentację Skript, można ją znaleźć tutaj. Co do przykładowych kodów - można je znaleźć w dziale Skript > Skrypty. Co prawda znajdują się tam kody zawierające złe praktyki, ale wystarczy, że Pan znajdzie jakiś prosty implementujący w sobie listener zdarzenia 'on inventory click'.
  3. Skrypt nie działa z prostego powodu. Dlaczego Pan porównuje w pierwszej linijce funkcji parametr typu tekstowego z parametrem typu 'block'? Jedno nigdy nie będzie równe drugiemu, więc ten warunek zawsze zwróci fałsz. Co więcej, w skrypcie doszukałem się kilku co najmniej zastanawiających operacji, więc przedstawię moje uwagi i spostrzeżenia. Zalecam nie nadpisywać parametrów przesyłanych do funkcji, ponieważ kod staje się mniej czytelny. Jeśli Pan potrzebuje coś zapisać do lokalnej zmiennej (takiej, która zaczyna się znakiem podłogi "_" (ang. underscore)), warto utworzyć nową zmienną. Dlaczego parametr funkcji {_b} zawierający kliknięty blok jest nadpisywany przez Pana wartością tekstową, a później Pan używa tej samej zmiennej (już zawierającej tekst) do odtworzenia efektów wizualnych tak jakby ciągle przechowywała informację o bloku? Zbędnym jest zapisywanie UUID gracza w nazwie lokalnej zmiennej. To są zmienne lokalne - są one czyszczone i tworzone na nowo przy każdorazowym wywołaniu funkcji. Wracając do punktu 3., Pan czyści zmienne lokalne, co również jest bezsensowne. Skript automatycznie to robi za Pana, a właściwie to te zmienne są tylko tymczasowo przechowywane w pamięci serwera tak długo jak kod zawierający je nie zostanie wykonany do końca. Nie rozumiem sensu przesyłania bloków w formie tekstu do funkcji. Nie może Pan ich przesłać po prostu jako bloki w niezmienionej formie (np. 'upgradeGen(player, hay block, coal block, 50, block)')? Oczywiście wymaga to modyfikacji definicji funkcji upgradeGen. Pozdrawiam.
  4. Nie rozumiem zbytnio pytania. Adres IP (w domyśle mówimy o IPv4) jest tym, co może ulec zmianie przy chociażby resecie routera. Rzecz jasna to nie jest jedyna możliwa przyczyna. Ktoś może mieć zmienny adres IP (uznajmy, że do tej kategorii zalicza się internet mobilny), ktoś może używać proxy, ktoś może używać VPN. Tłumaczyłem już wcześniej jak Pan może zapewnić wyłączanie autologinu w przypadku zmiany adresu IP gracza. Spokojnie, ja Pana wyręczę. Im(sqrt(-196)) - tg(pi/4) W porządku, rozumiem.
  5. Doceniam pozytywny odbiór z Pana strony. Przestrzegam jednak przed tym, że stworzenie wysoce bezpiecznego mechanizmu logowania wymaga niepowierzchownej wiedzy z zakresu kryptografii (ja jej z pewnością nie posiadam). Musi się Pan więc przygotować na kilkanaście godzin dobrej lektury i poszukiwania informacji ze sprawdzonych źródeł. Jednym z nich jest strona, do której wcześniej podałem link. Postarałem się jedynie naprowadzić Pana na dobre rozwiązania. Proszę jeszcze raz przeczytać od początku wszystko to co ja, jak i inni użytkownicy pisali. Na koniec powiem jedno. Bezpieczeństwo haseł to dla Pana najwyższy priorytet, proszę o tym nie zapominać. Wszelkie estetyczne modyfikacje i te mające na celu optymalizację skryptu (o ile nie są krytyczne) mogą poczekać. To dobrze, ale nie do końca rozumiem jak to ma się do rozwoju Pana skryptu. Może Pan rozwinąć ten temat?
  6. Problem leży w tym, że linijka otwierająca listener zdarzenia 'on inventory click:" znalazła się w wyzwalaczu (ang. trigger) komendy. Listener ten powinien być całkowicie niezależny od komendy, to znaczy całkowicie poza jej kodem. Odsyłam do dokumentacji Skript i polecam zobaczyć skrypty w dziale Skript > Skrypty. Co prawda to drugie nie zawsze jest wiarygodnym źródłem, ale trzeba od czegoś zacząć.
  7. Niech Pan się na początku zastanowi jak skrypt ma działać (co powinien robić). Następnie może Pan rozważać nad tym jak powinien on zostać napisany (jakie powinny pojawić się w nim listenery zdarzeń, warunki, efekty, itd.). Warto się przy tym posługiwać dokumentacją aby weryfikować czy istnieje jakaś instrukcja pozwalająca osiągnąć to czego potrzebujemy. Jeśli nie istnieje, trzeba ominąć jakoś dany problem. Warto zacząć od najprostszej możliwej wersji, czyli nadawania efektu przy wchodzeniu do regionu i usuwaniu go wychodzeniu z regionu. Dopiero gdy Pan napisze taki skrypt, może się Pan zastanowić nad jego rozwojem. Powyższe porady są uniwersalne dla każdego języka skryptowego/programowania, nie ograniczają się one do Skripta. Jeśli Pan ma problem z czymś konkretnym, proszę dać znać. Pomogę na tyle ile jestem w stanie.
  8. Myślę, że naprostszym rozwiązaniem dla Pana byłoby utworzenie regionu w pluginie WorldGuard. Po utworzeniu owego regionu musiałby Pan napisać skrypt nasłuchujący do zdarzeń 'on region enter:' i 'on region leave:'. W ramach wskazówki powiem, że w celu sprawdzenia może Pan napisać warunek sprawdzający czy to jest odpowiedni region według poniższego wzoru. on region enter: # Bądź on region leave "%regions at event-location%" contains "<nazwa regionu> in world <nazwa świata>" # Dalszy kod... Oczywiście musi Pan napisać listenery dla obu tych zdarzeń. Przy wchodzeniu do tego regionu nadaje Pan graczowi efekt siły III, a przy wychodzeniu z niego Pan usuwa go. Do tego przyda się Panu ten efekt. Usuwanie można zrobić efektem 'remove', którego wykorzystanie pojawia się w przykładach do efektu nadawania efektu mikstury. Pojawia się jeszcze możliwy scenariusz, w którym gracz stoi w regionie przez bardzo długi czas - należałoby wtedy odnawiać ów efekt co jakiś czas. Tak więc może Pan również tworzyć listę z graczami w regionie i zapętlać ją co jakiś czas.
  9. Owszem, z definicji funkcja hash to taka funkcja, która nie posiada funkcji odwrotnej, a więc z definicji odzyskanie danych wejściowych nie jest możliwe. Dlatego używanie terminu "odhashowanie" jest nieprawidłowe i zwróciłem wcześniej na to uwagę. Rozumiem jednak, że Helios tutaj zastosował pewien skrót myślowy. W dodatku wniósł kilka ważnych spraw do dyskusji. Problem leży w tym, że jeśli na ustawianie hasła gracza nie zostaną narzucone odpowiednie warunki (chociażby długość hasła i konieczność zawierania w nim poszczególnych znaków) i administrator nie dołoży wszelkich starań, aby utrzymać możliwie wysoki standard bezpieczeństwa, wiele haseł może zostać odnalezionych metodą brute-force. Oczywiście, pod uwagę również należy chociażby brać ataki typu pre-image oraz ataki z użyciem tablic tęczowych (ang. rainbow tables). Właśnie w celu uczynienia ich daremnymi zalecane jest stosowanie soli przy hashowaniu. Ponownie odsyłam do lektury artykułu, do którego link podałem wyżej.
  10. Skript sam w sobie nie wspiera takiej operacji, należy się tutaj wspomóc dodatkami. W mojej ocenie najlepszym sposobem byłoby napisanie przy pomocy skript-reflect asynchronicznie wykonywanej sekcji (ang. section), która zwracałaby tekst z jakiejś strony przy pomocy chociażby pętli z BufferedReaderem (przykład tutaj). Dokumentację dodatku skript-reflect znajdzie Pan tutaj. Co ważne, strona powinna być w formacie "raw", a więc powinien się na niej znajdować tylko tekst. Dobrym przykładem jest dowolny kod na code.skript.pl z dopiskiem "raw". Przykład tutaj. Kluczowe jest asynchroniczne wykonanie takiej operacji. Dzięki temu zabiegowi skrypt nie będzie blokował głównego wątku serwera przy każdorazowym pobieraniu tekstu ze strony, a więc serwer nie będzie doświadczał z tego powodu szeroko pojętych lagów. Rozumiem jednak możliwe problemy ze zrozumieniem podstaw Javy, więc istnieje opcja użycia tego wyrażenia pochodzącego z SkQuery. Po raz trzeci to powtórzę - nie należy wykonywać tej operacji synchronicznie. Pomocny w osiągnięciu tego okaże się efekt $ thread, notabene również pochodzący z SkQuery.
  11. Nie musiał Pan wysyłać całego skryptu. Wystarczy przecież tylko porównać zawartość listy {dragons::*} z nazwą klikniętego inwentarza. Proszę zrobić tak jak wcześniej sugerowałem. Niech Pan przed warunkiem 'if {dragons::*} contains name of event-inventory:' wypisze na czacie zawartość listy {dragons::*} i 'name of clicked inventory'. Skoro zdarzenie nie jest anulowane, powodem tego musi być brak spełnienia powyższego warunku.
  12. Co prawda moje wytłumaczenie było powiązane z moim kodem, ale tak. Masz rację, dla najprostszego przypadku taka wersja jest optymalna. Ja zdecydowałem stworzyć zmienną w celu sprawnego manipulowania tym kiedy informacja o ostatnim atakującym jest czyszczona, co widać w listenerze zdarzenia 'on quit'. Można ten skrypt dalej rozbudować o sprawdzanie różnicy czasu między czasem śmierci i czasem ostatniego uderzenia - jeśli jest dla przykładu większy niż 30 sekund, gracz, który ostatnio zaatakował, nie otrzymuje zabójstwa.
  13. @xAxee Jeśli się nie mylę przyjacielu, użycie %attacker% (po sprawdzeniu czy typ ostatnio atakującego to gracz) nie ma sensu, gdyż może zwrócić <none> przy chociażby śmierci od upadku z wysokości. Zamiast tego należałoby zapisywać do zmiennej przypisanej do ofiary (atakowanego gracza) ostatnio atakującego gracza. on join: {kills::%player%} is not set set {kills::%player%} to 0 on damage of player: attacker is a player set {lastAttacker::%victim%} to attacker on quit: clear {lastAttacker::%player%} on death of player: last attacker of victim is a player {lastAttacker::%victim%} is set add 1 to {kills::%{lastAttacker::%victim%}%} on chat: {kills::%player%} < 5 cancel event send "&cNie mozesz pisac na chacie, musisz zabic 5 osob" to player
  14. Rozwiązanie Axee'a jest jak najbardziej poprawne, jednak można je napisać krócej i bardziej przyszłościowo - to znaczy z myślą o ewentualnym dodawaniu kolejnych przyrostków. function convertNumber(n: number) :: text: set {_exponents::*} to 12, 9, 6 and 3 set {_suffixes::*} to "t", "b", "m" and "k" loop {_exponents::*}: {_n} >= 10^(loop-value) set {_value} to round({_n} / 10^(loop-value - 1)) / 10 return "%{_value}%%{_suffixes::%loop-index%}%" return "%{_n}%"
  15. Sugeruję zapętlić wszystkie przedmioty w ekwipunku użytkownika (a więc 'loop all items in player's inventory') i sprawdzać w każdej iteracji pętli czy dany przedmiot to pszenica, która posiada odpowiednią nazwę. Dodatkowo przyda się tutaj wyrażenie 'item amount', gdyż każdy slot może zawierać nie więcej niż 64 sztuki danego przedmiotu, więc trzeba będzie to jakoś sprawnie zliczać. Drugie rozwiązanie, które jest moją propozycją zmiany pomysłu owej "giga pszenicy" - zrobić tak, aby ona była blokiem (snopem) siana. Wtedy Skript będzie w stanie spokojnie na podstawie samego typu przedmiotu poprawnie określić co może zabrać z ekwipunku, a co nie.
  16. Pierwszy błąd mówi o tym, że Pan próbuje użyć w funkcji wyrażenia 'event-block', które nie jest w niej obecne. Jeśli Pan chce sprawdzać co jest w skrzyni w środku funkcji, musi Pan do niej przesłać tę skrzynię jako parametr. Przykład poniżej. function exampleFunction(p: player, b: block): inventory of {_b} contains 20 stone add 20 to {_p}'s balance Drugi błąd zdaje się być następstwem wystąpienia pierwszego. Jeśli Pan wyeliminuje przyczynę pierwszego błędu, drugi powinien zniknąć.
  17. Widzę, że dyskusja ciągle rozpala serca forumowiczów... W takim razie i ja zaproponuję swoje rozwiązanie. Niestety zdarzenie 'on fish' jest w samym Skript bardzo ubogie w wyrażenia, więc trzeba się posiłkować dodatkami. Proszę uprzejmie. Do działania poniższego skryptu wymagany jest dodatek skript-reflect. import: org.bukkit.event.player.PlayerFishEvent org.bukkit.event.player.PlayerFishEvent$State as FishEventState on PlayerFishEvent: event.getState() is FishEventState.IN_GROUND set {_hookLoc} to event.getHook().getLocation() set {_player} to event.getPlayer() set {_xyz::*} to x-loc of {_hookLoc}, y-loc of {_hookLoc} and z-loc of {_hookLoc} set {_w} to {_hookLoc}'s world set {_yawPitch::*} to {_player}'s yaw and {_player}'s pitch teleport {_player} to location({_xyz::1}, {_xyz::2}, {_xyz::3}, {_w}, {_yawPitch::1}, {_yawPitch::2})
  18. Nie zgodzę się z tym stwierdzeniem. Funkcje hashujące z rodziny SHA-2 są bezpieczne, ale tak długo jak są użytkowane w prawidłowy sposób. To samo tyczy się wszystkich innych dostępnych algorytmów. Ewentualny brak bezpieczeństwa wynika z winy osoby projektującej mechanizm logowania, nie z winy samej funkcji. Oczywiście wyjątkiem od tej zasady są wadliwie skonstruowane algorytmy jak chociażby wyżej przywołany przeze mnie MD5. Wiem, że jest to czepianie się z mojej strony, ale nie istnieje taki termin jak "odhashowanie", bo sugerowałoby to istnienie funkcji odwrotnej do funkcji hashującej. Zauważyłem, że nie napisałem o dorzucaniu soli do hasła przed hashowaniem. Mój błąd i dziękuję za poprawienie nie wprost. Do Pana piszącego ten skrypt - w dużym skrócie sól to szereg losowo wygenerowanych przy rejestracji (w kryptologicznie bezpieczny sposób) znaków, które są dodawane do hasła tuż przed hashowaniem. Wtedy w bazie danych (w Pana przypadku jest to plik variables.csv) przechowywana jest sól i hash. Jakie jest uzasadnienie użycia soli przy hashowaniu? Największym zagrożeniem dla bazy z hasłami jest niemałe ryzyko występowania takich samych haseł. Nietrudno sobie wyobrazić grupę użytkowników, którzy z lenistwa ustawią sobie hasło "123456789". Jeśli ktoś nieupoważniony ze złymi zamiarami i głową na karku dostanie się do bazy, przy odnalezieniu faktycznego hasła dla jednego hashu od razu uzyskuje dostęp do kont wszystkich użytkowników z tym samym hasłem. Dlatego sól jest ważna, bo dzięki niej mamy przynajmniej pewność, że pary (sól, hash hasła) są unikalne, co zdecydowanie zwiększa bezpieczeństwo. Dodam, że sól powinna być możliwie długa - ponieważ wynikiem algorytmu SHA-256 jest 32-bitowy ciąg znaków (a więc po prostu 32 znaki), zaleca się dodawanie soli zbudowanej również z 32 znaków. Dodatkowo, nie powinna być ona generowana poprzez zwykły generator losowych liczb (znaków). Do tego zadania sprawdzi się klasa 'java.security.SecureRandom', która dokłada wszelkich starań, aby wygenerowany ciąg bajtów (znaków) był unikalny. Jeśli mowa o spowolnieniu poszukiwań oryginalnego hasła, zysk w tym przypadku jest niewielki. Istnieją lepsze sposoby, aby tego dokonać. Na końcu mojego postu załączę artykuł, z którego swego czasu się uczyłem o hashowaniu i są tam zaprezentowane możliwe rozwiązania tego problemu. Kończąc mój wywód, Skript sam w sobie nie nadaje się do przechowywania haseł. Przykładem tego jest chociażby brak wsparcia dla generowania soli, o której notabene sami twórcy wspominają w dokumentacji. Oczywiście da się to napisać, jednak pojawiają się tutaj przez to dodatkowe trudności. Udostępniam również link do artykułu, o którym wspomniałem: https://crackstation.net/hashing-security.htm Pozdrawiam.
  19. Kormic

    Libertybans

    Według wiki pluginu tymczasowe permisje muszą być włączone. Zakładam, że ta opcja jest dostępna w pliku konfiguracyjnym pluginu.
  20. Kormic

    Blad w skrypcie

    Nie są one dobrze napisane, Pan nie stosuje dobrze wcięć w kodzie i zapomniał Pan o dwukropku na końcu pierwszej linijki. Błąd "invalid line - all code has to be put into triggers" oznacza, że Skript przy ładowaniu skryptu wykrył kod, który znajduje się poza jakimkolwiek wyzwalaczem (ang. trigger). Zasada w Skript jest taka: jeśli jakiś kod ma być następstwem linijki (warunku, listenera zdarzenia, itd.) zakończonej dwukropkiem, musi on mieć o jedno wcięcie więcej. Pan się nie stosuje do tej zasady i dlatego Skript zgłasza błędy. Szczególnie rażącym w oczy jest fragment zaczynający się od linijki 11. Dodam, że te wiadomości wyświetlane graczom nie są zależne od argumentu nr 2 - wystarczy jedna zależna tylko od warunku sprawdzającego czy argument nr 2 został podany.
  21. Niestety nie jestem w stanie odtworzyć bugu, z którym Pan się męczy. Może Pan ma literówki lub niezgadzające się kolory w nazwach GUI i przez to warunek nie jest spełniony? Napisałem poniższy kod testowy i wszystko działa jak należy, nieważne o którym GUI mówimy. on script load: set {dragons::*} to "&6smok1", "&6smok2", "&6smok3", "&6smok4", "&6smok5", "&6smok6", "&6smok7", "&6smok8", "&6smok9", "&6smok10", "&6smok11", "&6smok12" set {guis::dragons} to "&cSmoki" command /dragonstest: trigger: set {_g} to chest inventory with 3 rows named {guis::dragons} loop (size of {dragons::*}) times: set slot (loop-number - 1) of {_g} to iron ingot named {dragons::%loop-number%} open {_g} to player function mlody_smokiGUI(p: player, n: number): set {_g} to chest inventory with 3 rows named {dragons::%{_n}%} set slot (integers between 0 and 26) of {_g} to gold ingot named "Test" open {_g} to {_p} on inventory click: if name of event-inventory is {guis::dragons}: if name of event-item is not " ": cancel event set {_n} to name of event-item loop 12 times: if {dragons::%loop-number%} contains {_n}: close player's inventory mlody_smokiGUI(player, loop-number) stop if {dragons::*} contains name of event-inventory: cancel event send "Nie możesz tego wyjąć!" to player command /dragonsclear: trigger: clear {dragons::*} and {guis::dragons}
  22. Skrypt w mojej ocenie wygląda w porządku, nie widzę tu jakichkolwiek błędów. Nie jestem w stanie odtworzyć tego buga, skrypt działa u mnie całkowicie poprawnie (no, musiałem jedynie zmienić w pierwszej linijce listenera zdarzenia 'of wheat' na 'of ripe wheat plant'). Wszystko zależy od tego jaka jest zainstalowana wersja Skripta na serwerze i na jakiej wersji serwer jest postawiony. Jako szybkie rozwiązanie mogę doradzić dwie rzeczy. Posłużyć się wyrażeniem 'age of %block%', które zwraca wiek bloku zaczynając od 0 i kończąc na 7 w przypadku pszenicy. Skorzystać z 'block data', aby sprawdzić wiek pszenicy. Przykład poniżej. # Sprawdzenie czy wiek pszenicy jest równy 7 (czy jest już gotowa do zebrania) if event-block is wheat plant[age=7]: # Dalszy kod... Pozdrawiam.
  23. Widzę, że Pan nie zajrzał do dokumentacji. Proszę się z nią zapoznać. Zmienna przechowująca hash może być wyczyszczona tak samo jak dowolna inna zmienna.
  24. Nie rozumiem pytania. Każdą zmienną usuwa się w ten sam sposób, konkretniej za pomocą tego efektu (clear/delete).
  25. Mógłby Pan powiedzieć co się zmieniło w tej wersji? Dobrym zwyczajem jest podawanie listy nowości i zmian. Dzięki temu użytkownicy wiedzą co tak właściwie uległo zmianom. W mojej ocenie zabezpieczenia powinny mieć dla Pana najwyższy priorytet i do czasu ich poprawienia nie powinien Pan wypuszczać aktualizacji. W końcu to jest skrypt zarządzający hasłami. Według mnie gracze z odpowiednią permisją również powinni mieć dostęp do tych komend.
×
×
  • Dodaj nową pozycję...