Skocz do zawartości

Kormic

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

    11012
  • Rejestracja

  • Ostatnia wizyta

  • Wygrane w rankingu

    230

Treść opublikowana przez Kormic

  1. 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.
  2. 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?
  3. 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ąć.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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.
  9. 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.
  10. @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
  11. 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}%"
  12. 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.
  13. 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ąć.
  14. 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})
  15. 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.
  16. Kormic

    Libertybans

    Według wiki pluginu tymczasowe permisje muszą być włączone. Zakładam, że ta opcja jest dostępna w pliku konfiguracyjnym pluginu.
  17. 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.
  18. 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}
  19. 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.
  20. 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.
  21. Nie rozumiem pytania. Każdą zmienną usuwa się w ten sam sposób, konkretniej za pomocą tego efektu (clear/delete).
  22. 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.
  23. Kormic

    zmienna czasu

    Niech mi Pan uwierzy, że chciałbym. Problem w tym, że trzeba wykonać kilka kroków i jest to nieuniknione. Najpierw należy zamienić okres czasu na tekst, pousuwać przecinki, spójniki "and" i podstawić pod jednostki czasu ich skrótowe wersje. Następnie trzeba podzielić ten tekst na fragmenty dzieląc go na każdej spacji i zapisać do listy zmiennych. Parzyste elementy (czyli reszta z dzielenia równa 0) to jednostki czasu, a nieparzyste elementy (reszta z dzielenia równa 1) to ich wartości. Dzielimy je według tego kryterium na dwie listy i dodatkowo zaokrąglamy wartości do najbliższych liczb całkowitych. W ramach ostatniego kroku musimy połączyć te dwie listy ponownie w jeden napis. Gdyby wykonać go dla przypadku szczególnego (na przykład zakładamy, że będą tylko godziny i minuty), być może skrypt byłby nieco krótszy. Niemniej jednak uważam, iż zawsze warto szukać rozwiązania dla przypadku ogólnego, bo mamy pewność, że ono zawsze zadziała.
  24. Kormic

    zmienna czasu

    Niestety trudno tutaj o przykładowy kod. Mogę jedynie pokazać jak ja bym napisał taką funkcję. Wiem, że z dawania gotowego kodu pożytku praktycznie brak, ale mam nadzieję, że Pan sobie przeanalizuje ten skrypt i zrozumie jego działanie. Może Pan sobie używać w środku funkcji instrukcję 'broadcast', aby wyświetlić wartość danej zmiennej i widzieć "na bieżąco" co się dzieje. Proszę uprzejmie. W razie wątpliwości proszę pytać, chętnie odpowiem. Dodatkowo odsyłam do dokumentacji, którą się już kilkukrotnie posiłkowałem w moim poprzednim poście. function formatTimespan(t: timespan) :: text: set {_tText} to "%{_t}%" replace all "and " with "" in {_tText} replace all ", " with " " in {_tText} replace all "hours" with "h" in {_tText} replace all "minutes" with "m" in {_tText} replace all "seconds" with "s" in {_tText} set {_split::*} to {_tText} split at " " loop (size of {_split::*}) times: if mod(loop-number, 2) is 1: add "%round({_split::%loop-number%} parsed as number)%" to {_timeNumbers::*} continue add {_split::%loop-number%} to {_timeUnits::*} set {_returnTimespan} to "" loop {_timeNumbers::*}: if (loop-index parsed as number) is 1: set {_returnTimespan} to "%loop-value%%{_timeUnits::%loop-index%}%" continue set {_returnTimespan} to "%{_returnTimespan}%, %loop-value%%{_timeUnits::%loop-index%}%" return {_returnTimespan} command /testformat: trigger: set {_time} to "6 hours and 11.17 minutes" parsed as timespan send formatTimespan({_time}) to sender
  25. Kormic

    zmienna czasu

    Z tego co widzę, nie musi Pan w tym kodzie używać zmiennych globalnych, gdyż są one niepotrzebnie zapisywane w pliku variables.csv (przy założeniu, że nie ustawił sobie Pan jakiejkolwiek bazy danych). Zamiast tego może Pan używać zmiennych lokalnych, które są automatycznie czyszczone po wykonaniu całego kodu, w którym są obecne. Zmienne lokalne tworzymy poprzez dodanie podłogi (ang. underscore) '_' na początku nazwy zmiennej. Przykład: `set {_test} to "Test"`. Oczywiście, jeśli Pan gdzieś indziej wykorzystuje te zmienne, nie ma problemu. Nie może Pan tak robić, ponieważ efekt 'replace' może być używany tylko na zmiennej zawierającej tekst. Musi Pan więc zamienić wartość zmiennej {test1} na wartość typu tekst, co można najprościej uzyskać za pomocą poniższej linijki. set {_textTest} to "%{test1}%" replace ... Jeśli natomiast chce Pan zaokrąglić ilość minut dla danego okresu czasu, musi Pan użyć wyrażenia 'split' w celu podzielenia tekstu na spacji " ", a następnie zapisać jego wynik do jakiejś listy zmiennych lokalnych. Dalej, należałoby na podstawie wielkości listy (wyrażenie 'amount') określić ile mamy jednostek czasu (tylko sekundy, sekundy i minuty, godziny, a może i nawet dni), a następnie na podstawie tego wziąć odpowiedni element z tej listy, parse'ować go jako liczbę, zaokrąglić i zapisać ponownie do tekstu. Jak widać, roboty jest trochę. Istnieje również druga opcja - myślę, że prostsza. Jak wcześniej, dzielimy tekst z czasem na spacji i zapisujemy do listy zmiennych lokalnych. Następnie zapętlamy tę listę i próbujemy każdy element parse'ować jako liczbę i zapisać do jakiejś zmiennej. Jeśli ta zmienna będzie pusta, oznacza to, że zapętlany element nie był liczbą, a jakimś napisem (na przykład "hours", a nie "2"). Tutaj z pewnością przyda się ten warunek. Jeśli zmienna posiada jakąś wartość (a więc warunek 'is set' zwrócił 'true'), można ją dodać jako kolejnej listy i próbować to formatować. W skrócie - w Skript nie istnieje łatwa i przyjemna w użyciu instrukcja pozwalająca na formatowanie typu 'timespan'. A szkoda.
×
×
  • Dodaj nową pozycję...