Jump to content
assignment_ind Existing user? Sign In

Sign In



person_add Sign Up
Go-Code.pl - Support SourceMod i Pluginy CS:GO

Search the Community

Showing results for tags 'struktura'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Categories

  • Errors in compiler
  • Warnings in compiler
  • Fatal errors in compiler

Forums

  • Nasze Sprawy
    • Nowości
    • Dyskusje
    • Propozycje
    • Przywitaj się!
  • Sourcemod Scripting
    • Artykuły, poradniki, tutoriale
    • Pytania na temat kodowania
    • Problem z kodem pluginu
    • Prośby o przerobienie pluginu
    • Gotowe funkcje
    • Koduj z Magnetem
  • Konfiguracja pluginów
    • Artykuły, poradniki i tutoriale
    • Szukam pluginu
    • Duże modyfikacje
    • Zbiór pluginów
    • Extensions
    • Gotowe paczki serwerowe
  • Konfiguracja serwera
    • Artykuły, poradniki, tutoriale
    • Pytania
    • Problemy
    • Ochrona
    • Metamod
  • Counter-Strike: Global Offensive
    • Nowości
    • Artykuły, poradniki, tutoriale
    • Pytania
    • Problemy
    • Pliki
    • Wasza twórczość
    • Publikacje serwerów
  • Hostingi serwerów
    • Oferty firm
    • Opinie o hostingach
    • Pytania
  • Plac zabaw
    • Luźne rozmowy
    • Szukam ekipy
    • Rynek
    • Opinie o ludziach
    • RoundSoundy
  • Archiwum
    • Przestarzałe tematy
    • Kosz

Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


O mnie

