Skocz do zawartości

Rekomendowane odpowiedzi

SkCylinder

Witam Państwa, dzisiaj mam przyjemność zaprezentować mój pierwszy opublikowany w tej sekcji skrypt, a mianowicie skrypt na tworzenie okręgów, kół i walców.

EDIT:

Z pewnością niektórzy z Was mogą zauważyć pewne zmiany w tym artykule. Są one związane z aktualizacją owego skryptu do wersji 2.0, w której ograniczenia dla wersji 1.0 są już nieaktualne.

Zanim zacznę - najważniejsza informacja. Każdy kto stwierdza a priori, że ten skrypt nie może się równać z pluginem WorldEdit, ma rację.
Nie został on stworzony z myślą jakiejkolwiek konkurencji, gdyż wydajnościowo jest zdecydowanie słabszy.
Nie neguję również możliwej wadliwości zastosowanych w nim rozwiązań. Jest to dzieło o podłożu czysto hobbystycznym, mające na celu chociażby pokazanie podstawowych zastosowań matematyki.

 

Cechy:

Możliwość tworzenia walców (cylindrów):

- pełnych i pustych,

- o określonym promieniu,

- o określonej wysokości.

 

Dodatkowo:

Skrypt zawiera dwie funkcje służące do tworzenia okręgów i kół o zadanym promieniu.
Więcej informacji w dalszej części artykułu.

 

Wymagania:

- Skript min. 2.2

 

Definicje funkcji w skrypcie:

1. skCylinder_drawCircle([...]) - funkcja tworząca okrąg.

skCylinder_drawCircle(centerLoc: location, radius: number)

Parametry funkcji:
	centerLoc - lokalizacja wyznaczająca środek okręgu (typ: location)
	radius - promień okręgu (typ: number)

Typ zwracanej wartości: 
	blocks (lista bloków potrzebna do utworzenia okręgu)

2. skCylinder_drawDisk([...]) - funkcja tworząca koło.

skCylinder_drawDisk(centerLoc: location, radius: number)

Parametry funkcji:
	centerLoc - lokalizacja wyznaczająca środek koła (typ: location)
	radius - promień koła (typ: number)
    
Typ zwracanej wartości:
	blocks (lista bloków potrzebna do utworzenia koła)

3. skCylinder_drawCylinder([...]) - funkcja tworząca walec.

skCylinder_drawCylinder(startLoc: location, radius: number, height: integer, filled: boolean)

Parametry funkcji:
	startLoc - lokalizacja wyznaczająca środek górnej warstwy walca (typ: location)
	radius - promień walca (typ: number)
	height - wysokość walca (typ: number)
	filled - wartość logiczna (prawda/fałsz) określająca czy chcemy wypełniony walec (typ: boolean)
    
Typ zwracanej wartości:
	blocks (lista bloków potrzebna do utworzenia walca)

Uznałem, że dodawanie opisu funkcji skCylinder_squaredDistance([...]) jest zbędne, gdyż jest ona używana jedynie wewnątrz funkcji tworzącej koło.
Jej istnienie jest uzasadnione faktem, iż przy tysiącach operacji na blokach dobrym rozwiązaniem jest uniknięcie obliczania pierwiastka kwadratowego.

 

Zalecenia:

Ważna informacja - udostępnione niżej przykładowe kody zawierają instrukcje dostępne w dodatku SkQuery (wersja min. 3.6.2-Lime) w celu zapewnienia możliwie wysokiej wydajności.
Poniżej opiszę ich działanie.

 

1. $ thread - instrukcja pozwalająca na wykonanie następującej po niej linijki na innym wątku, co pozwala na uniknięcie generowania obciążenia na głównym wątku serwera.

2. @noupdate:: - instrukcja pozwalająca na ustawienie bloków bez aktualizowania stanu bloków dookoła (np. piasek zawieszony w powietrzu obok nie spadnie po utworzeniu danej struktury).
 

Oczywiście można skryptu używać bez tego dodatku po usunięciu wyżej opisanych efektów.
Proszę mieć jednak na względzie, że skrypt będzie obciążał serwer przy większych strukturach.

 

