-
Ilość zawartości
11012 -
Rejestracja
-
Ostatnia wizyta
-
Wygrane w rankingu
230
Treść opublikowana przez Kormic
-
Proszę bardzo. Skrypt był testowany. Muszę Panu powiedzieć jeszcze o dwóch rzeczach zanim Pan zacznie korzystać z poniższego skryptu: Jeżeli na serwerze będzie kilkudziesięciu graczy, poniższy skrypt może być obciążający dla serwera z racji tego, że dla każdej strzały jest tworzona pętla wykonująca się 20 razy na sekundę. Strzały wbite w ziemię/ścianę, doświadczenie leżące na ziemi i tym podobne rzeczy również są klasyfikowane jako byty (co prawda nieżywe, ale byty), więc jeżeli będą one na drodze od strzelającego do jego celu, podążanie może nie zadziałać. on shoot: shooter is a player projectile is an arrow targeted entity of shooter is a player set {_target} to targeted entity of shooter set {_startVelocity} to vector length of (velocity of projectile) set {_velocityVector} to vector({_startVelocity}, {_startVelocity}, {_startVelocity}) while projectile is not on ground: exit loop if {_target} or projectile is dead set velocity of projectile to {_velocityVector} * (normalized (vector from projectile to {_target}'s head)) wait 1 tick Gdyby pojawiły się jakieś problemy ze skryptem, proszę dać znać. Pozdrawiam.
-
Problem został rozwiązany.
-
Plugin ten oferuje wsparcie dla PlaceholderAPI (PAPI), więc jeżeli PAPI posiada jakiekolwiek rozszerzenie pozwalające na wyświetlenie czasu, jest to jak najbardziej możliwe. Pełną listę rozszerzeń i placeholderów wspieranych przez PlaceholderAPI znajdzie Pan tutaj. Proszę zwrócić uwagę na to, że lwia część rozszerzeń musi być uprzednio pobrana za pomocą komendy '/papi ecloud download <nazwa_rozszerzenia>'. Jeżeli dane rozszerzenie nie jest oficjalnie wspierane przez PAPI (na przykład rozszerzenie Skript, które pozwala używać zmiennych ze Skript jako placeholderów), należy je pobrać bezpośrednio ze strony eCloud (Expansion Cloud). Proszę mieć z tyłu głowy to, że nieoficjalne rozszerzenia właściciel serwera pobiera i instaluje na własną odpowiedzialność. Tak się składa, że raptem kilka dni temu pomagałem innemu Panu z korzystaniem z rozszerzenia PAPI o nazwie LocalTime, który oferuje wyświetlanie czasu. Wątek, o którym mówię, znajdzie Pan poniżej. Jeśli jednak chodzi o nazwę gracza, może Pan skorzystać z rozszerzenia Player i skorzystać z odpowiadającego Panu placeholdera. Na koniec dodam, że jak najbardziej jest możliwe stworzenie nowych placeholderów z pomocą dodatku skript-placeholders, jednakże nie ma potrzeby wynajdywania koła na nowo. Dodatek ten powinien być wykorzystywany tylko wtedy, gdy nie istnieje jakikolwiek odpowiadający nam placeholder. Pozdrawiam.
-
Ten temat został przeniesiony.
-
Proszę skorzystać z tego efektu i użyć słowa 'infinite'. W podlinkowanym fragmencie dokumentacji Pan znajdzie przykład z listenerem zdarzenia 'on join', w którym jest pokazane jak można go wykorzystać. Pozdrawiam.
-
Błędy są co prawda tylko dwa, jednakże mam również kilka uwag, które pozwolą na napisanie Panu lepszego (to znaczy schludniejszego) kodu. Zacznę od błędów. Pierwszy błąd dotyczy braku możliwości interpretacji przez Skripta listenera zdarzenia 'on tab complete'. Zdarzenie te nie jest wspierane przez samego Skripta, należy więc skorzystać z jednego z dodatków. Osobiście mogę polecić dodatek SkBee, który obsługuje zdarzenie 'on tab complete', jednakże zaznaczam, że kod będzie wymagał niewielkich modyfikacji. Fragment dokumentacji z przykładem dla SkBee i tego zdarzenia znajdzie Pan na tej stronie. Drugi błąd jest związany z niepoprawnym użyciem składni wyrażenia 'parsed as'. Proszę zauważyć, że może Pan je stosować jedynie do tekstu - w definicji komendy jest już wymóg, iż drugi jej argument musi być dowolną liczbą (<number> w linijce 5.), a więc Pan tak właściwie zmusza Skript do interpretowania liczby rzeczywistej jako liczbę rzeczywistą (co nie ma sensu i jest całkowicie zbędne). Gdy gracz poda drugi argument niebędący liczbą, komenda nie zadziała i na czacie wyświetli się komunikat zawarty w polu konfiguracji komendy 'usage' (linijka 7.). A teraz przejdźmy do moich uwag. Pierwsza uwaga odnosi się do pierwszego warunku w kodzie komendy i jest również powiązana z ustawieniem typu drugiego argumentu jako 'number'. Nietrudno spostrzec, że w takiej sytuacji warunek ten (linijka 11.) jest niepotrzebny, ponieważ nigdy nie zostanie spełniony. Sprawdzanie typu drugiego argumentu wykona wewnętrznie sama komenda, co objawi się (jak w 2. błędzie) pokazaniem graczowi komunikatu z pola 'usage'. W mojej ocenie typem drugiego argumentu powinien być 'integer' (liczba całkowita), nie 'number' (liczba rzeczywista). Mało sensownym wydaje się możliwość ocenienia czyjejś działki na przykładowo 4.3827193. Ograniczenie ocen do zbioru {1,2,3,4,5} ma ręce i nogi, no chyba że Panu zależy na ocenach takich jak chociażby 4,5 czy też 4,8. Samo ograniczenie zakresu możliwych liczb w argumencie 2. wynika z warunku w linijce 15. Gdyby miał Pan jakieś pytania, proszę śmiało je zadawać. Pozdrawiam.
-
NIEAKTUALNE ($ Płacę) Szukam osoby która będzie prywatnie pisała skrypty na zlecenie
Kormic odpowiedział(a) na kxozek temat w Archiwum współpracy
Ten temat został zamknięty. -
NIEAKTUALNE ($ Płacę) Szukam osoby która będzie prywatnie pisała skrypty na zlecenie
Kormic odpowiedział(a) na kxozek temat w Archiwum współpracy
Zwyczajnie zamotałem się, każdemu może się to zdarzyć, szczególnie o takiej porze. Mówienie, że nie wiedziałem w ogóle do czego ona służy, jest hiperbolą. Jeżeli Pan wytnie fragmenty kodu i wyda polecenie do ChataGPT, aby uzupełnił luki, rezultat będzie niemalże ten sam, gdyż pozostała część skryptu narzuca już określoną logikę postępowania w skrypcie. Gdyby Pan nakazał mu wykonanie skryptu całkowicie od zera, mogę z dużą dozą pewności stwierdzić, że rozwiązanie byłoby już co najwyżej podobne. Co do wiadomości, co mogę powiedzieć... tutaj wytłumaczenia nie ma żadnego, jest to zwyczajnie kwestia nieszczęśliwej zbieżności. Co prawda nie widziałem uzupełnionego kodu przez sztuczną (nie)inteligencję, ale wierzę Panu na słowo, bo nie widzę powodu ku temu, aby Pan mówił nieprawdę w kontekście wygenerowanego kodu. Dziękuję, wzajemnie. Nie zgadzam się z Pana oceną sytuacji, ale miał Pan pełne prawo do podjęcia takich kroków. Mogę jedynie powiedzieć, że zerwanie ze mną współpracy to dla Pana strata. Jeszcze mam jedno pytanie, całkowicie niezwiązane z powyższą wiadomością. Skoro Pan oznaczył temat jako nieaktualny, czy mogę go zamknąć? Pozdrawiam. -
napisałem w miare prosty skrypt w unreal engine 4 i nie wiem czemu nie działa pomoże ktoś
Kormic odpowiedział(a) na zxjOVER pytanie w Pytania i problemy
Ten temat został przeniesiony. -
NIEAKTUALNE ($ Płacę) Szukam osoby która będzie prywatnie pisała skrypty na zlecenie
Kormic odpowiedział(a) na kxozek temat w Archiwum współpracy
Miałem (nie)przyjemność współpracować z tym Panem i myślę, że najprościej będzie wypisać wady i zalety, zaczynając od tych drugich. Choć muszę przyznać, że współpraca była krótka, bo napisałem jedynie dwa dłuższe skrypty, o tym dalej. Zalety: szczegółowość w swoich zleceniach - opisane na tyle dokładnie, że rzadko kiedy trzeba dopytywać co jak ma działać, wywiązywanie się z umowy - wynagrodzenie ustalane przed przystąpieniem do pisania skryptu i otrzymywane bezproblemowo. Wady: duża podejrzliwość - wielokrotne oskarżenia o korzystanie z pomocy ChatGPT do tworzenia zleconych mi skryptów pomimo mojej długoletniej działalności na forum, była mowa o dowodach, ale żadnych nie ujrzałem. Mogę dopowiedzieć, że do zarzutów należało: pisanie "robotycznie" wyglądającego kodu (nadal nie rozumiem co to znaczy), stosowanie języka angielskiego do nazewnictwa zmiennych i jednorazowy przypadek gdy zapomniałem o istnieniu danej linijki sprawdzającej permisję. Podsumowując moje przemyślenia, Zleceniodawca wynagradza pracę i dobrze opisuje zlecenia, ale jeśli ktoś jest obeznany ze Skript i dodatkami do niego (na przykład skript-reflect, właściwie tylko z niego korzystałem), niech się nie spodziewa dłuższej współpracy. Pozdrawiam. -
Jak ukryc wiadomosc resetowania sie rud w pluginie RealMine
Kormic odpowiedział(a) na Be46 pytanie w Pytania i problemy
Pierwszy raz słyszę o tym pluginie, ale otworzyłem jego opis na stronie SpigotMC i rzuciła mi się w oczy komenda '/mine silent <name>' (w miejsce '<name>' wstawić nazwę kopalni). Wydaje mi się, że to właśnie o nią chodzi. Ewentualnie można zobaczyć czy pod komendą '/mine panel' po wybraniu odpowiedniej kopalni jest opcja jej wyciszenia. Pozdrawiam. -
Generalnie skrypt jest dobrze napisany, ale wkradł się do niego niewielki błąd. Mianowicie, gracz wysyłający wiadomość będzie otrzymywał wiadomość na czacie jakby pisał do samego siebie. Ponadto, mam dwie uwagi do Pana skryptu. Zamiast używać przeciwnych warunków (na przykład 'is not set' i 'is set'), lepszym podejściem jest użycie w poprzednim warunku instrukcji 'stop', co zapobiegnie dalszemu wykonywaniu się kodu. Przykłady tego będą pokazane w mojej wersji tego skryptu. Jeżeli do wysyłającego wiadomość odnosimy się wyrażeniem 'player', powinniśmy zagwarantować to, że tylko gracze mogą wykonywać komendę '/msg'. Jeśli chcemy, aby na przykład konsola również mogła z niej korzystać, używamy wyrażenia 'sender'. Ja zaprezentuję drugie podejście. Poniżej udostępniam mój skrypt na komendę /msg. options: msgUsage: &6Poprawne użycie: &e/msg <gracz> <wiadomość> command /msg [<player>] [<text>]: trigger: if arg 1 is not set: send "&6Podaj gracza, do którego chcesz wysłać wiadomość." and "{@msgUsage}" to sender stop if arg 2 is not set: send "&6Podaj wiadomość, którą chcesz wysłać do podanego gracza." and "{@msgUsage}" to sender stop send "&c[&6ja &c-> &6%arg 1%&c] &f%arg-2%" to sender send "&c[&6%sender% &c-> &6ja&c] &f%arg-2%" to arg 1 send title "&b&l!" to arg 1 Pozdrawiam.
-
Pan w drugim linku ma stronę opisującą dostępne formaty czasu (i daty), stamtąd biorę informacje jak zapisywać dany format. Pierwsza tabela zawiera wszystkie dostępne "składowe" formatu, natomiast w drugiej tabeli znajdzie Pan przykłady. Zalecam się zastanowić jak to zrobić. Jeśli Pan nie będzie miał pomysłu jak to napisać lub dojdzie do poprawnej (a właściwie jednej z wielu poprawnych) odpowiedzi, może Pan sprawdzić ją poniżej. Pozdrawiam.
-
jak ktoś wyszedł poza border to został cofnięty
Kormic odpowiedział(a) na DariuszGki pytanie w Zlecenia
Proszę uprzejmie. W Skript odległość odrzucania zwykle określa się metodą prób i błędów, a więc będzie musiał Pan samemu poeksperymentować z wartościami w sekcji 'options'. Opiszę je poniżej: worldBorderWorldName - nazwa świata, w którym znajduje się world border, generalPushForce - ogólna siła popychania gracza, im większa, tym silniej gracz jest popychany, verticalPushForce - siła wypychania gracza do góry, zasada ustawiania jak wyżej. Proszę pamiętać również o ustawieniu współrzędnych X i Z środka (centrum) world borderu w linijce 9. Na koniec dodam, że jeśli Pan korzysta z wersji Skript niższej niż 2.8.0, musi Pan zamienić pojedynczą gwiazdkę w linijce 13. na dwie gwiazdki '**'. options: worldBorderWorldName: "world" generalPushForce: 0.8 verticalPushForce: 0.2 damage of player: damage cause is world border victim is in world {@worldBorderWorldName} set {_centerLocation} to location at (0, y-loc of victim, 0) in world {@worldBorderWorldName} set {_v} to normalized (vector between victim and {_centerLocation}) set y of {_v} to {@verticalPushForce} set {_vForce} to vector({@generalPushForce}, {@generalPushForce}, {@generalPushForce}) set {_v} to {_v} * {_vForce} push victim {_v} Pozdrawiam. -
Proszę bardzo. W linijce 2. można ustawić ten "nieusuwalny" przedmiot, który nie zostanie usunięty przy teleportacji. W 7. linijce natomiast jest podana lokalizacja spawnu. Pierwsze trzy liczby to koordynaty X, Y i Z. Czwarty argument to świat podany za pomocą nazwy, a piąty i szósty argument to tzw. yaw i pitch. Yaw to obrót głowy lewo-prawo wyrażony w stopniach (od -180° do 180°), natomiast pitch to obrót głowy dół-góra wyrażony w stopniach (od -90° do 90°). Proszę bardzo. Skrypt nie był testowany, jednakże nie powinny wystąpić jakiekolwiek związane z nim problemy. options: unremovableItem: stick named "&aTest" command /spawnandclear: executable by: players trigger: teleport player to location(100, 100, 100, world "world", 45, 0) loop all items in player's inventory: loop-item is not {@unremovableItem} remove loop-item from player's inventory send "&aZostałeś przeteleportowany na spawn i usunięto wszystkie twoje przedmioty poza specjalnym przedmiotem." to player Pozdrawiam. -
Dziękuję za informację, ale wolę używać zwrotów grzecznościowych z racji tego, że zazwyczaj nie wiem z kim mam do czynienia. Wracając do meritum, rozumiem, że Pan korzysta z rozszerzenia do PlaceholderAPI o nazwie LocalTime. Pan używa jednego z czterech placeholderów udostępnianych przez te rozszerzenie. Poniżej wklejam wszystkie cztery placeholdery rozszerzenia LocalTime. %localtime_time% %localtime_time_<SimpleDateFormat>% %localtime_timezone_<TimeZoneID>% %localtime_timezone_<TimeZoneID>,<SimpleDateFormat>% Pana najbardziej będzie interesował drugi placeholder, gdyż pozwala on dodatkowo na przesłanie formatu zwracanego czasu według reguł klasy SimpleDateFormat. Jeśli jest potrzeba pobrania jedynie godziny w 24-godzinnym formacie (0-23) wraz z obecną minutą, wystarczy za '<SimpleDateFormat>' podstawić 'HH:mm' i powinno to zadziałać. Gdyby jeszcze Pan potrzebował czasu w 12-godzinnym formacie (1-12) wraz z obecną minutą i znacznikiem AM/PM, można użyć 'hh:mm a'. Po więcej informacji odsyłam do dokumentacji placeholderów w PlaceholderAPI i do fragmentu dokumentacji Javy opisującego klasę SimpleDateFormat. Pozdrawiam.
-
O co Pan pyta? Proszę się odnieść do konkretnej części mojego postu, bo nie wiem o której jego części Pan mówi. Pozdrawiam.
-
Skoro założył Pan nowy wątek w dziale "Skript > Pytania i problemy", zakładam, że Pan nie ma na myśli placeholder, a wyrażenie, które zwróci obecną godzinę w Skript. Może Pan w tym celu wykorzystać wyrażenie 'now', które domyślnie zwraca obecną datę wraz z obecną godziną z dokładnością co do minuty. send "%now%" to sender # Zwróci na przykład 22.06.2024, 14:30 Co więcej, może Pan je formatować wedle własnych upodobań za pomocą wyrażenia '%date% formatted as %text%' tak, aby wyodrębnić z niego interesujące nas informacje (na przykład godzinę i minuty). set {_time} to now formatted as "HH:mm" Po wyświetleniu zawartości zmiennej {_time} na czacie, ukaże nam się obecna godzina w formacie 24-godzinnym wraz z minutami. Jeżeli Pan chce skorzystać z formatu 12-godzinnego, należy zamienić wielkie "HH" na małe "hh". W razie pytań proszę śmiało je zadawać. Pozdrawiam.
-
Zaliczanie śmierci moba do zmiennej po zginięciu od ognia, spadnięciu z wysokości itp.
Kormic odpowiedział(a) na nnisu pytanie w Pytania i problemy
Z początku myślałem, że Pan może mieć jakiś problem ze Skriptem, ale sprawdziłem przed chwilą działanie wyrażenia 'last attacker of %entity%'. Rzeczywiście jest tak jak Pan mówi - w przypadku śmierci od obrażeń innych niż zadane bezpośrednio przez dowolny byt, wyrażenie te zwraca "<none>". Sprawdziłem kod źródłowy Skripta i dowiedziałem się kilku ciekawych rzeczy. https://github.com/SkriptLang/Skript/blob/7fc699e17299763523942d99524216480d426295/src/main/java/ch/njol/skript/expressions/ExprLastAttacker.java#L59 Warto zwrócić uwagę na użycie metody 'getLastDamageCause()', która (jak nazwa wskazuje) zwraca przyczynę ostatnio zadanych obrażeń, a właściwie to całe zdarzenie, które było powiązane z zadanymi ostatnio obrażeniami. Co więcej, poniższa klasa odpowiedzialna za wyrażenie 'attacker' przewiduje jedynie zdarzenie 'EntityDamageByEntityEvent'. Nawet kod od zdarzenia 'EntityDamageByBlockEvent' (np. gdy dozownik trafi w zombie strzałą) jest objęty komentarzem, a więc w przypadku śmierci od strzały wystrzelonej z dozownika również uświadczylibyśmy na czacie '<none>'. https://github.com/SkriptLang/Skript/blob/7fc699e17299763523942d99524216480d426295/src/main/java/ch/njol/skript/expressions/ExprAttacker.java#L78 Na końcu metody 'get()' w klasie ExprAttacker można zauważyć 'return null'. Ponieważ obrażenia od ognia nie są przewidziane w żadnym z warunków tej metody, otrzymujemy w rezultacie niemiło widziane '<none>'. Skoro już poznaliśmy źródło nieporozumienia, podpowiem Panu jak można rozwiązać ten problem. W mojej ocenie najprostszym wyjściem z tej sytuacji będzie użycie 'metadata'. Jak dokumentacja mówi, są to informacje przechowywane w rozmaitych metadata holderach (byty, bloki, itd.) do momentu restartu serwera, ale na Pana potrzeby wydaje mi się, że to będzie wystarczające. No dobrze, jak więc użyć metadata w Pana przypadku? Jest to bardzo proste. Dla przykładu ustawimy wartość metadata "lastAttacker" jako byt, który był odpowiedzialny za zadanie obrażeń. Następnie, będziemy mogli odczytywać jej wartość gdy będzie to potrzebne. Pokażę na przykładzie poniżej. W listenerze zdarzenia 'on damage' należy sprawdzić czy atakujący jest graczem. Jeśli tak, ustawiamy wartość znacznika (tagu) metadata "lastAttacker" na atakującego (w tym przypadku wiemy, że to jest gracz, ponieważ zweryfikowaliśmy to warunkiem w linijce powyżej). # [...] attacker is a player set metadata tag "lastAttacker" of victim to attacker # [...] Następnie, w listenerze zdarzenia 'on death of a zombie' sprawdzamy czy metadata tag "lastAttacker" posiada wartość (warunek 'is set'). Możemy to zrobić bezpośrednio, albo też możemy zapisać jej wartość do zmiennej i sprawdzić czy zmienna przechowuje jakąkolwiek wartość. Ja pokażę drugi sposób, gdyż jest schludniejszy - unikamy podwójnego użycia tego samego wyrażenia. # [...] set {_player} to metadata tag "lastAttacker" of victim {_player} is set # [...] Jeżeli warunek w powyższym fragmencie kodu zostanie spełniony, możemy być pewni, że ofiara posiada zapisaną w sobie informację o ostatnio atakującym graczu. Wystarczy wtedy użyć 'uuid of {_player}' i wszystko powinno być działać jak należy. Oczywiście może Pan rozszerzyć działanie powyższych kodów na wszystkie byty tak, aby na przykład owca zapisywała informację o tym, że wilk ją zaatakował. Wtedy kod nieco się skomplikuje i niewykluczone, że trzeba będzie użyć więcej metadata tagów. Zastanawiające jest jedynie to co jeśli zombie umrze po wyjściu gracza z serwera. Co prawda Skript w tej sytuacji powinien "przemianować" zapisaną informację o online player na informację o offline player. Warto jednak to przetestować, chociaż tę kwestię myślę, że mogę pozostawić Panu do własnego wglądu. Gdyby jeszcze miał Pan jakieś pytania lub wątpliwości, śmiało. Pozdrawiam. -
Wystarczy, że Pan doda warunek na początku listenera zdarzenia 'on place' jak poniżej. event-world is world "nazwa_świata" Dzięki powyższej modyfikacji lista przechowującą bloki przeznaczone do usunięcia będzie poszerzana tylko jeśli blok zostanie postawiony w świecie "nazwa_świata". Na koniec dodam, że kod można zoptymalizować pod kilkoma względami, gdyż istnienie zmiennej globalnej {Reset::Timer} jest bezzasadne. To samo tyczy się użycia listy lokalizacji {Reset::Blocks::*}. Jeśli jednak Pan będzie chciał, abym to poprawił, proszę utworzyć nowy wątek w dziale "Skript > Zlecenia". Tam pokażę jak można powyższy skrypt upiększyć i usprawnić. Pozdrawiam.
-
Zaliczanie śmierci moba do zmiennej po zginięciu od ognia, spadnięciu z wysokości itp.
Kormic odpowiedział(a) na nnisu pytanie w Pytania i problemy
No dobrze, już podpowiadam. Problem z użyciem tego wyrażenia jest taki, ze zwracana przez nie wartość jest typu 'Object', a więc może to być tak właściwie wszystko. Wynika to z faktu, iż ostatnio atakującym może być dowolny byt, a nawet blok, na przykład dozownik (ang. dispenser), który wystrzeliwuje strzały. Bezpieczniejszą opcją będzie zamiana wartości wyrażenia 'last attacker of %entity%' na typ tekstowy, aby później nakazać Skriptowi interpretację go jako gracza offline. Dlaczego gracz offline, a nie online? Powody ku temu są dwa: Gracz może wyjść z serwera zanim zombie umrze. Może tak być w przypadku nadania efektu obumierania, podpalenia, itd. Powód mniej oczywisty to to, że wyrażenie '%string% parsed as player' ma pewną mało znaną, a znaczącą wadę. W przypadku parse'owania jako gracza online wystarczy początek nazwy gracza, aby Skript "wygenerował" nam obiekt gracza. Natomiast jeśli używamy '[...] parsed as offline player', musimy podać dokładnie nazwę gracza. Podam przykład wykorzystujący moją nazwę. "Kormic" parsed as player # Zwróci obiekt gracza o nazwie "Kormic", o ile jest on na serwerze "Kor" parsed as player # Zwróci obiekt gracza o nazwie "Kormic", o ile jest on na serwerze "Kormic" parsed as offline player # Zwróci obiekt gracza o nazwie "Kormic" niezależnie od tego czy jest i był kiedykolwiek na serwerze "Kor" parsed as offline player # Zwróci obiekt gracza o nazwie "Kor" niezależnie od tego czy jest i był kiedykolwiek na serwerze W tej sytuacji pojawia się pytanie "Co jeśli poprosimy o obiekt gracza online o nazwie "Kor", podczas gdy na serwerze są gracze "Kor" i "Kormic"? Którego gracza otrzymamy?". Dlatego też w mojej ocenie bezpieczniejszy jest 'parsed as offline player', bo musimy podać dokładną nazwę. Poniżej udostępniam Panu fragment kodu, dzięki któremu w zmiennej {_player} przechowywany jest obiekt gracza offline (offline - może, ale nie musi być online). Wtedy wystarczy użyć 'uuid of {_player}' tam gdzie trzeba. # [...] last attacker of victim is a player set {_player} to "%last attacker of victim%" parsed as offline player # [...] Alternatywnie, można spróbować jak poniżej. Nie mam pewności czy poniższy sposób zadziała poprawnie, ale spróbować nie zaszkodzi. # [...] last attacker of victim is a player set {_uuid} to uuid of last attacker of victim # [...] Pozdrawiam. -
Co do pierwszego, nie podoba mi się ta pętla 'while'. Zgaduję, że w Pana kodzie wygląda to tak jak poniżej. on join: while player is online: # [...] wait {_timespan} Proszę zauważyć, że powyższy skrypt powoduje, iż na serwerze działa jednocześnie n pętli 'while', gdzie n to liczba graczy obecnych na serwerze. Lepiej będzie to rozwiązać zwykłym periodicalem. Może Pan pomyśleć o tym w ten sposób, że lepiej zatrudnić jednego pracownika obsługującego n graczy w jednej chwili czasu z daną częstotliwością niż zatrudnić n pracowników obsługującego każdego gracza indywidualnie z tą samą częstotliwością, ale chwilami wykonywania kodu przesuniętymi w czasie względem siebie. Oczywiście, w przypadku periodicala będą widoczne wzrosty użycia zasobów serwera (procesor, pamięć ram, itd.), ale pętle while nigdy nie będą lepszym rozwiązaniem. Mogą być co najwyżej tak samo wydajne, bo ich użycie zasobów jest bliskie równomiernego w czasie, chociaż obciążenie jest średnio wyższe niż w przypadku periodicala. Poza tym - myślę, że to istotna i dość oczywista zaleta - łatwiej jest zarządzać jedną pętlą niż n pętlami. Jeśli chodzi o drugie, w użytku jest określenie "lista zmiennych", ale myślę, że każdy zrozumie co Pan ma na myśli poprzez zmienną grupową. To czy jest ona używana w skrypcie, niewiele mi mówi. Ważne jest to jak jest używana. To samo tyczy się zmiennych globalnych przypisanych do graczy. Jeżeli one nie są używane nagminnie i w ogromnych ilościach, nie powinno być problemu. Pozdrawiam.
-
Zaliczanie śmierci moba do zmiennej po zginięciu od ognia, spadnięciu z wysokości itp.
Kormic odpowiedział(a) na nnisu pytanie w Pytania i problemy
Najprościej będzie to rozwiązać za pomocą wyrażenia 'last attacker of %entity%'. Należy mieć na uwadze to, że te wyrażenie zwróci nazwę gracza, nie jego UUID. Dodam, że powinien Pan sprawdzać na początku listeneru zdarzenia czy ostatnio atakujący byt jest graczem. Dzięki temu unikamy zapisu zmiennych dla bytów innych niż gracze (wszystkie byty (nawet przedmioty) posiadają UUID, chociaż głównie należy martwić się tutaj żywymi bytami), na przykład żelazne golemy czy szkielety. One też jak najbardziej są w stanie zabić zombie. on death of a zombie: last attacker of victim is a player # Dalszy kod... Oczywiście może (i myślę, że byłoby wskazane) sprawdzanie czasu od ostatniego uderzenia, ale samo użycie powyższego wyrażenia do podstawowych zastosowań jest wystarczające. Gdyby jednak Pan potrzebował coś takiego, mogę zaproponować jak można taki kod napisać. Pozdrawiam. -
Najbardziej podejrzliwe są skrypt dodający automatyczną wymiane na bloki i skrypt dodający system sprawdzania. Jeżeli są one w większości oparte na listenerach zdarzeń (a więc są asynchroniczne, ale tylko do pewnego stopnia, bo są zależne od zegara gry) i nie występują w nich duże pętle czy też długie kody wykonywane w krótkich odstępach czasu (periodicale) oraz wielkie operacje działające na wielu zmiennych globalnych w jednym momencie, wszystko powinno być w porządku. Skrypty pozwalające na banowanie i dodające komendy takie jak /msg, /helpop i /gamma nie budzą moich podejrzeń. Zdaje się, że widziałem skrypt dodający ostatnią z nich, gdyż Pan ją pokazywał. Niczego strasznego tam nie widziałem, więc mogę stwierdzić, że nie będzie on generował dużego obciążenia na serwerze. O pierwszych dwóch komendach nie wspomnę, gdyż ich implementacja jest trywialna - nie ma potrzeby tworzenia tam jakichkolwiek zmiennych globalnych i pętli. Pozdrawiam.
-
Dobrze. Widzę, że trzeba wyjaśnić kilka spraw. Lakonicznie odpowiadając na Pana pytanie, Skript sam w sobie nie jest obciążający dla serwera. To źle i niewydajnie napisane skrypty są powodem obciążenia serwera. A teraz pora na dłuższą odpowiedź. 1. Wiele osób piszących w Skript w nonszalancki sposób: wykorzystuje zapis zmiennych globalnych, tworzy ogromne pętle działające na wielu danych, wykonuje kosztowne w zasobach serwera operacje w sposób synchroniczny, podczas gdy często istnieje możliwość wykorzystania takich dodatków jak skript-reflect (czy też SkQuery) do asynchronicznego wykonania kodu. System zmiennych globalnych w Skript jest bardzo niewydajnie napisany, co zresztą wielokrotnie przyznawali twórcy pluginu. Niewydajność wynika z tego, że Skript każdą zmienną (globalną) zapisuje do pamięci RAM (rzecz normalna), ale również na dysku. Innymi słowy, za każdym razem gdy skrypt wykonuje efekt 'set {zmienna::globalna} to <coś>', zmiana ta jest zapisywana na dysku. W przypadku zapisu setek (a czasem tysięcy) zmiennych w jednym momencie, taka operacja staje się niezwykle kosztowna. Trzeba również pamiętać o tym, że Skript "lubi" często przeorganizowywać plik ze zmiennymi globalnymi (variables.csv), co jest kolejnym powodem niskiej wydajności tego systemu. W ramach ciekawostki powiem, że na pewno do niedawna (a może i do teraz, kto wie) poniższy kod był w stanie zatrzymać pracę serwera (wywalić go). command /test: trigger: loop 10000 times: set {testVariable::%loop-number%} to loop-number W przypadku używania zmiennych lokalnych takiego ryzyka nie ma, gdyż są one zapisywane jedynie w pamięci RAM. Dodam, że miłą alternatywą dla zmiennych globalnych może się okazać dodatek skript-yaml. Ogromną przewagą tego pluginu jest fakt, iż to skrypter decyduje kiedy dane mają być zapisane na dysku, nie Skript (czyli właściwie każdorazowo gdy zapisujemy zmienną globalną). Do momentu zapisu na dysku dane są przechowywane w pamięci RAM, a więc pod tym kątem są tak samo wydajne jak zmienne lokalne. Wniosek? Generalnie kierujemy się zasadą: zmiennych globalnych należy używać tylko wtedy gdy nie jesteśmy w stanie rozwiązać danego problemu przy pomocy zmiennych lokalnych. 2. Część (skripterów?) przecenia możliwości Skripta i myśli, że jest on w stanie w 100% zastąpić pluginy. Wtedy zaczyna się tworzenie w nim wielkich projektów - od anticheatów, poprzez całe tryby, kończąc na skryptach obsługujących dosłownie wszystko. Skript został stworzony w celu dodawania mało skomplikowanych mechanizmów i rzeczy na serwer gdy tworzenie osobnego pluginu jest zwyczajnie nieopłacalne. Plugin ten nie jest i nigdy nie będzie dobry do tworzenia ogromnych projektów. Oczywiście, istnieją wielkie dzieła napisane wydajnie w Skript, jednakże jest to nie więcej niż promil podjętych prób tworzenia ich. Dlatego też odradzam takiego postępowania dopóki nie jest się absolutnie pewnym tego co się robi. 3. Na koniec jeszcze jedno. Zła reputacja Skripta bierze się w dużej mierze z ignorancji rzeszy jego użytkowników, którzy myślą, że to akurat ich skrypty są dobre. Nie, nie są. Wystarczy spojrzeć na to, że połowa (jak nie więcej) skrypterów nie potrafi posługiwać się dokumentacją, więc nie ma mowy o pisaniu dobrego (to znaczy, wydajnego i schludnego) kodu. Myślę, że powiedziałem o wszystkich ważniejszych rzeczach. Gdyby jeszcze zrodziły się jakieś pytania, śmiało je można zadawać. Z miłą chęcią odpowiem. Pozdrawiam.