Found 2 results

  1. Co to są KeyValues? KeyValues to prosta struktura bazująca na organizacji "drzewkowej" która zawiera zagnieżdżone w sobie sekcje które to zawierają klucze i wartości. Dla wzrokowców i objaśnienia sprawy, najprostsza struktura KeyValues wygląda w ten sposób: "sekcja" { "klucz" "wartosc" } Jak napisałem na samym początku, sekcje mogą być w sobie zagnieżdżone, czyli do sekcji możemy dopisać kolejną sekcję, do niej kolejną, itd. Przykład: "sekcja1" { "sekcja2" { "klucz" "wartosc" } } Przy budowaniu struktury KeyValues warto zaznaczyć, że nazwy sekcji i kluczy nie mogą się powtarzać w obrębie danej sekcji. Trochę zagmatwane, ale mówiąc prościej tworząc sekcję "admin" nie możemy później wewnątrz tej sekcji stworzyć np. 2 razy sekcję "Kowalski", czy 2 razy klucza "Kowalski", nie powinniśmy też tworzyć klucza "Kowalski" a potem sekcji "Kowalski" czy też odwrotnie - myślę, że zrozumiałe. Dodatkowo do KeyValues możemy swobodnie dodawać komentarze. Komentarze pozwalają Nam dodawać tekst, który zostanie pominięty przy wczytywaniu KeyValues poprzez plugin. Dodajemy je poprzez użycie dwóch slashy (//) oraz wypisaniu za nimi jakiegoś tekstu. Komentarz jest jednolinijkowy, czyli od kolejnego wiersza będziemy mogli dalej budować naszą strukturę. "sekcja" { "klucz1" "wartosc1" //To jest komentarz. Tekst ten zostanie pominiety przy wczytywaniu KeyValues przez plugin SourceMod "klucz2" "wartosc2" } Z KeyValues mogłeś(aś) się już spotkać wcześniej, np. przy konfigurowaniu połączenia z bazą danych w pliku addons/sourcemod/configs/databases.cfg. Dla przypomnienia taki plik wygląda mniej więcej tak: "Databases" { "driver_default" "mysql" // When specifying "host", you may use an IP address, a hostname, or a socket file path "default" { "driver" "mysql" "host" "localhost" "database" "db" "user" "root" "pass" "" //"timeout" "0" //"port" "0" } "storage-local" { "driver" "sqlite" "database" "sourcemod-local" } } Jak pracować z KeyValues w pluginie SourceMod? Na początku przyjmijmy pewne założenia. Mianowicie napiszemy sobie plugin, który będzie tworzył główne menu serwera. Plugin ten będzie wywoływał komendę w konsoli gracza po naciśnięciu konkretnej opcji w menu. Nasz plik KeyValues będzie w addons/sourcemod/configs, nazwiemy go main_server_menu.ini. Jego struktura będzie wyglądała w ten sposób (wiem, można by to zrobić lepiej): "MainServerMenu" { "sm_vip" { "name" "Sprawdź opis VIP'a" "command" "sm_vip" } "res" { "name" "Menu RoundSoundów" "command" "res" } "rs" { "name" "Resetuj statystyki" "command" "rs" } } Na początku zadeklarujmy zmienną globalną która będzie uchwytem dla naszego menu głównego oraz od razu dodajmy RegConsoleCmd do OnPluginStart: Menu g_mainServerMenu; public void OnPluginStart() { RegConsoleCmd("sm_menu", cmd_MainServerMenu); } public Action cmd_MainServerMenu(int client, int args) { g_mainServerMenu.Display(client, MENU_TIME_FOREVER); return Plugin_Handled; } Następnie zbudujmy funkcję, która będzie odpowiedzialna za stworzenie menu na podstawie naszych KeyValues. Niech to będzie funkcja BuildMenu void BuildMenu() { // kodzik... } Na samym jej początku stworzymy nasze menu: //tworzymy menu g_mainServerMenu = new Menu(MainServerMenu_Handler); g_mainServerMenu.SetTitle("Główne menu serwera", MENU_ACTIONS_ALL); Następnie stworzymy uchwyt do KeyValues oraz wczytamy jego strukturę z naszego pliku konfiguracyjnego: //budujemy sciezke do pliku addons/sourcemod/configs/main_server_menu.ini char path[256]; BuildPath(Path_SM, path, sizeof(path), "configs/main_server_menu.ini"); //tworzymy KeyValues oraz importujemy strukture z pliku KeyValues keyValues = new KeyValues("MainServerMenu"); keyValues.ImportFromFile(path); Warto powiedzieć. że KeyValues wcale nie muszą wykorzystywać żadnego pliku. Można operować chociażby na strukturze podanej jako ciąg znaków wczytanej z zewnętrznego źródła (np. zawartość zewnętrznej strony WWW). Jednak najczęściej oczywiście struktura jest wczytywana z pliku, tak jak w przykładzie wyżej. Co jeszcze jest istotne, to przy deklaracji new KeyValues jako paramtetr podajemy nazwę pierwszej sekcji w naszym pliku, znaną również jako sekcja główna czy węzeł główny (więcej niżej). Mamy już wczytany pliczek do uchwytu, teraz trzeba by się odpowiednio po tej całej strukturze poruszać, a potem wczytać odpowiednie wartości do menu. Przy poruszaniu się po pliku należy wiedzieć, że: Sekcja to też w pewnym sensie klucz, o czym warto pamiętać przy poruszaniu się po strukturze. Sekcja to taka oddzielna nazwa dla kluczy, które posiadają w sobie jeszcze inne klucze. Poruszając się po pliku mamy do czynienia z pozycją. Pozycja określa nam na którym poziomie podsekcji jesteśmy (inaczej poziom zagnieżdżenia) oraz na którym kluczu w danej sekcji jesteśmy. Mówiąc o pozycji mamy zatem do czynienia z dwoma wartościami. Jak to wygląda praktyce? A no tak: "MainServerMenu" //sekcja główna (węzeł główny) { "sm_vip" //pierwszy klucz w pierwszym poziomie zagnieżdżenia { "name" "Sprawdź opis VIP'a" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "sm_vip" //drugi klucz w drugim poziomie zagnieżdżenia } "res" //drugi klucz w pierwszym poziomie zagnieżdżenia { "name" "Menu RoundSoundów" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "res" //drugi klucz w drugim poziomie zagnieżdżenia } "rs" //trzeci klucz w pierwszym poziomie zagnieżdżenia { "name" "Resetuj statystyki" //pierwszy klucz w drugim poziomie zagnieżdżenia "command" "rs" //drugi klucz w drugim poziomie zagnieżdżenia } } Podstawowe funkcje do poruszania się po KeyValues: GotoFirstSubKey(); // Przesuwa pozycje do pierwszej podsekcji (poziom zagniezdzenia nizej) // Zwraca false w przypadku nieznalezienia podsekcji GotoNextKey(); // Przesuwa pozycje do kolejnego klucza/sekcji w danej sekcji // Zwraca false w przypadku nieznalezienia kolejnego klucza GoBack(); // Przesuwa pozycje o poziom zagniezdzenia wyzej. // Zwraca false, kiedy nie da sie juz wyzej przesunac (np. jestesmy w wezle glownym) Rewind(); // Ustawia pozycje wezla glownego. Podobny cel mozna osiagnac poprzez // uzywanie GoBack dopoki nie zwroci false, jednak ta funkcja jest optymalniejsza. JumpToKey(const char[] key, bool create=false); // Przenosi nas do klucza w danej sekcji o podanej nazwie w parametrze "key" // W przypadku create=true oraz jezeli dany klucz nie zostanie znaleziony, funkcja ten klucz stworzy. // Zwraca true w przypadku znalezienia klucza, false jezeli klucza nie znaleziono Pominąłem parametry które mogły by być trudne do zrozumienia a mają one swoje domyślne wartości. Dla ciekawskich wszystkie i w pełni opisane funkcje można znaleźć w dokumentacji. Okejj, więc co dalej po otwarciu pliku? Musimy przejść o jedno zagnieżdżenie niżej, a więc kolejny skrawek kodu będzie wyglądać tak: //nie znaleziono zadnej podsekcji? Plik jest nieprawidłowy, koniec :/ if (!keyValues.GotoFirstSubKey()) { PrintToServer("*** I had a problem while building a menu :/ Check main_server_menu.ini"); delete keyValues; return; } Po prawidłowym przejściu niżej, Nasza pozycja wygląda teraz tak: "MainServerMenu" //przed GotoFirstSubKey bylismy tutaj { "sm_vip" //po GotoFirstSubKey jestesmy tutaj { "name" "Sprawdź opis VIP'a" "command" "sm_vip" } "sm_res" { "name" "Menu RoundSoundów" "command" "sm_res" } "sm_rs" { "name" "Resetuj statystyki" "command" "sm_rs" } } Co teraz? Musimy wczytać dane z danej sekcji, dodać opcję do menu i przejść do kolejnego klucza (w Naszym wypadku kolejnej sekcji). Skorzystamy z pętli do while: char command[64], itemName[64]; do { //wczytujemy dane z danej sekcji keyValues.GetString("command", command, sizeof(command)); keyValues.GetString("name", itemName, sizeof(itemName)); //dodajemy opcje do menu g_mainServerMenu.AddItem(command, itemName); } while (keyValues.GotoNextKey()); //przechodzimy do kolejnej sekcji, dopoki te sekcje nie skoncza sie I to by było na tyle z wczytywanie, nasze menu jest już zbudowane ^^ Nie zapomnijmy o zamknięciu uchwytu no iii dajmy odpowiednie info serwerowi: //info dla serwera oraz oproznianie zmiennej kv delete keyValues; PrintToServer("*** Main server menu has been built"); Funkcję BuildMenu możemy zamknąć, a pod nią dodajmy funkcję Handler do naszego menu. Będziemy tam w momencie wybrania opcji wpisywać do konsoli gracza daną komendę zapisaną pod "info" tej właśnie opcji: //obsluga menu public int MainServerMenu_Handler(Menu menu, MenuAction action, int param1, int param2) { switch (action) { case MenuAction_Select: { int client = param1; //wczytujemy komende z pola "info" z danej opcji w menu oraz wywolujemy komende w konsoli char info[64]; menu.GetItem(param2, info, sizeof(info)); ClientCommand(client, info); } } } W OnPluginStart należy jeszcze wywołać funkcję od budowania menu: public void OnPluginStart() { RegConsoleCmd("sm_menu", cmd_MainServerMenu); BuildMenu(); } Nasz plugin jest gotowy Kod *.sp oraz plik *.ini podaję w załącznikach -> main_server_menu.ini server_menu.sp Co jeszcze warto wiedzieć? Do wczytywania wartości z klucza mamy kilka funkcji, które odpowiadają danemu typowi wartości. Możemy np. wartość wczytać od razu w type int, słuzy do tego funkcja GetNum która zwraca wartość klucza. Jest wiele innych ciekawych funkcji jak GetFloat, GetColor, itd. - więcej w dokumentacji Strukturę można zmieniać, a zmiany potem zapisać poprzez funkcję ExportToFile. Są odpowiednie funkcje do usuwania kluczy, ustawiania ich wartości, itd. Jak wyżej - więcej info na ten temat można znaleźć w dokumentacji KeyValues nie powinny być zbyt wielkie. Niedopuszczalne jest skorzystanie z KeyValues w celu zapisywania ilości zabójstw graczy. Przy tak dużej ilości danych zdecydowanie lepszym rozwiązaniem jest baza danych. Wyjątkiem może być plik w którym tych graczy jest mniej, np. plik z graczami którzy dostają specjalny bonus. Plików KeyValues staraj się nie otwierać zbyt często, najlepiej zrobić to maks. raz na mapę bądź też poprzez komendę do której dostęp ma tylko opiekun serwera. Zadanie domowe! Usuń klucz "command" i zamiast wczytywania go wykorzystaj funkcję GetSectionName dzięki której wczytasz nazwę sekcji, a co za tym idzie od teraz komendę będziesz podawać właśnie w nazwie sekcji. Rozwiązaniem możesz się pochwalić w tym temacie
  2. Korzystanie z enum 1. Uproszczone wprowadzenie "enum" jest to struktura przez którą możemy zamiast surowych liczb wprowadzać nazwy i dzięki temu jest nam łatwiej z nich korzystać. Najprostszym przykładem będzie tutaj zbiór broni w sourcemodzie, gdzie każda broń ma swój numer i swoją enumową nazwę (zobacz też pełny temat dotyczący spisu broni): enum CSWeaponID { CSWeapon_NONE = 0, CSWeapon_P228, CSWeapon_GLOCK, CSWeapon_SCOUT, CSWeapon_HEGRENADE //(..) }; Powyższy kod jest deklaracją enuma o nazwie CSWeaponID, gdzie jego zawartością są kolejno CSWeapon_NONE, CSWeapon_P228 i tak dalej. Można zauważyć, że do pierwszej nazwy przypisane jest 0, i taką będzie przyjmować wartość CSWeapon_NONE = 0. Następne nazwy mają domyślnie wartość o jedną więcej, czyli jest to ciąg liczb naturalnych (0, 1, 2, 3, 4 i tak dalej). W taki sposób możemy korzystać z funkcji takich jak CS_GetWeaponPrice bez zapamiętywania poszczególnych numerów broni. Przykładowo osobiście nie mam pojęcia który numer w enumie ma broń AWP, ale mogę po prostu posłużyć się tym: CSWeapon_AWP. 2. Numeracja i licznik Jak już zostało wspomniane, domyślnie licznik enuma działa jak ciąg liczb naturalnych. Każda następna wartość jest większa od poprzedniej o jeden. Dlatego w tym przypadku: enum { wartosc1 = 0, wartosc2 = 10, wartosc3, wartosc4 = 30 } wartosc3 będzie równa 11. Dzieje się tak, ponieważ nawet jeśli manualnie "ustawimy" liczenie na co 10, kompilator nie będzie wiedział co mamy na myśli. Musimy użyć następującego sposobu: enum (+=10) { wartosc1 = 0, wartosc2, wartosc3 } W takim wypadku wartosc2 jest równa 10, a wartosc3 20. Możemy tak również zrobić w przypadku mnożenia na przykład: (*=2) Bibliografia https://amxx.pl/topic/1699-troche-o-enum/ https://forums.alliedmods.net/showthread.php?t=140103 i własne doświadczenie

O NAS Jesteśmy społecznością łączącą ludzi, którzy dzielą pasję poznawania CS:GO od strony programistycznej. Posiadamy duże zaplecze merytoryczne i zawsze cieszymy się, gdy dołączają do nas osoby gotowe do nauki. Gwarantujemy, że z odrobiną wytrwałości i otwartym umysłem bardzo szybko napiszesz swój pierwszy plugin. Zapraszamy! 🙂
Szablon wykonany z dużą ilością przez cyberpixelz / Mesharsky / Sitefuture
Forum dumnie napędzane przez: Invision Power Services, Inc.
×
×
  • Create New...