Przykładowe zastosowania:

Ze względu na to, że tworzenie wyżej wymienionych struktur odbywa się poprzez funkcję, to wystarczy ją wywołać podając przy tym odpowiednie argumenty,
a następnie zwróconą listę bloków użyć do utworzenia danej struktury.

 

Przykład z walcem wypełnionym, bądź nie (w zależności od wartości argumentu nr 3):

command /cylinder <number> <integer> [<boolean=false>] [<item = yellow wool>]:
	executable by: players
	trigger:
		$ thread
		set {_blocks::*} to skCylinder_drawCylinder(location of block at player, arg-1, arg-2, arg-3)
		set blocks in {_blocks::*} to arg-4 with no update
        
# Komenda bez użycia składni dodatku SkQuery (niezalecane):
command /cylinder <number> <integer> [<boolean=false>] [<item = yellow wool>]:
	executable by: players
	trigger:
		set {_blocks::*} to skCylinder_drawCylinder(location of block at player, arg-1, arg-2, arg-3)
		set blocks in {_blocks::*} to arg-4

 

Przykład z okręgiem i kołem:

command /circle <number> [<boolean=false>] [<item = yellow wool>]:
	executable by: players
	trigger:
		if arg-2 is true:
			$ thread
			set {_blocks::*} to skCylinder_drawDisk(location of block at player, arg-1)
		else:
			$ thread
			set {_blocks::*} to skCylinder_drawCircle(location of block at player, arg-1)
		set blocks in {_blocks::*} to arg-3 with no update
        
# Komenda bez użycia składni dodatku SkQuery (niezalecane):
command /circle <number> [<boolean=false>] [<item = yellow wool>]:
	executable by: players
	trigger:
		if arg-2 is true:
			set {_blocks::*} to skCylinder_drawDisk(location of block at player, arg-1)
		else:
			set {_blocks::*} to skCylinder_drawCircle(location of block at player, arg-1)
		set blocks in {_blocks::*} to arg-3

 

Końcowe informacje:

1. Co prawda funkcje akceptują promień jako liczbę niecałkowitą (ściślej mówiąc, nie należącą do zbioru liczb naturalnych), jednakże najlepszy efekt uzyskuje się dla wartości naturalnych.

2. Bardziej dociekliwi mogą zauważyć, że wprowadzona na sztywno w skrypcie wartość liczby pi jest niedokładna (pomijając fakt, iż jest liczbą niewymierną).
Proszę się jednak nie martwić tym, gdyż wedle moich szacowań metodą "pi razy drzwi", błędy numeryczne powinny być fizycznie widoczne dopiero przy tworzeniu okręgu o promieniu rzędu tysięcy kratek.
Zakładam, że nikt nie będzie używał SkCylinder do tego typu zastosowań. Jeśli jednak ktoś będzie miał taką potrzebę, mogą Państwo śmiało dopisać więcej cyfr znaczących.

 

Pobieranie:

https://code.skript.pl/OSlCMrpe - v. 1.0

https://code.skript.pl/jXtexOTY - v. 2.0

 

Rozwiązywanie problemów i składanie propozycji:

W razie jakichś błędów czy też sugestii, jak ulepszyć skrypt, prosiłbym bardzo, aby dać mi znać o nich w komentarzach do tego artykułu.
Postaram się możliwie szybko na nie odpowiedzieć.

 

Dziękuję bardzo za przeczytanie artykułu, życzę miłych wrażeń z użytkowania skryptu.
Czekam na wszelki odzew, czy to pozytywny, czy też krytyczny.

Odnośnik do komentarza
https://skript.pl/temat/41378-skcylinder-skrypt-na-tworzenie-okr%C4%99g%C3%B3w-k%C3%B3%C5%82-i-walc%C3%B3w/
Udostępnij na innych stronach

