-
Ilość zawartości
536 -
Rejestracja
-
Ostatnia wizyta
-
Wygrane w rankingu
13
Aktywność reputacji
-
TheMolkaPL otrzymał(a) reputację od Pikachuu w Jak zablokować komendy typu /essentials:baltop lub /essentials:eamsg
Wystarczy usunąć aliasy do tych komend z plugin.yml Essentials (otwierasz JARa WinRARem)...
-
TheMolkaPL otrzymał(a) reputację od Kormic w Regeneracja światów (idealne pod mini-gry)
Właśnie odpisałem w temacie SkyWars - Obszar bogaty post na temat jak zrobić regenerację światów. Myślę, że może się to przydać wielu osobom. Omówię tutaj dwa znane rozwiązania regeneracji, oraz podam nowy - najlepszy. Będę podawać referencję do kodu mojego Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, ponieważ tam właśnie taki system "regeneracji" istnieje.
Zapis zmiany stanu bloków - BŁĄD!
Przy słowie "regeneracja" rozumiemy przede wszystkim powrót stanu bloków do takiego, jakie były w punkcje pierwotnym. Pierwsze rozwiązanie takiego problemu przychodzi nam rejestracja zmiany stanu wszystkich bloków. Stawiamy dirt? Informujemy, że na koordynatach X, Y oraz Z nowy blok to dirt. Na pierwszy rzut oka może się to wydawać działające, ale to nie prawda. Nigdy nie ma pewności, że wszystkie bloki zostaną zregenerowane, dodatkowo taki zapis brudzi tylko naszą pamięć RAM (jeżeli mam to robić in-memory). Musielibyśmy nasłuchiwać każdą jedną możliwą zmianę bloku w serwerze oraz ją rejestrować. Drugi problem z tego się rodzi - kiedy i jak to zregenerować? Moc obliczeniowa do wykonania tak dużego zadania jak podmiana dużej ilości bloków zużyje nam dużo CPU. Kolokwialnie rzecz ujmując regeneracja można wpłynąć znaczenia na działanie serwera, więc najlepiej byłoby to zrobić podczas gdy jest on wyłączony, lub nie ma na niej żadnych graczy.
Tworzenie rzutu stanu bloków - BŁĄD!
No dobrze, skoro nie działa rejestracja bloków, to może przy starcie gry zapiszmy stan wszystkich bloków świata, a potem przywróćmy je do tej wartości? Pobieranie oraz zapisanie stanu bloków będzie bardzo podobne do ich podmiany - kosztuje bardzo mocnym zużyciem zasobów serwera, więc należałoby zrobić go poza jego normalnym działaniem. Ostatecznie takie rozwiązanie odpada, ponieważ jest to także w dużej mierze powielenie rozwiązania pierwszego.
Ładowanie - wyładowywanie światów - ROZWIĄZANIE!
Silnik Bukkit oferuje nam możliwość ładowania i wyładowywania światów w czasie jego trwania działania. Wyładowanie świata następuje natychmiastowo, polega jedynie na usunięciu go z pamięci RAM. Ładowanie natomiast może znaczenia wpłynąć na działanie logiki serwera. Generalnie rzecz biorąc ładowanie i wyładowywanie światów jest najlepszym rozwiązaniem, ponieważ i tak będzie kosztować zużyciem mniejszej ilości zasobów, niż rzeczywista regeneracja.
Wprowadzenie
No dobrze - zacznijmy. Na początku prosiłbym abyśmy ustanowili w tym poście kilka słów stałych, aby nie było problemów ze zrozumieniem.
Świat (world) - tym słowym mam na myśli Minecraftowy świat ładowany do serwera. W plikach świata musi znajdować się plik level.dat; tam zapisane są informacje o generatorze, ziarnie (seed), miejscu spawna, obecny spawnpoint oraz masa innych rzeczy. Mapa - tym słowem mam na myśli zbiór bloków które tworzą jakąś strukturę. Znajdują się one w chunkach, czyli dużych zbiornikach 16x16 bloków (na koordynatach X oraz Z) na pełnej wysokości świata - koordynat Y.
Ładowanie świata
Świat do serwera ładujemy metodą Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! z interfejsu Server. W parametrze podajemy nowy obiekt klasy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - jest to Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, czyli budowniczy innego obiektu, gdzie jego stworzenie wykonujemy po woli wykonując po kolei jej metody. Załadowanie nowego świata można także Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. WorldCreator jest świetnym narzędziem do wypełnienia znacznej większości ustawień świata. Zaczynami od ich ustawienia.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy typ świata - może to być NORMAL, THE_END lub NETHER. Dzięki temu zmienimy dużo w jego działaniu. Na przykład niebo (w netherze jest czerwone, w the endzie jest czarne z gwiazdami), oraz fizykę (w netherze nie można wylewać wody, w the endzie spawnują się tylko ender-dragony i endermany). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - w parametrze podajemy wartość true/false, gdzie true ustawi nam, że na tym świecie będą się generować struktury - wioski, opuszczone kopalnie, piramidy, studnie, ... - false je wyłączy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy generator z jakiego nasz nowy świat będzie korzystać. Proszę spojrzeć na metody poniżej - mamy tutaj wiele możliwości wyboru. Możemy tutaj stworzyć swój własny generator podając nasz Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, lub pobrać domyślny generator pluginu podając jego nazwę w Stringu. Proszę poczytać więcej o generatorach w poście niżej - to bardzo ważne! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy dodatkowe ustawienia generatora - nie znam do końca jego działania - nigdy z tego nie korzystałem. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy nazwę naszego świata - UWAGA: nazwa świata musi znajdować się w przedziale A-Z, a-z, 0-9 oraz _ i - żadne inne znaki nie są wspomagane! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy seed - ziarenko z którego będzie korzystać nasz generator. Działa tylko przy korzystaniu z generatora vanilla! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy typ naszego świata. Podajemy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! gdzie możemy podać świat płaski, duże biomy, oraz masę innych typów. Pozwolę sobie jeszcze pokazać jak to działa w pluginie Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Następnie wykonujemy metodę createWorld(), a rezultat zapisujemy w obiekcie World. W tym momencie nasz świat zostanie załadowany do pamięci serwera. Może to zająć moment, zależnie od wielkości świata.
Teraz należy ustawić ostatnie ustawienia gdzie dokładniej ustawimy ten świat pod nasz serwer.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - dzięki temu nasz świat nie zapisze się przy jego wyładowaniu, oraz wyłączymy auto-save, który domyślnie wykonuje się co 5 minut (do ustawienia w bukkit.yml). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - domyślnie w Minecraft chunki na spawnie oraz wokół niego nie są wyładowywanie z pamięci, oraz zawsze znajdują się w pamięci podręcznej serwera. Jest to zbędny zabieg, ponieważ spawnpoint świata nie koniecznie jest spawnem mapy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - może być przydatne na mapie typu SkyWars. Dzięki temu wyłączymy możliwość spawnowania się potworów i/lub zwierząt na całym świecie. Jak to działa w Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
I gotowe! Teraz mamy załadowany świat gotowy do gry!
Wyładowywanie świata
Wyładowywanie świata jest bardzo proste. Wystarczy użyć metody Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. Możemy podać nazwę świata, lub obiekt World. Drugi parametr ustawiamy na false, dzięki czemu nasz świat nie zostanie zapisany.
Optymalizacja światów
Jak wiemy generowanie świata zużywa drastycznie dużo zasobów serwera. Aby temu zaradzić należy zrobić prosty generator który wygeneruje nam tak zwany "void", czyli pusty świat. Tutaj istnieje taki generator, który generuje nam całkowicie pusty świat -> Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Należałoby także zoptymalizować pliki świata. Klient, serwer, mody oraz różne programy (np MCEdit) generują nam dodatkowe, zbędne pliki które możemy spokojnie usunąć.
level.dat - pozostaw - tutaj zapisane są wszystkie podstawowe informacje na temat świata. region (folder) - pozostaw - tutaj znajdują się pliki, w których zapisane są chunki świata. data (folder) - pozostaw - tutaj zapisane są wszystkie wioski na mapie, oraz mapy (te które wskazują nam jakiś punkt, lub po prostu mamy w niej grafikę). Wszystko inne należy usunąć!
Usuwanie zbędnych chunków
Przy budowie mapy Minecraft generuje nam wszystkie chunki dookoła nas. Wiele z nich jest zbędnych ponieważ nie znajduje się na nich żaden element naszej mapy. Jest to kolejny krok naszej optymalizacji, która będzie miała wpływ na przyspieszenie ładowania świata. Ten krok należy wykonać przed powyższym "Optymalizacja światów".
Przy ładowaniu świata serwer będzie nam czytał chunki które znajdują się na mapie. Odczytanie ich z pliku zajmie znacznie więcej czasu niż pobranie pustej tablicy w naszym generatorze. Zupełnie inaczej jest w generatorze vanilla - tam pobranie zapisanego świata zajmie znacznie mniej czasu, niż wygenerowanie nowego! Pamiętaj o tym!
Pobieramy sobie programik MCEdit - Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! Otwieramy go Po otwarciu pokaże nam się menu główne programu Klikamy "Load Level" Wybieramy plik level.dat świata w którym chcemy usunąć zbędne chunki Klikamy "otwórz" Nasz świat zostanie załadowany Klikamy na górze programu "Chunk View"; przełączymy się dzięki temu z widoku gracza na widok z lotu ptaka. Na ekranie pojawi nam się siatka (możemy przybliżyć/oddalić świat scrollując myszką) Zaznaczamy myszką te chunki (kratki) na których znajduje się nasza mapa Po lewej stronie pokazuje nam się okienko - klikamy na nim przycisk "Prune" Wyskoczy nam okienko potwierdzające usunięcie wszystkich chunków które nie zostały zaznaczone. Proszę się upewnić czy na pewno zaznaczyliśmy te chunki na których znajduje się mapa. Następnego punktu nie da się cofnąć! Klikamy OK, chunki zostaną usunięte Gotowe, zamykamy program i przechodzimy do punktu "Optymalizacja światów"!
Zakończenie
Tak o to mamy całkowcie zoptymalizowany świat oraz system "regeneracji".
Dobre praktyki
Jest jeszcze jedna rzecz którą chciałbym zaznaczyć. Folder twojego świata w głównym folderze serwera nie zostanie usunięty. Zalecam otworzyć plik bukkit.yml, oraz w sekcji settings, dopisać world-container: '/worlds' - dzięki temu wszystkie nasze światy będą zapisywane w folderze worlds, podobnie jak pluginy w plugins. Jest to dość ukryta funkcja w Bukkicie, ponieważ nie jest domyślnie zapisane w YAMLu.
Przykład:
settings: world-container: '/worlds'
Drugie zagadnienie to 100% pewność, że nasza mapa nie zostanie uszkodzona. zalecam w głównym folderze serwera, obok logs, plugins i worlds zrobić folder maps. Tam będziemy trzymać wszystkie światy na których znajdują się mapy. Podczas ładowania tej mapy będziemy kopiować jej pliki do folderu worlds z poziomu pluginu. Dzięki temu mamy 100% pewność, że naszej mapie (która może być wykorzystywana przez wiele serwerów jednocześnie) na pewno się nic nie stanie!
Mam nadzieję, że pomogłem
-
TheMolkaPL otrzymał(a) reputację od Glicz w Regeneracja światów (idealne pod mini-gry)
Właśnie odpisałem w temacie SkyWars - Obszar bogaty post na temat jak zrobić regenerację światów. Myślę, że może się to przydać wielu osobom. Omówię tutaj dwa znane rozwiązania regeneracji, oraz podam nowy - najlepszy. Będę podawać referencję do kodu mojego Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, ponieważ tam właśnie taki system "regeneracji" istnieje.
Zapis zmiany stanu bloków - BŁĄD!
Przy słowie "regeneracja" rozumiemy przede wszystkim powrót stanu bloków do takiego, jakie były w punkcje pierwotnym. Pierwsze rozwiązanie takiego problemu przychodzi nam rejestracja zmiany stanu wszystkich bloków. Stawiamy dirt? Informujemy, że na koordynatach X, Y oraz Z nowy blok to dirt. Na pierwszy rzut oka może się to wydawać działające, ale to nie prawda. Nigdy nie ma pewności, że wszystkie bloki zostaną zregenerowane, dodatkowo taki zapis brudzi tylko naszą pamięć RAM (jeżeli mam to robić in-memory). Musielibyśmy nasłuchiwać każdą jedną możliwą zmianę bloku w serwerze oraz ją rejestrować. Drugi problem z tego się rodzi - kiedy i jak to zregenerować? Moc obliczeniowa do wykonania tak dużego zadania jak podmiana dużej ilości bloków zużyje nam dużo CPU. Kolokwialnie rzecz ujmując regeneracja można wpłynąć znaczenia na działanie serwera, więc najlepiej byłoby to zrobić podczas gdy jest on wyłączony, lub nie ma na niej żadnych graczy.
Tworzenie rzutu stanu bloków - BŁĄD!
No dobrze, skoro nie działa rejestracja bloków, to może przy starcie gry zapiszmy stan wszystkich bloków świata, a potem przywróćmy je do tej wartości? Pobieranie oraz zapisanie stanu bloków będzie bardzo podobne do ich podmiany - kosztuje bardzo mocnym zużyciem zasobów serwera, więc należałoby zrobić go poza jego normalnym działaniem. Ostatecznie takie rozwiązanie odpada, ponieważ jest to także w dużej mierze powielenie rozwiązania pierwszego.
Ładowanie - wyładowywanie światów - ROZWIĄZANIE!
Silnik Bukkit oferuje nam możliwość ładowania i wyładowywania światów w czasie jego trwania działania. Wyładowanie świata następuje natychmiastowo, polega jedynie na usunięciu go z pamięci RAM. Ładowanie natomiast może znaczenia wpłynąć na działanie logiki serwera. Generalnie rzecz biorąc ładowanie i wyładowywanie światów jest najlepszym rozwiązaniem, ponieważ i tak będzie kosztować zużyciem mniejszej ilości zasobów, niż rzeczywista regeneracja.
Wprowadzenie
No dobrze - zacznijmy. Na początku prosiłbym abyśmy ustanowili w tym poście kilka słów stałych, aby nie było problemów ze zrozumieniem.
Świat (world) - tym słowym mam na myśli Minecraftowy świat ładowany do serwera. W plikach świata musi znajdować się plik level.dat; tam zapisane są informacje o generatorze, ziarnie (seed), miejscu spawna, obecny spawnpoint oraz masa innych rzeczy. Mapa - tym słowem mam na myśli zbiór bloków które tworzą jakąś strukturę. Znajdują się one w chunkach, czyli dużych zbiornikach 16x16 bloków (na koordynatach X oraz Z) na pełnej wysokości świata - koordynat Y.
Ładowanie świata
Świat do serwera ładujemy metodą Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! z interfejsu Server. W parametrze podajemy nowy obiekt klasy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - jest to Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, czyli budowniczy innego obiektu, gdzie jego stworzenie wykonujemy po woli wykonując po kolei jej metody. Załadowanie nowego świata można także Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. WorldCreator jest świetnym narzędziem do wypełnienia znacznej większości ustawień świata. Zaczynami od ich ustawienia.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy typ świata - może to być NORMAL, THE_END lub NETHER. Dzięki temu zmienimy dużo w jego działaniu. Na przykład niebo (w netherze jest czerwone, w the endzie jest czarne z gwiazdami), oraz fizykę (w netherze nie można wylewać wody, w the endzie spawnują się tylko ender-dragony i endermany). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - w parametrze podajemy wartość true/false, gdzie true ustawi nam, że na tym świecie będą się generować struktury - wioski, opuszczone kopalnie, piramidy, studnie, ... - false je wyłączy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy generator z jakiego nasz nowy świat będzie korzystać. Proszę spojrzeć na metody poniżej - mamy tutaj wiele możliwości wyboru. Możemy tutaj stworzyć swój własny generator podając nasz Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, lub pobrać domyślny generator pluginu podając jego nazwę w Stringu. Proszę poczytać więcej o generatorach w poście niżej - to bardzo ważne! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy dodatkowe ustawienia generatora - nie znam do końca jego działania - nigdy z tego nie korzystałem. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy nazwę naszego świata - UWAGA: nazwa świata musi znajdować się w przedziale A-Z, a-z, 0-9 oraz _ i - żadne inne znaki nie są wspomagane! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy seed - ziarenko z którego będzie korzystać nasz generator. Działa tylko przy korzystaniu z generatora vanilla! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy typ naszego świata. Podajemy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! gdzie możemy podać świat płaski, duże biomy, oraz masę innych typów. Pozwolę sobie jeszcze pokazać jak to działa w pluginie Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Następnie wykonujemy metodę createWorld(), a rezultat zapisujemy w obiekcie World. W tym momencie nasz świat zostanie załadowany do pamięci serwera. Może to zająć moment, zależnie od wielkości świata.
Teraz należy ustawić ostatnie ustawienia gdzie dokładniej ustawimy ten świat pod nasz serwer.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - dzięki temu nasz świat nie zapisze się przy jego wyładowaniu, oraz wyłączymy auto-save, który domyślnie wykonuje się co 5 minut (do ustawienia w bukkit.yml). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - domyślnie w Minecraft chunki na spawnie oraz wokół niego nie są wyładowywanie z pamięci, oraz zawsze znajdują się w pamięci podręcznej serwera. Jest to zbędny zabieg, ponieważ spawnpoint świata nie koniecznie jest spawnem mapy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - może być przydatne na mapie typu SkyWars. Dzięki temu wyłączymy możliwość spawnowania się potworów i/lub zwierząt na całym świecie. Jak to działa w Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
I gotowe! Teraz mamy załadowany świat gotowy do gry!
Wyładowywanie świata
Wyładowywanie świata jest bardzo proste. Wystarczy użyć metody Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. Możemy podać nazwę świata, lub obiekt World. Drugi parametr ustawiamy na false, dzięki czemu nasz świat nie zostanie zapisany.
Optymalizacja światów
Jak wiemy generowanie świata zużywa drastycznie dużo zasobów serwera. Aby temu zaradzić należy zrobić prosty generator który wygeneruje nam tak zwany "void", czyli pusty świat. Tutaj istnieje taki generator, który generuje nam całkowicie pusty świat -> Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Należałoby także zoptymalizować pliki świata. Klient, serwer, mody oraz różne programy (np MCEdit) generują nam dodatkowe, zbędne pliki które możemy spokojnie usunąć.
level.dat - pozostaw - tutaj zapisane są wszystkie podstawowe informacje na temat świata. region (folder) - pozostaw - tutaj znajdują się pliki, w których zapisane są chunki świata. data (folder) - pozostaw - tutaj zapisane są wszystkie wioski na mapie, oraz mapy (te które wskazują nam jakiś punkt, lub po prostu mamy w niej grafikę). Wszystko inne należy usunąć!
Usuwanie zbędnych chunków
Przy budowie mapy Minecraft generuje nam wszystkie chunki dookoła nas. Wiele z nich jest zbędnych ponieważ nie znajduje się na nich żaden element naszej mapy. Jest to kolejny krok naszej optymalizacji, która będzie miała wpływ na przyspieszenie ładowania świata. Ten krok należy wykonać przed powyższym "Optymalizacja światów".
Przy ładowaniu świata serwer będzie nam czytał chunki które znajdują się na mapie. Odczytanie ich z pliku zajmie znacznie więcej czasu niż pobranie pustej tablicy w naszym generatorze. Zupełnie inaczej jest w generatorze vanilla - tam pobranie zapisanego świata zajmie znacznie mniej czasu, niż wygenerowanie nowego! Pamiętaj o tym!
Pobieramy sobie programik MCEdit - Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! Otwieramy go Po otwarciu pokaże nam się menu główne programu Klikamy "Load Level" Wybieramy plik level.dat świata w którym chcemy usunąć zbędne chunki Klikamy "otwórz" Nasz świat zostanie załadowany Klikamy na górze programu "Chunk View"; przełączymy się dzięki temu z widoku gracza na widok z lotu ptaka. Na ekranie pojawi nam się siatka (możemy przybliżyć/oddalić świat scrollując myszką) Zaznaczamy myszką te chunki (kratki) na których znajduje się nasza mapa Po lewej stronie pokazuje nam się okienko - klikamy na nim przycisk "Prune" Wyskoczy nam okienko potwierdzające usunięcie wszystkich chunków które nie zostały zaznaczone. Proszę się upewnić czy na pewno zaznaczyliśmy te chunki na których znajduje się mapa. Następnego punktu nie da się cofnąć! Klikamy OK, chunki zostaną usunięte Gotowe, zamykamy program i przechodzimy do punktu "Optymalizacja światów"!
Zakończenie
Tak o to mamy całkowcie zoptymalizowany świat oraz system "regeneracji".
Dobre praktyki
Jest jeszcze jedna rzecz którą chciałbym zaznaczyć. Folder twojego świata w głównym folderze serwera nie zostanie usunięty. Zalecam otworzyć plik bukkit.yml, oraz w sekcji settings, dopisać world-container: '/worlds' - dzięki temu wszystkie nasze światy będą zapisywane w folderze worlds, podobnie jak pluginy w plugins. Jest to dość ukryta funkcja w Bukkicie, ponieważ nie jest domyślnie zapisane w YAMLu.
Przykład:
settings: world-container: '/worlds'
Drugie zagadnienie to 100% pewność, że nasza mapa nie zostanie uszkodzona. zalecam w głównym folderze serwera, obok logs, plugins i worlds zrobić folder maps. Tam będziemy trzymać wszystkie światy na których znajdują się mapy. Podczas ładowania tej mapy będziemy kopiować jej pliki do folderu worlds z poziomu pluginu. Dzięki temu mamy 100% pewność, że naszej mapie (która może być wykorzystywana przez wiele serwerów jednocześnie) na pewno się nic nie stanie!
Mam nadzieję, że pomogłem
-
TheMolkaPL otrzymał(a) reputację od Peridot w Regeneracja światów (idealne pod mini-gry)
Właśnie odpisałem w temacie SkyWars - Obszar bogaty post na temat jak zrobić regenerację światów. Myślę, że może się to przydać wielu osobom. Omówię tutaj dwa znane rozwiązania regeneracji, oraz podam nowy - najlepszy. Będę podawać referencję do kodu mojego Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, ponieważ tam właśnie taki system "regeneracji" istnieje.
Zapis zmiany stanu bloków - BŁĄD!
Przy słowie "regeneracja" rozumiemy przede wszystkim powrót stanu bloków do takiego, jakie były w punkcje pierwotnym. Pierwsze rozwiązanie takiego problemu przychodzi nam rejestracja zmiany stanu wszystkich bloków. Stawiamy dirt? Informujemy, że na koordynatach X, Y oraz Z nowy blok to dirt. Na pierwszy rzut oka może się to wydawać działające, ale to nie prawda. Nigdy nie ma pewności, że wszystkie bloki zostaną zregenerowane, dodatkowo taki zapis brudzi tylko naszą pamięć RAM (jeżeli mam to robić in-memory). Musielibyśmy nasłuchiwać każdą jedną możliwą zmianę bloku w serwerze oraz ją rejestrować. Drugi problem z tego się rodzi - kiedy i jak to zregenerować? Moc obliczeniowa do wykonania tak dużego zadania jak podmiana dużej ilości bloków zużyje nam dużo CPU. Kolokwialnie rzecz ujmując regeneracja można wpłynąć znaczenia na działanie serwera, więc najlepiej byłoby to zrobić podczas gdy jest on wyłączony, lub nie ma na niej żadnych graczy.
Tworzenie rzutu stanu bloków - BŁĄD!
No dobrze, skoro nie działa rejestracja bloków, to może przy starcie gry zapiszmy stan wszystkich bloków świata, a potem przywróćmy je do tej wartości? Pobieranie oraz zapisanie stanu bloków będzie bardzo podobne do ich podmiany - kosztuje bardzo mocnym zużyciem zasobów serwera, więc należałoby zrobić go poza jego normalnym działaniem. Ostatecznie takie rozwiązanie odpada, ponieważ jest to także w dużej mierze powielenie rozwiązania pierwszego.
Ładowanie - wyładowywanie światów - ROZWIĄZANIE!
Silnik Bukkit oferuje nam możliwość ładowania i wyładowywania światów w czasie jego trwania działania. Wyładowanie świata następuje natychmiastowo, polega jedynie na usunięciu go z pamięci RAM. Ładowanie natomiast może znaczenia wpłynąć na działanie logiki serwera. Generalnie rzecz biorąc ładowanie i wyładowywanie światów jest najlepszym rozwiązaniem, ponieważ i tak będzie kosztować zużyciem mniejszej ilości zasobów, niż rzeczywista regeneracja.
Wprowadzenie
No dobrze - zacznijmy. Na początku prosiłbym abyśmy ustanowili w tym poście kilka słów stałych, aby nie było problemów ze zrozumieniem.
Świat (world) - tym słowym mam na myśli Minecraftowy świat ładowany do serwera. W plikach świata musi znajdować się plik level.dat; tam zapisane są informacje o generatorze, ziarnie (seed), miejscu spawna, obecny spawnpoint oraz masa innych rzeczy. Mapa - tym słowem mam na myśli zbiór bloków które tworzą jakąś strukturę. Znajdują się one w chunkach, czyli dużych zbiornikach 16x16 bloków (na koordynatach X oraz Z) na pełnej wysokości świata - koordynat Y.
Ładowanie świata
Świat do serwera ładujemy metodą Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! z interfejsu Server. W parametrze podajemy nowy obiekt klasy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - jest to Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, czyli budowniczy innego obiektu, gdzie jego stworzenie wykonujemy po woli wykonując po kolei jej metody. Załadowanie nowego świata można także Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. WorldCreator jest świetnym narzędziem do wypełnienia znacznej większości ustawień świata. Zaczynami od ich ustawienia.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy typ świata - może to być NORMAL, THE_END lub NETHER. Dzięki temu zmienimy dużo w jego działaniu. Na przykład niebo (w netherze jest czerwone, w the endzie jest czarne z gwiazdami), oraz fizykę (w netherze nie można wylewać wody, w the endzie spawnują się tylko ender-dragony i endermany). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - w parametrze podajemy wartość true/false, gdzie true ustawi nam, że na tym świecie będą się generować struktury - wioski, opuszczone kopalnie, piramidy, studnie, ... - false je wyłączy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy generator z jakiego nasz nowy świat będzie korzystać. Proszę spojrzeć na metody poniżej - mamy tutaj wiele możliwości wyboru. Możemy tutaj stworzyć swój własny generator podając nasz Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, lub pobrać domyślny generator pluginu podając jego nazwę w Stringu. Proszę poczytać więcej o generatorach w poście niżej - to bardzo ważne! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy dodatkowe ustawienia generatora - nie znam do końca jego działania - nigdy z tego nie korzystałem. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy nazwę naszego świata - UWAGA: nazwa świata musi znajdować się w przedziale A-Z, a-z, 0-9 oraz _ i - żadne inne znaki nie są wspomagane! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy seed - ziarenko z którego będzie korzystać nasz generator. Działa tylko przy korzystaniu z generatora vanilla! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy typ naszego świata. Podajemy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! gdzie możemy podać świat płaski, duże biomy, oraz masę innych typów. Pozwolę sobie jeszcze pokazać jak to działa w pluginie Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Następnie wykonujemy metodę createWorld(), a rezultat zapisujemy w obiekcie World. W tym momencie nasz świat zostanie załadowany do pamięci serwera. Może to zająć moment, zależnie od wielkości świata.
Teraz należy ustawić ostatnie ustawienia gdzie dokładniej ustawimy ten świat pod nasz serwer.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - dzięki temu nasz świat nie zapisze się przy jego wyładowaniu, oraz wyłączymy auto-save, który domyślnie wykonuje się co 5 minut (do ustawienia w bukkit.yml). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - domyślnie w Minecraft chunki na spawnie oraz wokół niego nie są wyładowywanie z pamięci, oraz zawsze znajdują się w pamięci podręcznej serwera. Jest to zbędny zabieg, ponieważ spawnpoint świata nie koniecznie jest spawnem mapy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - może być przydatne na mapie typu SkyWars. Dzięki temu wyłączymy możliwość spawnowania się potworów i/lub zwierząt na całym świecie. Jak to działa w Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
I gotowe! Teraz mamy załadowany świat gotowy do gry!
Wyładowywanie świata
Wyładowywanie świata jest bardzo proste. Wystarczy użyć metody Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. Możemy podać nazwę świata, lub obiekt World. Drugi parametr ustawiamy na false, dzięki czemu nasz świat nie zostanie zapisany.
Optymalizacja światów
Jak wiemy generowanie świata zużywa drastycznie dużo zasobów serwera. Aby temu zaradzić należy zrobić prosty generator który wygeneruje nam tak zwany "void", czyli pusty świat. Tutaj istnieje taki generator, który generuje nam całkowicie pusty świat -> Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Należałoby także zoptymalizować pliki świata. Klient, serwer, mody oraz różne programy (np MCEdit) generują nam dodatkowe, zbędne pliki które możemy spokojnie usunąć.
level.dat - pozostaw - tutaj zapisane są wszystkie podstawowe informacje na temat świata. region (folder) - pozostaw - tutaj znajdują się pliki, w których zapisane są chunki świata. data (folder) - pozostaw - tutaj zapisane są wszystkie wioski na mapie, oraz mapy (te które wskazują nam jakiś punkt, lub po prostu mamy w niej grafikę). Wszystko inne należy usunąć!
Usuwanie zbędnych chunków
Przy budowie mapy Minecraft generuje nam wszystkie chunki dookoła nas. Wiele z nich jest zbędnych ponieważ nie znajduje się na nich żaden element naszej mapy. Jest to kolejny krok naszej optymalizacji, która będzie miała wpływ na przyspieszenie ładowania świata. Ten krok należy wykonać przed powyższym "Optymalizacja światów".
Przy ładowaniu świata serwer będzie nam czytał chunki które znajdują się na mapie. Odczytanie ich z pliku zajmie znacznie więcej czasu niż pobranie pustej tablicy w naszym generatorze. Zupełnie inaczej jest w generatorze vanilla - tam pobranie zapisanego świata zajmie znacznie mniej czasu, niż wygenerowanie nowego! Pamiętaj o tym!
Pobieramy sobie programik MCEdit - Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! Otwieramy go Po otwarciu pokaże nam się menu główne programu Klikamy "Load Level" Wybieramy plik level.dat świata w którym chcemy usunąć zbędne chunki Klikamy "otwórz" Nasz świat zostanie załadowany Klikamy na górze programu "Chunk View"; przełączymy się dzięki temu z widoku gracza na widok z lotu ptaka. Na ekranie pojawi nam się siatka (możemy przybliżyć/oddalić świat scrollując myszką) Zaznaczamy myszką te chunki (kratki) na których znajduje się nasza mapa Po lewej stronie pokazuje nam się okienko - klikamy na nim przycisk "Prune" Wyskoczy nam okienko potwierdzające usunięcie wszystkich chunków które nie zostały zaznaczone. Proszę się upewnić czy na pewno zaznaczyliśmy te chunki na których znajduje się mapa. Następnego punktu nie da się cofnąć! Klikamy OK, chunki zostaną usunięte Gotowe, zamykamy program i przechodzimy do punktu "Optymalizacja światów"!
Zakończenie
Tak o to mamy całkowcie zoptymalizowany świat oraz system "regeneracji".
Dobre praktyki
Jest jeszcze jedna rzecz którą chciałbym zaznaczyć. Folder twojego świata w głównym folderze serwera nie zostanie usunięty. Zalecam otworzyć plik bukkit.yml, oraz w sekcji settings, dopisać world-container: '/worlds' - dzięki temu wszystkie nasze światy będą zapisywane w folderze worlds, podobnie jak pluginy w plugins. Jest to dość ukryta funkcja w Bukkicie, ponieważ nie jest domyślnie zapisane w YAMLu.
Przykład:
settings: world-container: '/worlds'
Drugie zagadnienie to 100% pewność, że nasza mapa nie zostanie uszkodzona. zalecam w głównym folderze serwera, obok logs, plugins i worlds zrobić folder maps. Tam będziemy trzymać wszystkie światy na których znajdują się mapy. Podczas ładowania tej mapy będziemy kopiować jej pliki do folderu worlds z poziomu pluginu. Dzięki temu mamy 100% pewność, że naszej mapie (która może być wykorzystywana przez wiele serwerów jednocześnie) na pewno się nic nie stanie!
Mam nadzieję, że pomogłem
-
TheMolkaPL otrzymał(a) reputację od Qotrek w Łączenie graczy z serwerami pod BungeeCord
Witajcie Czerwono Towarzysze! W tym poradniku przedstawię Wam jak łączyć graczy z innym serwerem podpiętym do BungeeCord. Przydatne na przykład do łączenia graczy z serwera lobby na inne serwery (oraz vice-versa). Do dzieła!
Chcesz wykonać instrukcję przeniesienia gracza na inny serwer. Na początku musisz jednak zrozumieć czym jest serwer, na przykład na silniku Spigot i czym jest BungeeCord. Bez tej wiedzy nieudolnie będziesz próbować różnych sztuczek z przenoszeniem na inny serwer.
Na początku spróbuje tą trochę zobrazować. Prawdopodobnie wyobrażasz sobie, że BungeeCord działa na następującej zasadzie. Janusz wchodzi na serwer poprzez połączenie się przez BungeeCorda, następnie na serwerze (który jest serwerem lobby) wybiera inny serwer, więc ten go łączy.
[CIACH]
Jest to błąd bo serwer nie wysyła graczy na inny serwer. Wszystko robi BungeeCord. Serwer lobby jest kolejnym serwerem który działa na takiej samej zasadzie jak inne w tej samej sieci. Działa ona na identycznej zasadzie jak Creative, Free Build czy Survival.
[CIACH]
Aby móc przenieść Towarzysza Sebastian z serwera Lobby na serwer Creative należy do BungeeCord wysłać taką instrukcję. Tylko on przekierowuje połączenia i tylko on może przenosić graczy między serwerami. BungeeCord jest proxy między klientem, czyli Sebastianem, a fizycznym serwerem, czyli Lobby.
Komendy BungeeCord, takie jak /end, /perms, /server, /find czy /alert są zatem komendami na proxy, a nie na serwerze. Co to oznacza? Klient z serwerem (i vice versa) komunikuje się za pomocą pakietów, czyli małych paczuszek z danymi. Może to być informacja o postawieniu klocka na mapie, ruszeniu się gracza, czy jego interakcji w świat. Towarzysz, na przykład Grażyna wpisuje na chacie komendę /server, klient do wysyła do serwera pakiet o wykonaniu komendy. Pakiet dociera do BungeeCorda, ten go otwiera i sprawdza czym on tak na prawdę jest. Widzi, że użyto komendy /server. Sprawdza on czy u siebie ma taką zarejestrowaną komendę. Jeśli nie wysyła ten pakiet dalej na serwer. Jeśli tak do ją wykonuje. To wszystko sprowadza się do tego, że serwer nie może wykonać za gracza komendy, bo musi ona zostać przesłana pakietem. Pakiet musi przejść przez proxy BungeeCorda.
Wykonanie takiej czynności całkowicie więc odpada. BungeeCord natomiast oferuje wysyłanie danych między sobą a serwerem. Jest to tak zwany "Plugin Messaging Channel". Teraz pokażę Ci jak to zrobić Towarzyszu.
1. Najpierw musisz zarejestrować ten kanał w swoim pluginie. Najlepiej wykonać to w Twoim onEnable():
@Override public void onEnable() { this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); } 2. Teraz należy stworzyć sobie klasę BungeeConnector w Twoim projekcie. Będzie ona miała za zadanie łączyć wybranych graczy z wybranym przez ciebie serwerem.
/** * Connect players between servers within the BungeeCord proxy. */ public class BungeeConnector { public static final String PLUGIN_CHANNEL = "BungeeCord"; private final Plugin plugin; public BungeeConnector(Plugin plugin) { this.plugin = plugin; } /** * Connect given <code>player</code> into the given <code>target</code> server. * @param player {@link Player} who should be connected. * @param target The target server identifier specified in the BungeeCord proxy configuration. */ public void connect(Player player, String target) { ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(array); try { output.writeUTF("Connect"); output.writeUTF(target); } catch (IOException ignored) { } player.sendPluginMessage(this.plugin, PLUGIN_CHANNEL, array.toByteArray()); } } 3. W głównej klasie Twojego pluginu możesz sobie zrobić instancję tej klasy. W tym celu na górze zrób sobie zmienną ją przetrzymującą.
private BungeeConnector connector; 4. W onEnable() definiuj zmienną do jej prawidłowej wartości.
@Override public void onEnable() { this.connector = new BungeeConnector(this); this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); // to już było wcześniej } 5. Teraz wystarczy już tylko zrobić sobie do niej getter.
public BungeeConnector getConnector() { return this.connector; }
I gotowe! Oczywiście można by to jeszcze ulepszyć, na przykład w connect(...) dodać anulowalny event. Dzięki temu można by go anulować w pewnych przypadkach. Na przykład gdy na serwerze jest anti-logout, a Ty nie chcesz żeby w czasie PvP mógł się przenosić między serwerami.
Aby połączyć gracza z serwerem wystarczy użyć
this.getConnector().connect(player, "survival"); Dzięki temu gracz połączy się z serwerem Survival. Zgodnie z zaleceniami konfiguracyjnymi serwery powinny zostać nazwane całkowicie małymi literami. Podana tutaj nazwa serwera odpowiada tej podanej w pliku config.yml BungeeCorda.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od xAxee w Łączenie graczy z serwerami pod BungeeCord
Witajcie Czerwono Towarzysze! W tym poradniku przedstawię Wam jak łączyć graczy z innym serwerem podpiętym do BungeeCord. Przydatne na przykład do łączenia graczy z serwera lobby na inne serwery (oraz vice-versa). Do dzieła!
Chcesz wykonać instrukcję przeniesienia gracza na inny serwer. Na początku musisz jednak zrozumieć czym jest serwer, na przykład na silniku Spigot i czym jest BungeeCord. Bez tej wiedzy nieudolnie będziesz próbować różnych sztuczek z przenoszeniem na inny serwer.
Na początku spróbuje tą trochę zobrazować. Prawdopodobnie wyobrażasz sobie, że BungeeCord działa na następującej zasadzie. Janusz wchodzi na serwer poprzez połączenie się przez BungeeCorda, następnie na serwerze (który jest serwerem lobby) wybiera inny serwer, więc ten go łączy.
[CIACH]
Jest to błąd bo serwer nie wysyła graczy na inny serwer. Wszystko robi BungeeCord. Serwer lobby jest kolejnym serwerem który działa na takiej samej zasadzie jak inne w tej samej sieci. Działa ona na identycznej zasadzie jak Creative, Free Build czy Survival.
[CIACH]
Aby móc przenieść Towarzysza Sebastian z serwera Lobby na serwer Creative należy do BungeeCord wysłać taką instrukcję. Tylko on przekierowuje połączenia i tylko on może przenosić graczy między serwerami. BungeeCord jest proxy między klientem, czyli Sebastianem, a fizycznym serwerem, czyli Lobby.
Komendy BungeeCord, takie jak /end, /perms, /server, /find czy /alert są zatem komendami na proxy, a nie na serwerze. Co to oznacza? Klient z serwerem (i vice versa) komunikuje się za pomocą pakietów, czyli małych paczuszek z danymi. Może to być informacja o postawieniu klocka na mapie, ruszeniu się gracza, czy jego interakcji w świat. Towarzysz, na przykład Grażyna wpisuje na chacie komendę /server, klient do wysyła do serwera pakiet o wykonaniu komendy. Pakiet dociera do BungeeCorda, ten go otwiera i sprawdza czym on tak na prawdę jest. Widzi, że użyto komendy /server. Sprawdza on czy u siebie ma taką zarejestrowaną komendę. Jeśli nie wysyła ten pakiet dalej na serwer. Jeśli tak do ją wykonuje. To wszystko sprowadza się do tego, że serwer nie może wykonać za gracza komendy, bo musi ona zostać przesłana pakietem. Pakiet musi przejść przez proxy BungeeCorda.
Wykonanie takiej czynności całkowicie więc odpada. BungeeCord natomiast oferuje wysyłanie danych między sobą a serwerem. Jest to tak zwany "Plugin Messaging Channel". Teraz pokażę Ci jak to zrobić Towarzyszu.
1. Najpierw musisz zarejestrować ten kanał w swoim pluginie. Najlepiej wykonać to w Twoim onEnable():
@Override public void onEnable() { this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); } 2. Teraz należy stworzyć sobie klasę BungeeConnector w Twoim projekcie. Będzie ona miała za zadanie łączyć wybranych graczy z wybranym przez ciebie serwerem.
/** * Connect players between servers within the BungeeCord proxy. */ public class BungeeConnector { public static final String PLUGIN_CHANNEL = "BungeeCord"; private final Plugin plugin; public BungeeConnector(Plugin plugin) { this.plugin = plugin; } /** * Connect given <code>player</code> into the given <code>target</code> server. * @param player {@link Player} who should be connected. * @param target The target server identifier specified in the BungeeCord proxy configuration. */ public void connect(Player player, String target) { ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(array); try { output.writeUTF("Connect"); output.writeUTF(target); } catch (IOException ignored) { } player.sendPluginMessage(this.plugin, PLUGIN_CHANNEL, array.toByteArray()); } } 3. W głównej klasie Twojego pluginu możesz sobie zrobić instancję tej klasy. W tym celu na górze zrób sobie zmienną ją przetrzymującą.
private BungeeConnector connector; 4. W onEnable() definiuj zmienną do jej prawidłowej wartości.
@Override public void onEnable() { this.connector = new BungeeConnector(this); this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); // to już było wcześniej } 5. Teraz wystarczy już tylko zrobić sobie do niej getter.
public BungeeConnector getConnector() { return this.connector; }
I gotowe! Oczywiście można by to jeszcze ulepszyć, na przykład w connect(...) dodać anulowalny event. Dzięki temu można by go anulować w pewnych przypadkach. Na przykład gdy na serwerze jest anti-logout, a Ty nie chcesz żeby w czasie PvP mógł się przenosić między serwerami.
Aby połączyć gracza z serwerem wystarczy użyć
this.getConnector().connect(player, "survival"); Dzięki temu gracz połączy się z serwerem Survival. Zgodnie z zaleceniami konfiguracyjnymi serwery powinny zostać nazwane całkowicie małymi literami. Podana tutaj nazwa serwera odpowiada tej podanej w pliku config.yml BungeeCorda.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od wojtess w Regeneracja światów (idealne pod mini-gry)
Właśnie odpisałem w temacie SkyWars - Obszar bogaty post na temat jak zrobić regenerację światów. Myślę, że może się to przydać wielu osobom. Omówię tutaj dwa znane rozwiązania regeneracji, oraz podam nowy - najlepszy. Będę podawać referencję do kodu mojego Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, ponieważ tam właśnie taki system "regeneracji" istnieje.
Zapis zmiany stanu bloków - BŁĄD!
Przy słowie "regeneracja" rozumiemy przede wszystkim powrót stanu bloków do takiego, jakie były w punkcje pierwotnym. Pierwsze rozwiązanie takiego problemu przychodzi nam rejestracja zmiany stanu wszystkich bloków. Stawiamy dirt? Informujemy, że na koordynatach X, Y oraz Z nowy blok to dirt. Na pierwszy rzut oka może się to wydawać działające, ale to nie prawda. Nigdy nie ma pewności, że wszystkie bloki zostaną zregenerowane, dodatkowo taki zapis brudzi tylko naszą pamięć RAM (jeżeli mam to robić in-memory). Musielibyśmy nasłuchiwać każdą jedną możliwą zmianę bloku w serwerze oraz ją rejestrować. Drugi problem z tego się rodzi - kiedy i jak to zregenerować? Moc obliczeniowa do wykonania tak dużego zadania jak podmiana dużej ilości bloków zużyje nam dużo CPU. Kolokwialnie rzecz ujmując regeneracja można wpłynąć znaczenia na działanie serwera, więc najlepiej byłoby to zrobić podczas gdy jest on wyłączony, lub nie ma na niej żadnych graczy.
Tworzenie rzutu stanu bloków - BŁĄD!
No dobrze, skoro nie działa rejestracja bloków, to może przy starcie gry zapiszmy stan wszystkich bloków świata, a potem przywróćmy je do tej wartości? Pobieranie oraz zapisanie stanu bloków będzie bardzo podobne do ich podmiany - kosztuje bardzo mocnym zużyciem zasobów serwera, więc należałoby zrobić go poza jego normalnym działaniem. Ostatecznie takie rozwiązanie odpada, ponieważ jest to także w dużej mierze powielenie rozwiązania pierwszego.
Ładowanie - wyładowywanie światów - ROZWIĄZANIE!
Silnik Bukkit oferuje nam możliwość ładowania i wyładowywania światów w czasie jego trwania działania. Wyładowanie świata następuje natychmiastowo, polega jedynie na usunięciu go z pamięci RAM. Ładowanie natomiast może znaczenia wpłynąć na działanie logiki serwera. Generalnie rzecz biorąc ładowanie i wyładowywanie światów jest najlepszym rozwiązaniem, ponieważ i tak będzie kosztować zużyciem mniejszej ilości zasobów, niż rzeczywista regeneracja.
Wprowadzenie
No dobrze - zacznijmy. Na początku prosiłbym abyśmy ustanowili w tym poście kilka słów stałych, aby nie było problemów ze zrozumieniem.
Świat (world) - tym słowym mam na myśli Minecraftowy świat ładowany do serwera. W plikach świata musi znajdować się plik level.dat; tam zapisane są informacje o generatorze, ziarnie (seed), miejscu spawna, obecny spawnpoint oraz masa innych rzeczy. Mapa - tym słowem mam na myśli zbiór bloków które tworzą jakąś strukturę. Znajdują się one w chunkach, czyli dużych zbiornikach 16x16 bloków (na koordynatach X oraz Z) na pełnej wysokości świata - koordynat Y.
Ładowanie świata
Świat do serwera ładujemy metodą Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! z interfejsu Server. W parametrze podajemy nowy obiekt klasy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - jest to Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, czyli budowniczy innego obiektu, gdzie jego stworzenie wykonujemy po woli wykonując po kolei jej metody. Załadowanie nowego świata można także Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. WorldCreator jest świetnym narzędziem do wypełnienia znacznej większości ustawień świata. Zaczynami od ich ustawienia.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy typ świata - może to być NORMAL, THE_END lub NETHER. Dzięki temu zmienimy dużo w jego działaniu. Na przykład niebo (w netherze jest czerwone, w the endzie jest czarne z gwiazdami), oraz fizykę (w netherze nie można wylewać wody, w the endzie spawnują się tylko ender-dragony i endermany). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - w parametrze podajemy wartość true/false, gdzie true ustawi nam, że na tym świecie będą się generować struktury - wioski, opuszczone kopalnie, piramidy, studnie, ... - false je wyłączy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy generator z jakiego nasz nowy świat będzie korzystać. Proszę spojrzeć na metody poniżej - mamy tutaj wiele możliwości wyboru. Możemy tutaj stworzyć swój własny generator podając nasz Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, lub pobrać domyślny generator pluginu podając jego nazwę w Stringu. Proszę poczytać więcej o generatorach w poście niżej - to bardzo ważne! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy dodatkowe ustawienia generatora - nie znam do końca jego działania - nigdy z tego nie korzystałem. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy nazwę naszego świata - UWAGA: nazwa świata musi znajdować się w przedziale A-Z, a-z, 0-9 oraz _ i - żadne inne znaki nie są wspomagane! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy seed - ziarenko z którego będzie korzystać nasz generator. Działa tylko przy korzystaniu z generatora vanilla! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy typ naszego świata. Podajemy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! gdzie możemy podać świat płaski, duże biomy, oraz masę innych typów. Pozwolę sobie jeszcze pokazać jak to działa w pluginie Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Następnie wykonujemy metodę createWorld(), a rezultat zapisujemy w obiekcie World. W tym momencie nasz świat zostanie załadowany do pamięci serwera. Może to zająć moment, zależnie od wielkości świata.
Teraz należy ustawić ostatnie ustawienia gdzie dokładniej ustawimy ten świat pod nasz serwer.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - dzięki temu nasz świat nie zapisze się przy jego wyładowaniu, oraz wyłączymy auto-save, który domyślnie wykonuje się co 5 minut (do ustawienia w bukkit.yml). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - domyślnie w Minecraft chunki na spawnie oraz wokół niego nie są wyładowywanie z pamięci, oraz zawsze znajdują się w pamięci podręcznej serwera. Jest to zbędny zabieg, ponieważ spawnpoint świata nie koniecznie jest spawnem mapy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - może być przydatne na mapie typu SkyWars. Dzięki temu wyłączymy możliwość spawnowania się potworów i/lub zwierząt na całym świecie. Jak to działa w Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
I gotowe! Teraz mamy załadowany świat gotowy do gry!
Wyładowywanie świata
Wyładowywanie świata jest bardzo proste. Wystarczy użyć metody Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. Możemy podać nazwę świata, lub obiekt World. Drugi parametr ustawiamy na false, dzięki czemu nasz świat nie zostanie zapisany.
Optymalizacja światów
Jak wiemy generowanie świata zużywa drastycznie dużo zasobów serwera. Aby temu zaradzić należy zrobić prosty generator który wygeneruje nam tak zwany "void", czyli pusty świat. Tutaj istnieje taki generator, który generuje nam całkowicie pusty świat -> Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Należałoby także zoptymalizować pliki świata. Klient, serwer, mody oraz różne programy (np MCEdit) generują nam dodatkowe, zbędne pliki które możemy spokojnie usunąć.
level.dat - pozostaw - tutaj zapisane są wszystkie podstawowe informacje na temat świata. region (folder) - pozostaw - tutaj znajdują się pliki, w których zapisane są chunki świata. data (folder) - pozostaw - tutaj zapisane są wszystkie wioski na mapie, oraz mapy (te które wskazują nam jakiś punkt, lub po prostu mamy w niej grafikę). Wszystko inne należy usunąć!
Usuwanie zbędnych chunków
Przy budowie mapy Minecraft generuje nam wszystkie chunki dookoła nas. Wiele z nich jest zbędnych ponieważ nie znajduje się na nich żaden element naszej mapy. Jest to kolejny krok naszej optymalizacji, która będzie miała wpływ na przyspieszenie ładowania świata. Ten krok należy wykonać przed powyższym "Optymalizacja światów".
Przy ładowaniu świata serwer będzie nam czytał chunki które znajdują się na mapie. Odczytanie ich z pliku zajmie znacznie więcej czasu niż pobranie pustej tablicy w naszym generatorze. Zupełnie inaczej jest w generatorze vanilla - tam pobranie zapisanego świata zajmie znacznie mniej czasu, niż wygenerowanie nowego! Pamiętaj o tym!
Pobieramy sobie programik MCEdit - Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! Otwieramy go Po otwarciu pokaże nam się menu główne programu Klikamy "Load Level" Wybieramy plik level.dat świata w którym chcemy usunąć zbędne chunki Klikamy "otwórz" Nasz świat zostanie załadowany Klikamy na górze programu "Chunk View"; przełączymy się dzięki temu z widoku gracza na widok z lotu ptaka. Na ekranie pojawi nam się siatka (możemy przybliżyć/oddalić świat scrollując myszką) Zaznaczamy myszką te chunki (kratki) na których znajduje się nasza mapa Po lewej stronie pokazuje nam się okienko - klikamy na nim przycisk "Prune" Wyskoczy nam okienko potwierdzające usunięcie wszystkich chunków które nie zostały zaznaczone. Proszę się upewnić czy na pewno zaznaczyliśmy te chunki na których znajduje się mapa. Następnego punktu nie da się cofnąć! Klikamy OK, chunki zostaną usunięte Gotowe, zamykamy program i przechodzimy do punktu "Optymalizacja światów"!
Zakończenie
Tak o to mamy całkowcie zoptymalizowany świat oraz system "regeneracji".
Dobre praktyki
Jest jeszcze jedna rzecz którą chciałbym zaznaczyć. Folder twojego świata w głównym folderze serwera nie zostanie usunięty. Zalecam otworzyć plik bukkit.yml, oraz w sekcji settings, dopisać world-container: '/worlds' - dzięki temu wszystkie nasze światy będą zapisywane w folderze worlds, podobnie jak pluginy w plugins. Jest to dość ukryta funkcja w Bukkicie, ponieważ nie jest domyślnie zapisane w YAMLu.
Przykład:
settings: world-container: '/worlds'
Drugie zagadnienie to 100% pewność, że nasza mapa nie zostanie uszkodzona. zalecam w głównym folderze serwera, obok logs, plugins i worlds zrobić folder maps. Tam będziemy trzymać wszystkie światy na których znajdują się mapy. Podczas ładowania tej mapy będziemy kopiować jej pliki do folderu worlds z poziomu pluginu. Dzięki temu mamy 100% pewność, że naszej mapie (która może być wykorzystywana przez wiele serwerów jednocześnie) na pewno się nic nie stanie!
Mam nadzieję, że pomogłem
-
TheMolkaPL otrzymał(a) reputację od smileDev w Łączenie graczy z serwerami pod BungeeCord
Witajcie Czerwono Towarzysze! W tym poradniku przedstawię Wam jak łączyć graczy z innym serwerem podpiętym do BungeeCord. Przydatne na przykład do łączenia graczy z serwera lobby na inne serwery (oraz vice-versa). Do dzieła!
Chcesz wykonać instrukcję przeniesienia gracza na inny serwer. Na początku musisz jednak zrozumieć czym jest serwer, na przykład na silniku Spigot i czym jest BungeeCord. Bez tej wiedzy nieudolnie będziesz próbować różnych sztuczek z przenoszeniem na inny serwer.
Na początku spróbuje tą trochę zobrazować. Prawdopodobnie wyobrażasz sobie, że BungeeCord działa na następującej zasadzie. Janusz wchodzi na serwer poprzez połączenie się przez BungeeCorda, następnie na serwerze (który jest serwerem lobby) wybiera inny serwer, więc ten go łączy.
[CIACH]
Jest to błąd bo serwer nie wysyła graczy na inny serwer. Wszystko robi BungeeCord. Serwer lobby jest kolejnym serwerem który działa na takiej samej zasadzie jak inne w tej samej sieci. Działa ona na identycznej zasadzie jak Creative, Free Build czy Survival.
[CIACH]
Aby móc przenieść Towarzysza Sebastian z serwera Lobby na serwer Creative należy do BungeeCord wysłać taką instrukcję. Tylko on przekierowuje połączenia i tylko on może przenosić graczy między serwerami. BungeeCord jest proxy między klientem, czyli Sebastianem, a fizycznym serwerem, czyli Lobby.
Komendy BungeeCord, takie jak /end, /perms, /server, /find czy /alert są zatem komendami na proxy, a nie na serwerze. Co to oznacza? Klient z serwerem (i vice versa) komunikuje się za pomocą pakietów, czyli małych paczuszek z danymi. Może to być informacja o postawieniu klocka na mapie, ruszeniu się gracza, czy jego interakcji w świat. Towarzysz, na przykład Grażyna wpisuje na chacie komendę /server, klient do wysyła do serwera pakiet o wykonaniu komendy. Pakiet dociera do BungeeCorda, ten go otwiera i sprawdza czym on tak na prawdę jest. Widzi, że użyto komendy /server. Sprawdza on czy u siebie ma taką zarejestrowaną komendę. Jeśli nie wysyła ten pakiet dalej na serwer. Jeśli tak do ją wykonuje. To wszystko sprowadza się do tego, że serwer nie może wykonać za gracza komendy, bo musi ona zostać przesłana pakietem. Pakiet musi przejść przez proxy BungeeCorda.
Wykonanie takiej czynności całkowicie więc odpada. BungeeCord natomiast oferuje wysyłanie danych między sobą a serwerem. Jest to tak zwany "Plugin Messaging Channel". Teraz pokażę Ci jak to zrobić Towarzyszu.
1. Najpierw musisz zarejestrować ten kanał w swoim pluginie. Najlepiej wykonać to w Twoim onEnable():
@Override public void onEnable() { this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); } 2. Teraz należy stworzyć sobie klasę BungeeConnector w Twoim projekcie. Będzie ona miała za zadanie łączyć wybranych graczy z wybranym przez ciebie serwerem.
/** * Connect players between servers within the BungeeCord proxy. */ public class BungeeConnector { public static final String PLUGIN_CHANNEL = "BungeeCord"; private final Plugin plugin; public BungeeConnector(Plugin plugin) { this.plugin = plugin; } /** * Connect given <code>player</code> into the given <code>target</code> server. * @param player {@link Player} who should be connected. * @param target The target server identifier specified in the BungeeCord proxy configuration. */ public void connect(Player player, String target) { ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(array); try { output.writeUTF("Connect"); output.writeUTF(target); } catch (IOException ignored) { } player.sendPluginMessage(this.plugin, PLUGIN_CHANNEL, array.toByteArray()); } } 3. W głównej klasie Twojego pluginu możesz sobie zrobić instancję tej klasy. W tym celu na górze zrób sobie zmienną ją przetrzymującą.
private BungeeConnector connector; 4. W onEnable() definiuj zmienną do jej prawidłowej wartości.
@Override public void onEnable() { this.connector = new BungeeConnector(this); this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); // to już było wcześniej } 5. Teraz wystarczy już tylko zrobić sobie do niej getter.
public BungeeConnector getConnector() { return this.connector; }
I gotowe! Oczywiście można by to jeszcze ulepszyć, na przykład w connect(...) dodać anulowalny event. Dzięki temu można by go anulować w pewnych przypadkach. Na przykład gdy na serwerze jest anti-logout, a Ty nie chcesz żeby w czasie PvP mógł się przenosić między serwerami.
Aby połączyć gracza z serwerem wystarczy użyć
this.getConnector().connect(player, "survival"); Dzięki temu gracz połączy się z serwerem Survival. Zgodnie z zaleceniami konfiguracyjnymi serwery powinny zostać nazwane całkowicie małymi literami. Podana tutaj nazwa serwera odpowiada tej podanej w pliku config.yml BungeeCorda.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od Peridot w Enderchest
Wystarczy dostać się do tego
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
i w InventorySubcontainer podmienić b (int) na własność wartość.
-
TheMolkaPL otrzymał(a) reputację od kerpson w Metody statyczne
Utils... (inaczej helper) - czyli coś gdzie wrzucasz wszystko co nie pasuje do żadnej twojej klasy...
Założenie jest takie, że musisz zrobić jakąś metodę, ale nie ma żadnej klasy która reprezentowała by strukturę, gdzie taka metoda by pasowała... albo potrzebujesz zrobić metodę do klasy finalnej, więc nierozszerzalnej, lub coś w tym rodzaju. W związku z tym klasa ta nie ma obiektów. Powinieneś tą klasę oznaczyć jako final, tak, aby nikt nie mógł jej rozszerzać oraz zrobić prywatny konstruktor bez parametrów. Dzięki temu stworzenie instancji tej klasy nie będzie możliwe.
Teraz wady i zalety takiego rozwiązania. Zaletą jest na pewno łatwy dostęp do takich metod. Są to, a przynajmniej powinny, publiczne metody statyczne, a więc wystarczy odnieść się do klasy i wywołać statyczną metodę. Wad natomiast znalazłbym kilka. Po pierwsze globalność - takiej metody nie da się nadpisać i zmienić jej zachowania - czyli jednej z najważniejszych zalet programowania obiektowego. W najlepszej sytuacji powinna być klasa, która będzie coś reprezentować, którą można rozszerzyć i nadpisać metody, by zmienić ich zachowanie. Po drugie trudność debugowania. Metoda ta jest globalna, dostępna zewsząd. Debugowanie takiej metody w poszukiwaniu zmian jest znacznie bardziej utrudnione.
Czyli podsumowując takie utils to metody, które nie pasują do żadnej klasy, którą masz, więc wrzucasz je do jednego worka, aka "utils"/"helper". Metody w tej klasie zawarte powinny być publiczne i statyczne, co niesie za sobą łatwość dostępu, ale za to trudność debugowania i niezmienność (brak możliwości zmiany ich zachowania).
Jeszcze inną kwestią jest, tutaj nie poruszona, przechowywanie modyfikowalnych (mutable) danych globalnie, czyli w polach statycznych.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od yooniks w Metody statyczne
Utils... (inaczej helper) - czyli coś gdzie wrzucasz wszystko co nie pasuje do żadnej twojej klasy...
Założenie jest takie, że musisz zrobić jakąś metodę, ale nie ma żadnej klasy która reprezentowała by strukturę, gdzie taka metoda by pasowała... albo potrzebujesz zrobić metodę do klasy finalnej, więc nierozszerzalnej, lub coś w tym rodzaju. W związku z tym klasa ta nie ma obiektów. Powinieneś tą klasę oznaczyć jako final, tak, aby nikt nie mógł jej rozszerzać oraz zrobić prywatny konstruktor bez parametrów. Dzięki temu stworzenie instancji tej klasy nie będzie możliwe.
Teraz wady i zalety takiego rozwiązania. Zaletą jest na pewno łatwy dostęp do takich metod. Są to, a przynajmniej powinny, publiczne metody statyczne, a więc wystarczy odnieść się do klasy i wywołać statyczną metodę. Wad natomiast znalazłbym kilka. Po pierwsze globalność - takiej metody nie da się nadpisać i zmienić jej zachowania - czyli jednej z najważniejszych zalet programowania obiektowego. W najlepszej sytuacji powinna być klasa, która będzie coś reprezentować, którą można rozszerzyć i nadpisać metody, by zmienić ich zachowanie. Po drugie trudność debugowania. Metoda ta jest globalna, dostępna zewsząd. Debugowanie takiej metody w poszukiwaniu zmian jest znacznie bardziej utrudnione.
Czyli podsumowując takie utils to metody, które nie pasują do żadnej klasy, którą masz, więc wrzucasz je do jednego worka, aka "utils"/"helper". Metody w tej klasie zawarte powinny być publiczne i statyczne, co niesie za sobą łatwość dostępu, ale za to trudność debugowania i niezmienność (brak możliwości zmiany ich zachowania).
Jeszcze inną kwestią jest, tutaj nie poruszona, przechowywanie modyfikowalnych (mutable) danych globalnie, czyli w polach statycznych.
Pozdrawiam Czerwono
-
TheMolkaPL przyznał(a) reputację dla Usunięty#3468 w Jak napisać optymalnie plugin!
Ilosc zadan, jakie zarejestrujesz nie stanowi roznicy, bo wszystkie i tak wykonaja sie w jednym momencie. Jeszcze jest cos takiego jak timingi, ktore zliczaja czas wykonania zadania, gdy wszystkie taski sprowadzisz do jednego, w pewnym sensie stracisz kontrole nad timingami przez co stana sie zwyczajnie bezuzyteczne.
-
TheMolkaPL otrzymał(a) reputację od MaticzekYTPL w DerpMC.PL - Najlepsze tryby z zagranicznych serwerów!
You made my day XDD
-
TheMolkaPL otrzymał(a) reputację od Leon135 w Regeneracja światów (idealne pod mini-gry)
Właśnie odpisałem w temacie SkyWars - Obszar bogaty post na temat jak zrobić regenerację światów. Myślę, że może się to przydać wielu osobom. Omówię tutaj dwa znane rozwiązania regeneracji, oraz podam nowy - najlepszy. Będę podawać referencję do kodu mojego Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, ponieważ tam właśnie taki system "regeneracji" istnieje.
Zapis zmiany stanu bloków - BŁĄD!
Przy słowie "regeneracja" rozumiemy przede wszystkim powrót stanu bloków do takiego, jakie były w punkcje pierwotnym. Pierwsze rozwiązanie takiego problemu przychodzi nam rejestracja zmiany stanu wszystkich bloków. Stawiamy dirt? Informujemy, że na koordynatach X, Y oraz Z nowy blok to dirt. Na pierwszy rzut oka może się to wydawać działające, ale to nie prawda. Nigdy nie ma pewności, że wszystkie bloki zostaną zregenerowane, dodatkowo taki zapis brudzi tylko naszą pamięć RAM (jeżeli mam to robić in-memory). Musielibyśmy nasłuchiwać każdą jedną możliwą zmianę bloku w serwerze oraz ją rejestrować. Drugi problem z tego się rodzi - kiedy i jak to zregenerować? Moc obliczeniowa do wykonania tak dużego zadania jak podmiana dużej ilości bloków zużyje nam dużo CPU. Kolokwialnie rzecz ujmując regeneracja można wpłynąć znaczenia na działanie serwera, więc najlepiej byłoby to zrobić podczas gdy jest on wyłączony, lub nie ma na niej żadnych graczy.
Tworzenie rzutu stanu bloków - BŁĄD!
No dobrze, skoro nie działa rejestracja bloków, to może przy starcie gry zapiszmy stan wszystkich bloków świata, a potem przywróćmy je do tej wartości? Pobieranie oraz zapisanie stanu bloków będzie bardzo podobne do ich podmiany - kosztuje bardzo mocnym zużyciem zasobów serwera, więc należałoby zrobić go poza jego normalnym działaniem. Ostatecznie takie rozwiązanie odpada, ponieważ jest to także w dużej mierze powielenie rozwiązania pierwszego.
Ładowanie - wyładowywanie światów - ROZWIĄZANIE!
Silnik Bukkit oferuje nam możliwość ładowania i wyładowywania światów w czasie jego trwania działania. Wyładowanie świata następuje natychmiastowo, polega jedynie na usunięciu go z pamięci RAM. Ładowanie natomiast może znaczenia wpłynąć na działanie logiki serwera. Generalnie rzecz biorąc ładowanie i wyładowywanie światów jest najlepszym rozwiązaniem, ponieważ i tak będzie kosztować zużyciem mniejszej ilości zasobów, niż rzeczywista regeneracja.
Wprowadzenie
No dobrze - zacznijmy. Na początku prosiłbym abyśmy ustanowili w tym poście kilka słów stałych, aby nie było problemów ze zrozumieniem.
Świat (world) - tym słowym mam na myśli Minecraftowy świat ładowany do serwera. W plikach świata musi znajdować się plik level.dat; tam zapisane są informacje o generatorze, ziarnie (seed), miejscu spawna, obecny spawnpoint oraz masa innych rzeczy. Mapa - tym słowem mam na myśli zbiór bloków które tworzą jakąś strukturę. Znajdują się one w chunkach, czyli dużych zbiornikach 16x16 bloków (na koordynatach X oraz Z) na pełnej wysokości świata - koordynat Y.
Ładowanie świata
Świat do serwera ładujemy metodą Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! z interfejsu Server. W parametrze podajemy nowy obiekt klasy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - jest to Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, czyli budowniczy innego obiektu, gdzie jego stworzenie wykonujemy po woli wykonując po kolei jej metody. Załadowanie nowego świata można także Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. WorldCreator jest świetnym narzędziem do wypełnienia znacznej większości ustawień świata. Zaczynami od ich ustawienia.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy typ świata - może to być NORMAL, THE_END lub NETHER. Dzięki temu zmienimy dużo w jego działaniu. Na przykład niebo (w netherze jest czerwone, w the endzie jest czarne z gwiazdami), oraz fizykę (w netherze nie można wylewać wody, w the endzie spawnują się tylko ender-dragony i endermany). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - w parametrze podajemy wartość true/false, gdzie true ustawi nam, że na tym świecie będą się generować struktury - wioski, opuszczone kopalnie, piramidy, studnie, ... - false je wyłączy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy generator z jakiego nasz nowy świat będzie korzystać. Proszę spojrzeć na metody poniżej - mamy tutaj wiele możliwości wyboru. Możemy tutaj stworzyć swój własny generator podając nasz Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!, lub pobrać domyślny generator pluginu podając jego nazwę w Stringu. Proszę poczytać więcej o generatorach w poście niżej - to bardzo ważne! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - ustawiamy dodatkowe ustawienia generatora - nie znam do końca jego działania - nigdy z tego nie korzystałem. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy nazwę naszego świata - UWAGA: nazwa świata musi znajdować się w przedziale A-Z, a-z, 0-9 oraz _ i - żadne inne znaki nie są wspomagane! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy seed - ziarenko z którego będzie korzystać nasz generator. Działa tylko przy korzystaniu z generatora vanilla! Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - podajemy typ naszego świata. Podajemy Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! gdzie możemy podać świat płaski, duże biomy, oraz masę innych typów. Pozwolę sobie jeszcze pokazać jak to działa w pluginie Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Następnie wykonujemy metodę createWorld(), a rezultat zapisujemy w obiekcie World. W tym momencie nasz świat zostanie załadowany do pamięci serwera. Może to zająć moment, zależnie od wielkości świata.
Teraz należy ustawić ostatnie ustawienia gdzie dokładniej ustawimy ten świat pod nasz serwer.
Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - dzięki temu nasz świat nie zapisze się przy jego wyładowaniu, oraz wyłączymy auto-save, który domyślnie wykonuje się co 5 minut (do ustawienia w bukkit.yml). Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - domyślnie w Minecraft chunki na spawnie oraz wokół niego nie są wyładowywanie z pamięci, oraz zawsze znajdują się w pamięci podręcznej serwera. Jest to zbędny zabieg, ponieważ spawnpoint świata nie koniecznie jest spawnem mapy. Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! - może być przydatne na mapie typu SkyWars. Dzięki temu wyłączymy możliwość spawnowania się potworów i/lub zwierząt na całym świecie. Jak to działa w Arcade2: Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
I gotowe! Teraz mamy załadowany świat gotowy do gry!
Wyładowywanie świata
Wyładowywanie świata jest bardzo proste. Wystarczy użyć metody Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!. Możemy podać nazwę świata, lub obiekt World. Drugi parametr ustawiamy na false, dzięki czemu nasz świat nie zostanie zapisany.
Optymalizacja światów
Jak wiemy generowanie świata zużywa drastycznie dużo zasobów serwera. Aby temu zaradzić należy zrobić prosty generator który wygeneruje nam tak zwany "void", czyli pusty świat. Tutaj istnieje taki generator, który generuje nam całkowicie pusty świat -> Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść!
Należałoby także zoptymalizować pliki świata. Klient, serwer, mody oraz różne programy (np MCEdit) generują nam dodatkowe, zbędne pliki które możemy spokojnie usunąć.
level.dat - pozostaw - tutaj zapisane są wszystkie podstawowe informacje na temat świata. region (folder) - pozostaw - tutaj znajdują się pliki, w których zapisane są chunki świata. data (folder) - pozostaw - tutaj zapisane są wszystkie wioski na mapie, oraz mapy (te które wskazują nam jakiś punkt, lub po prostu mamy w niej grafikę). Wszystko inne należy usunąć!
Usuwanie zbędnych chunków
Przy budowie mapy Minecraft generuje nam wszystkie chunki dookoła nas. Wiele z nich jest zbędnych ponieważ nie znajduje się na nich żaden element naszej mapy. Jest to kolejny krok naszej optymalizacji, która będzie miała wpływ na przyspieszenie ładowania świata. Ten krok należy wykonać przed powyższym "Optymalizacja światów".
Przy ładowaniu świata serwer będzie nam czytał chunki które znajdują się na mapie. Odczytanie ich z pliku zajmie znacznie więcej czasu niż pobranie pustej tablicy w naszym generatorze. Zupełnie inaczej jest w generatorze vanilla - tam pobranie zapisanego świata zajmie znacznie mniej czasu, niż wygenerowanie nowego! Pamiętaj o tym!
Pobieramy sobie programik MCEdit - Zarejestruj się lub zaloguj, aby zobaczyć ukrytą treść! Otwieramy go Po otwarciu pokaże nam się menu główne programu Klikamy "Load Level" Wybieramy plik level.dat świata w którym chcemy usunąć zbędne chunki Klikamy "otwórz" Nasz świat zostanie załadowany Klikamy na górze programu "Chunk View"; przełączymy się dzięki temu z widoku gracza na widok z lotu ptaka. Na ekranie pojawi nam się siatka (możemy przybliżyć/oddalić świat scrollując myszką) Zaznaczamy myszką te chunki (kratki) na których znajduje się nasza mapa Po lewej stronie pokazuje nam się okienko - klikamy na nim przycisk "Prune" Wyskoczy nam okienko potwierdzające usunięcie wszystkich chunków które nie zostały zaznaczone. Proszę się upewnić czy na pewno zaznaczyliśmy te chunki na których znajduje się mapa. Następnego punktu nie da się cofnąć! Klikamy OK, chunki zostaną usunięte Gotowe, zamykamy program i przechodzimy do punktu "Optymalizacja światów"!
Zakończenie
Tak o to mamy całkowcie zoptymalizowany świat oraz system "regeneracji".
Dobre praktyki
Jest jeszcze jedna rzecz którą chciałbym zaznaczyć. Folder twojego świata w głównym folderze serwera nie zostanie usunięty. Zalecam otworzyć plik bukkit.yml, oraz w sekcji settings, dopisać world-container: '/worlds' - dzięki temu wszystkie nasze światy będą zapisywane w folderze worlds, podobnie jak pluginy w plugins. Jest to dość ukryta funkcja w Bukkicie, ponieważ nie jest domyślnie zapisane w YAMLu.
Przykład:
settings: world-container: '/worlds'
Drugie zagadnienie to 100% pewność, że nasza mapa nie zostanie uszkodzona. zalecam w głównym folderze serwera, obok logs, plugins i worlds zrobić folder maps. Tam będziemy trzymać wszystkie światy na których znajdują się mapy. Podczas ładowania tej mapy będziemy kopiować jej pliki do folderu worlds z poziomu pluginu. Dzięki temu mamy 100% pewność, że naszej mapie (która może być wykorzystywana przez wiele serwerów jednocześnie) na pewno się nic nie stanie!
Mam nadzieję, że pomogłem
-
TheMolkaPL otrzymał(a) reputację od yooniks w Łączenie graczy z serwerami pod BungeeCord
Witajcie Czerwono Towarzysze! W tym poradniku przedstawię Wam jak łączyć graczy z innym serwerem podpiętym do BungeeCord. Przydatne na przykład do łączenia graczy z serwera lobby na inne serwery (oraz vice-versa). Do dzieła!
Chcesz wykonać instrukcję przeniesienia gracza na inny serwer. Na początku musisz jednak zrozumieć czym jest serwer, na przykład na silniku Spigot i czym jest BungeeCord. Bez tej wiedzy nieudolnie będziesz próbować różnych sztuczek z przenoszeniem na inny serwer.
Na początku spróbuje tą trochę zobrazować. Prawdopodobnie wyobrażasz sobie, że BungeeCord działa na następującej zasadzie. Janusz wchodzi na serwer poprzez połączenie się przez BungeeCorda, następnie na serwerze (który jest serwerem lobby) wybiera inny serwer, więc ten go łączy.
[CIACH]
Jest to błąd bo serwer nie wysyła graczy na inny serwer. Wszystko robi BungeeCord. Serwer lobby jest kolejnym serwerem który działa na takiej samej zasadzie jak inne w tej samej sieci. Działa ona na identycznej zasadzie jak Creative, Free Build czy Survival.
[CIACH]
Aby móc przenieść Towarzysza Sebastian z serwera Lobby na serwer Creative należy do BungeeCord wysłać taką instrukcję. Tylko on przekierowuje połączenia i tylko on może przenosić graczy między serwerami. BungeeCord jest proxy między klientem, czyli Sebastianem, a fizycznym serwerem, czyli Lobby.
Komendy BungeeCord, takie jak /end, /perms, /server, /find czy /alert są zatem komendami na proxy, a nie na serwerze. Co to oznacza? Klient z serwerem (i vice versa) komunikuje się za pomocą pakietów, czyli małych paczuszek z danymi. Może to być informacja o postawieniu klocka na mapie, ruszeniu się gracza, czy jego interakcji w świat. Towarzysz, na przykład Grażyna wpisuje na chacie komendę /server, klient do wysyła do serwera pakiet o wykonaniu komendy. Pakiet dociera do BungeeCorda, ten go otwiera i sprawdza czym on tak na prawdę jest. Widzi, że użyto komendy /server. Sprawdza on czy u siebie ma taką zarejestrowaną komendę. Jeśli nie wysyła ten pakiet dalej na serwer. Jeśli tak do ją wykonuje. To wszystko sprowadza się do tego, że serwer nie może wykonać za gracza komendy, bo musi ona zostać przesłana pakietem. Pakiet musi przejść przez proxy BungeeCorda.
Wykonanie takiej czynności całkowicie więc odpada. BungeeCord natomiast oferuje wysyłanie danych między sobą a serwerem. Jest to tak zwany "Plugin Messaging Channel". Teraz pokażę Ci jak to zrobić Towarzyszu.
1. Najpierw musisz zarejestrować ten kanał w swoim pluginie. Najlepiej wykonać to w Twoim onEnable():
@Override public void onEnable() { this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); } 2. Teraz należy stworzyć sobie klasę BungeeConnector w Twoim projekcie. Będzie ona miała za zadanie łączyć wybranych graczy z wybranym przez ciebie serwerem.
/** * Connect players between servers within the BungeeCord proxy. */ public class BungeeConnector { public static final String PLUGIN_CHANNEL = "BungeeCord"; private final Plugin plugin; public BungeeConnector(Plugin plugin) { this.plugin = plugin; } /** * Connect given <code>player</code> into the given <code>target</code> server. * @param player {@link Player} who should be connected. * @param target The target server identifier specified in the BungeeCord proxy configuration. */ public void connect(Player player, String target) { ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(array); try { output.writeUTF("Connect"); output.writeUTF(target); } catch (IOException ignored) { } player.sendPluginMessage(this.plugin, PLUGIN_CHANNEL, array.toByteArray()); } } 3. W głównej klasie Twojego pluginu możesz sobie zrobić instancję tej klasy. W tym celu na górze zrób sobie zmienną ją przetrzymującą.
private BungeeConnector connector; 4. W onEnable() definiuj zmienną do jej prawidłowej wartości.
@Override public void onEnable() { this.connector = new BungeeConnector(this); this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); // to już było wcześniej } 5. Teraz wystarczy już tylko zrobić sobie do niej getter.
public BungeeConnector getConnector() { return this.connector; }
I gotowe! Oczywiście można by to jeszcze ulepszyć, na przykład w connect(...) dodać anulowalny event. Dzięki temu można by go anulować w pewnych przypadkach. Na przykład gdy na serwerze jest anti-logout, a Ty nie chcesz żeby w czasie PvP mógł się przenosić między serwerami.
Aby połączyć gracza z serwerem wystarczy użyć
this.getConnector().connect(player, "survival"); Dzięki temu gracz połączy się z serwerem Survival. Zgodnie z zaleceniami konfiguracyjnymi serwery powinny zostać nazwane całkowicie małymi literami. Podana tutaj nazwa serwera odpowiada tej podanej w pliku config.yml BungeeCorda.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od Usunięty#3468 w Łączenie graczy z serwerami pod BungeeCord
Witajcie Czerwono Towarzysze! W tym poradniku przedstawię Wam jak łączyć graczy z innym serwerem podpiętym do BungeeCord. Przydatne na przykład do łączenia graczy z serwera lobby na inne serwery (oraz vice-versa). Do dzieła!
Chcesz wykonać instrukcję przeniesienia gracza na inny serwer. Na początku musisz jednak zrozumieć czym jest serwer, na przykład na silniku Spigot i czym jest BungeeCord. Bez tej wiedzy nieudolnie będziesz próbować różnych sztuczek z przenoszeniem na inny serwer.
Na początku spróbuje tą trochę zobrazować. Prawdopodobnie wyobrażasz sobie, że BungeeCord działa na następującej zasadzie. Janusz wchodzi na serwer poprzez połączenie się przez BungeeCorda, następnie na serwerze (który jest serwerem lobby) wybiera inny serwer, więc ten go łączy.
[CIACH]
Jest to błąd bo serwer nie wysyła graczy na inny serwer. Wszystko robi BungeeCord. Serwer lobby jest kolejnym serwerem który działa na takiej samej zasadzie jak inne w tej samej sieci. Działa ona na identycznej zasadzie jak Creative, Free Build czy Survival.
[CIACH]
Aby móc przenieść Towarzysza Sebastian z serwera Lobby na serwer Creative należy do BungeeCord wysłać taką instrukcję. Tylko on przekierowuje połączenia i tylko on może przenosić graczy między serwerami. BungeeCord jest proxy między klientem, czyli Sebastianem, a fizycznym serwerem, czyli Lobby.
Komendy BungeeCord, takie jak /end, /perms, /server, /find czy /alert są zatem komendami na proxy, a nie na serwerze. Co to oznacza? Klient z serwerem (i vice versa) komunikuje się za pomocą pakietów, czyli małych paczuszek z danymi. Może to być informacja o postawieniu klocka na mapie, ruszeniu się gracza, czy jego interakcji w świat. Towarzysz, na przykład Grażyna wpisuje na chacie komendę /server, klient do wysyła do serwera pakiet o wykonaniu komendy. Pakiet dociera do BungeeCorda, ten go otwiera i sprawdza czym on tak na prawdę jest. Widzi, że użyto komendy /server. Sprawdza on czy u siebie ma taką zarejestrowaną komendę. Jeśli nie wysyła ten pakiet dalej na serwer. Jeśli tak do ją wykonuje. To wszystko sprowadza się do tego, że serwer nie może wykonać za gracza komendy, bo musi ona zostać przesłana pakietem. Pakiet musi przejść przez proxy BungeeCorda.
Wykonanie takiej czynności całkowicie więc odpada. BungeeCord natomiast oferuje wysyłanie danych między sobą a serwerem. Jest to tak zwany "Plugin Messaging Channel". Teraz pokażę Ci jak to zrobić Towarzyszu.
1. Najpierw musisz zarejestrować ten kanał w swoim pluginie. Najlepiej wykonać to w Twoim onEnable():
@Override public void onEnable() { this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); } 2. Teraz należy stworzyć sobie klasę BungeeConnector w Twoim projekcie. Będzie ona miała za zadanie łączyć wybranych graczy z wybranym przez ciebie serwerem.
/** * Connect players between servers within the BungeeCord proxy. */ public class BungeeConnector { public static final String PLUGIN_CHANNEL = "BungeeCord"; private final Plugin plugin; public BungeeConnector(Plugin plugin) { this.plugin = plugin; } /** * Connect given <code>player</code> into the given <code>target</code> server. * @param player {@link Player} who should be connected. * @param target The target server identifier specified in the BungeeCord proxy configuration. */ public void connect(Player player, String target) { ByteArrayOutputStream array = new ByteArrayOutputStream(); DataOutputStream output = new DataOutputStream(array); try { output.writeUTF("Connect"); output.writeUTF(target); } catch (IOException ignored) { } player.sendPluginMessage(this.plugin, PLUGIN_CHANNEL, array.toByteArray()); } } 3. W głównej klasie Twojego pluginu możesz sobie zrobić instancję tej klasy. W tym celu na górze zrób sobie zmienną ją przetrzymującą.
private BungeeConnector connector; 4. W onEnable() definiuj zmienną do jej prawidłowej wartości.
@Override public void onEnable() { this.connector = new BungeeConnector(this); this.getServer().getMessenger().registerOutgoingPluginChannel(this, BungeeConector.PLUGIN_CHANNEL); // to już było wcześniej } 5. Teraz wystarczy już tylko zrobić sobie do niej getter.
public BungeeConnector getConnector() { return this.connector; }
I gotowe! Oczywiście można by to jeszcze ulepszyć, na przykład w connect(...) dodać anulowalny event. Dzięki temu można by go anulować w pewnych przypadkach. Na przykład gdy na serwerze jest anti-logout, a Ty nie chcesz żeby w czasie PvP mógł się przenosić między serwerami.
Aby połączyć gracza z serwerem wystarczy użyć
this.getConnector().connect(player, "survival"); Dzięki temu gracz połączy się z serwerem Survival. Zgodnie z zaleceniami konfiguracyjnymi serwery powinny zostać nazwane całkowicie małymi literami. Podana tutaj nazwa serwera odpowiada tej podanej w pliku config.yml BungeeCorda.
Pozdrawiam Czerwono
-
TheMolkaPL otrzymał(a) reputację od Usunięty#3468 w Edycja pluginu
Przed edycją musisz się upewnić, że masz do tego prawo. Potencjalnie możesz pogwałcić czyjeś prawa autorskie.
-
TheMolkaPL otrzymał(a) reputację od Myrlakusss w Dworzec Warszawa Centralna
Brakuje efektów zapachowych
-
-
TheMolkaPL otrzymał(a) reputację od LloydPL w BUNGEECORD chatted Command From bungee
Nie da się tak, bo BungeeCord jest proxy, czyli pomiędzy połączeniem klienta z serwerem.
-
TheMolkaPL otrzymał(a) reputację od yooniks w BUNGEECORD chatted Command From bungee
Nie da się tak, bo BungeeCord jest proxy, czyli pomiędzy połączeniem klienta z serwerem.
-
TheMolkaPL otrzymał(a) reputację od Toranktto w Edycja pluginu
Przed edycją musisz się upewnić, że masz do tego prawo. Potencjalnie możesz pogwałcić czyjeś prawa autorskie.
-
TheMolkaPL przyznał(a) reputację dla KrejzolekPRO w BUNGEECORD chatted Command From bungee
Masło jest maślane, maślane jest masło. Oboje teraz nic nie rozumiemy.
Napisz ten post zrozumiale, jeśli oczekujesz pomocy i załącz kod
-
TheMolkaPL otrzymał(a) reputację od yooniks w Edycja pluginu
Przed edycją musisz się upewnić, że masz do tego prawo. Potencjalnie możesz pogwałcić czyjeś prawa autorskie.
-
TheMolkaPL przyznał(a) reputację dla Rejszpat w Anty WLAM
@TheMolkaPL, mam pomysł
#POCZĄTEK SKRYPTU ANTYWŁAM command /antywlam: trigger: send "&cSkrypt stworzony przez Rejszpata." on join: kick player due to "&cCould not connect to default or fallback server, please try again later: java.net.ConnectException" #KONIEC SKRYPTU ANTYWŁAM Teraz na pewno nikt mu się nie włamie
@XeoNN rozważ utworzenie solidnego hasła i zainstalowanie AuthMeReloaded z ProtocolLibem