No dobra, skoro już temat na pw pociągnąłeś... 
 

  • zaokrąglanie współrzędnych jest tutaj naprawdę zbędne (jeszcze bym zrozumiał gdyby było wyrównane do środka bloku w którym gracz się znajduje) - przez zaokrąglanie do rogu bloku struktury mogą wyjść niesymetryczne
  • co do generowania koła (pomijając sposób który ci wysłałem na pw)
    najlepiej byłoby to zrobić w taki sposób:
     
    • mamy współrzędne środka, tworzymy sobie od niej dwie współrzędne przeciwległych boków kwadratu opisanego na kole o danym promieniu (czyli dla jednego dodajemy promień do X i Z środka, a dla drugiego odejmujemy)
    • zapętlamy wszystkie bloki wewnątrz tego kwadratu
    • sprawdzamy czy odległość pomiędzy środkiem, a blokiem z pętli jest mniejsza lub równa promieniowi
      jeżeli tak, dodajemy współrzędne bloku do listy ORAZ blok do drugiej listy
    • robimy pętlę powtarzającą się wysokość-razy, a w niej kolejną pętlę z listą współrzędnych bloków
      dodajemy 1 do każdej współrzędnej Y z pętli i dodajemy blok na tych nowych współrzędnych do listy bloków
    • po zakończeniu pętli, lista bloków będzie miała wszystkie bloki wypełnionego walca, ustawiamy je za pomocą efektu
      @noupdate::set (lista bloków) to (rodzaj bloku)
    • wszystko powyższe robimy w funkcji, którą odpalamy w osobnym wątku - linijkę przed jej wywołaniem wpisujemy 
      $ thread
      drawCylinder(coś tam)
    • co do pustych w środku walców - wracamy do punkty trzeciego:
      sprawdzamy czy odległość pomiędzy środkiem, a blokiem z pętli ZAWIERA SIĘ POMIĘDZY PROMIENIEM A PROMIENIEM POMNIEJSZONYM O 1
       
  • pamiętaj żeby możliwie jak najbardziej ograniczać tworzenie zmiennych przy tak dużych pętlach

 

 

2 godziny temu, Kormic napisał:

- skrypt NIE powinien być używany do tworzenia ogromnych struktur
- Zalecany maksymalny rozmiar pełnego cylindra to promień 20 kratek i wysokość 20 kratek.
- Zalecany maksymalny rozmiar pustego cylindra to promień 10 kratek i wysokość 10 kratek.

zrób tak jak powyżej, a będziesz mógł usunąć te limity z posta

 

Edytowane przez PanMaruda

Dzięki wielkie za podpowiedzi, co do pierwszej uwagi, współrzędne nie są tylko zaokrąglane do rogu bloku, później zwiększam każdą z współrzędnych o 0.5 kratki. Zdałem sobie w międzyczasie, że nawet nie muszę tego zaokrąglać, bo mogę podać blok w miejscu gracza. Ale co do drugiej uwagi postaram się to zrobić, przetestuję i zobaczę. Co do $ thread, nigdy nie miałem okazji używać tego w Skript'cie, wiem tylko, że to działa chyba jedynie na następną linijkę. Czyli rozumiem, że to ma głównie zastosowanie w funkcjach, tak?

Edytowane przez Kormic
9 minut temu, Kormic napisał:

Dzięki wielkie za podpowiedzi, co do pierwszej uwagi, współrzędne nie są tylko zaokrąglane do rogu bloku, później zwiększam każdą z współrzędnych o 0.5 kratki.

faktycznie, nie zauważyłem.

 

$ thread

tak, działa tylko na kolejną linijkę
i tak, ma to głównie zastosowanie w funkcjach

ogólnie chodzi o to że gdy wykonamy taką bardziej wymagającą funkcję asynchronicznie to nie wpłynie ona aż tak mocno na serwer (tj. tps nie spadnie aż tak mocno, nie będzie laga, nie wyrzuci graczy z serwera bo główny wątek serwera nie będzie obciążony).
Możesz sobie to sprawdzić na serwerze ze swoim skryptem - wywołaj tworzenie jakiegoś większego walca normalnie oraz asynchronicznie - w pierwszym przypadku lag będzie widoczny (nie wykonasz żadnej czynności póki funkcja nie zakończy pracy) - w drugim bez problemu zrobisz wszystko.

Okej, dzięki, jeszcze jedno. Dlaczego mam użyć '@noupdate' przy setowaniu bloków? Z tego co wiem to to powoduje, że bloki wokół setowanego bloku się nie update'ują.

6 minut temu, Kormic napisał:

bloki wokół setowanego bloku się nie update'ują.

właśnie sobie wytłumaczyłeś

ta funkcja nie jest od ustawiania jednego czy dwóch bloków, ona musi być gotowa na ilości liczone w tysiącach, a nawet dziesiątkach tysięcy
ograniczamy więc obciążanie procesora

a tak poza tym to ładnie ten efekt wygląda + jest w jednej linijce i załatwia wszystkie bloki za jednym zamachem

Teraz, PanMaruda napisał:

właśnie sobie wytłumaczyłeś

ta funkcja nie jest od ustawiania jednego czy dwóch bloków, ona musi być gotowa na ilości liczone w tysiącach, a nawet dziesiątkach tysięcy
ograniczamy więc obciążanie procesora

a tak poza tym to ładnie ten efekt wygląda + jest w jednej linijce i załatwia wszystkie bloki za jednym zamachem

Faktycznie, zdałem sobie sprawę z tego, że chociażby nie musi sprawdzać czy szyba jest obok i czy aby przypadkiem nie musi się połączyć z blokiem. Dobra, jeszcze raz dzięki, postaram się w takim razie wdrożyć te usprawnienia do skryptu.

Aktualizacja v. 2.0

Nowości:

- gruntowna przebudowa artykułu opisującego skrypt,

- gruntowna przebudowa i optymalizacja kodu (m.in. zastosowanie funkcji trygonometrycznych do części rozwiązań).

 

Z tego miejsca chciałbym serdecznie podziękować mojemu przyjacielowi (@PanMaruda) za wszystkie udzielone mi wcześniej porady. Nie sądziłem, że powrócę do tej abominacji po tylu latach, a jednak.
 

Zapraszam Państwa do zapoznania się z wprowadzonymi zmianami i przetestowania skryptu pod kątem wszelkich błędów oraz sugestii jego udoskonalenia. Pozdrawiam.

  • Kormic zmienił(a) tytuł na SkCylinder - skrypt na tworzenie okręgów, kół i walców

Szczerze powiedziawszy przydał by się jakiś tutorial jak używać tej funkcji ponieważ sam próbowałem użyć Pana skryptu ale mi się nie udało (a przy czytaniu kodu troszkę mi nie wyszło). Byłbym wdzięczny jak by Pan wytłumaczył jak używać przykładowych komend a ja się jeszcze troszkę pobawię z tym skryptem może mi coś wyjdzie. Pozdrawiam :)

17 minut temu, Hiri12 napisał:

Szczerze powiedziawszy przydał by się jakiś tutorial jak używać tej funkcji ponieważ sam próbowałem użyć Pana skryptu ale mi się nie udało (a przy czytaniu kodu troszkę mi nie wyszło). Byłbym wdzięczny jak by Pan wytłumaczył jak używać przykładowych komend a ja się jeszcze troszkę pobawię z tym skryptem może mi coś wyjdzie. Pozdrawiam :)

Gdy pisałem artykuł, zamieściłem w nim definicje każdej funkcji wraz z opisem każdego z parametrów. Dodałem również przykłady użycia skryptu.
Jeśli Pan ich nie przeczytał, proszę się z nimi zapoznać.

Jeżeli jednak Pan mnie prosi o pomoc po przeczytaniu artykułu, śpieszę z tłumaczeniem. Więc tak.

  1. Każda z tych funkcja zwraca listę bloków, którą warto sobie zapisać do lokalnej listy zmiennych.
    Podkreślam, jest to lista bloków, nie lokalizacji.
  2. Mając zapisaną listę z owymi blokami, używamy efektu 'set %blocks% to %item type%'.

Z początku może się wydawać to skomplikowane, ale zapewniam o jednym - skrypt został napisany w taki sposób, aby jego użytkowanie było możliwie proste.

Jeśli Pan ma jeszcze jakieś pytania/wątpliwości, proszę dać znać. Ewentualny kod jest mile widziany.

Pozdrawiam.

28 minut temu, Kormic napisał:

Gdy pisałem artykuł, zamieściłem w nim definicje każdej funkcji wraz z opisem każdego z parametrów. Dodałem również przykłady użycia skryptu.
Jeśli Pan ich nie przeczytał, proszę się z nimi zapoznać.

Jeżeli jednak Pan mnie prosi o pomoc po przeczytaniu artykułu, śpieszę z tłumaczeniem. Więc tak.

  1. Każda z tych funkcja zwraca listę bloków, którą warto sobie zapisać do lokalnej listy zmiennych.
    Podkreślam, jest to lista bloków, nie lokalizacji.
  2. Mając zapisaną listę z owymi blokami, używamy efektu 'set %blocks% to %item type%'.

Z początku może się wydawać to skomplikowane, ale zapewniam o jednym - skrypt został napisany w taki sposób, aby jego użytkowanie było możliwie proste.

Jeśli Pan ma jeszcze jakieś pytania/wątpliwości, proszę dać znać. Ewentualny kod jest mile widziany.

Pozdrawiam.

Dzięki za wytłumaczenie. Trochę poeksperymentowałem i mi się udało :D sam w sobie skrypt napisany na ogromnym poziomie (pod względem matematyki) (nic nie rozumiem) więc wszystkim którzy będą go kiedyś potrzebować polecam :)

25 minut temu, Hiri12 napisał:

Dzięki za wytłumaczenie. Trochę poeksperymentowałem i mi się udało :D sam w sobie skrypt napisany na ogromnym poziomie (pod względem matematyki) (nic nie rozumiem) więc wszystkim którzy będą go kiedyś potrzebować polecam :)

Nie ma problemu. Cieszę się, że Pan zrozumiał.

Co do matematyki, oczywiście nie pamięta wół jak cielęciem był, ale w mojej ocenie nie jest jej tutaj zbyt wiele poza wykorzystaniem trygonometrii do tworzenia okręgu.

Funkcje sinus i cosinus najlepiej jest graficznie zrozumieć jako współrzędne x i y przy poruszaniu się po okręgu o promieniu 1.
Współrzędna x-owa (potocznie: lewo, prawo) to cosinus, natomiast współrzędna y-owa (potocznie: góra, dół) to sinus.
Jeśli kąt jest równy 0, zaczynamy po prawej stronie. Uzasadnieniem tego jest fakt, iż cos(0) = 1, a sin(0) = 0. Tak więc, tłumacząc to na współrzędne, otrzymujemy punkt (X,Y) = (1,0).
Zwiększając kąt będący argumentem obu funkcji, poruszamy się po wcześniej wspomnianym okręgu przeciwnie do ruchu wskazówek zegara.

W celu dalszego zrozumienia polecam Panu wyszukanie sobie wykresów funkcji sinus i cosinus. Przydatne również mogą okazać się materiały do nauki obrazujące wyżej wspomniane poruszanie się po okręgu.

Oczywiście zastosowałem w swoim wywodzie kilka skrótów myślowych i pominąłem nieskończenie wiele innych przypadków, jednakże najprościej zacząć od jakiegoś przypadku i próbować zrozumieć całą stojącą za tym teorię drogą indukcji (od szczegółu do ogółu).

Na koniec dodam, że nietrudno wywnioskować pewną rzecz. Jeśli chcemy poruszać się po okręgu o promieniu r (gdzie r to dowolna liczba rzeczywista), wystarczy przemnożyć obie współrzędne przez ten promień.

4 godziny temu, Fendi napisał:

https://imgur.com/a/M8gKm28

Do opisu skryptu wkradł się jakiś błąd graficzny przy tekście

Nie udzielam wsparcia użytkownikom wykorzystującym biały motyw forum.

A tak na poważnie to dziękuję za zwrócenie na to uwagi, poprawię to w wolnej chwili.

EDIT:

Poprawione.

Edytowane przez Kormic

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Nieaktywny
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...