Jump to content
  • Chmurka
  • Boróweczka
  • Jabłuszko
  • Limonka
  • Czekoladka
  • Węgielek

Search the Community

Showing results for tags 'artykuł'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


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 10 results

  1. Usuwanie niepotrzebnego, zbędnego kodu z naszego projektu jest istotnym elementem dobrej opieki nad nim. Ale są ludzie, którzy powiedzą "Hej! Panie! Ja tu się namęczyłem z pisaniem tego kodu i NIE MA OPCJI żebym go teraz kasował nawet jeśli już go nie używam". Ten artykuł ma wszystkich upartych przekonać, dlaczego martwy kod trzeba zakopywać głęboko klawiszem backspace. Nad projektem może pracować więcej niż jedna osoba. A jeśli produkujesz oprogramowanie open-source, to kod będzie przeglądać o wiele więcej ludzi niż Twój zespół programistyczny. Jak dobrze wiemy kod jest przede wszystkim komunikacją między programistami, a to, że działa i spełnia swoje zadania jest sprawą drugorzędną. Obca osoba czytając martwy kod musi poświęcić dwa razy więcej czasu niż w przypadku kodu który jest w użytku ponieważ a) Musi zrozumieć jak działa b) Musi zrozumieć dlaczego ten kod nie jest używany i czy na pewno nie jest nigdzie używany i może go usunąć; Za każdym razem przeglądając kod po raz dziesiąty czy setny, ktoś spędzi dłuuugie sekundy myśląc sobie "ah, to tu jest martwy kod, moje oczy muszą go ominąć". Taki kod to po prostu hałas dla oczu. Niepotrzebny żwir na naszym asfalcie. Dlaczego na naszym płaskim, idealnym asfalcie jest wysypany żwir? To na pewno nie jest sposób w jaki chcemy produkować a tym bardziej przeglądać kod; Martwy kod jest martwy. Nie jest rozwijany. Został pozostawiony sam sobie kilka, kilkadziesiąt, kilkaset iteracji temu. Programista może użyć go bez wiedzy, że jest martwy. "Jest tam, więc czemu miałby być źle napisany?" Otóż nierozwijany kod zostawiony sam sobie może już nie spełniać obecnych standardów projektu, lub nawet jego autor mógł go nie dokończyć. Wtedy przy jego użyciu mogą wystąpić konsekwencje - bugi Jeśli używasz jakiegokolwiek systemu kontroli wersji kodu i to na Ciebie spada odpowiedzialność za utrzymanie i konserwację kodu (zachowując jednocześnie martwy kod w projekcie), to masz więcej linii kodu do przejrzenia, więcej odpowiedzialności na Twoich barkach oraz większe pole do popisu dla błędów w zarządzaniu kodem Konsekwencją chomikowania martwego kodu jest to, że ten kod się kumuluje. Normalnie, zachowuje się tylko najpotrzebniejsze rzeczy, tylko rzeczy używane, tylko rzeczy które spełniają jakąś rolę w naszym programie. Dlatego opiekujemy się nim, optymalizujemy go, refaktorujemy. W przeciwieństwie do martwego kodu. Ten, kumuluje się i zbiera, rosnąc diametralnie, a swoim rozmiarem zniechęca maksymalnie kogokolwiek, żeby zrobił co trzeba - przejrzał jeszcze raz kod, zrozumiał go i wyrzucił do kosza Nie martw się, że kod który napisałeś zostanie skasowany, bo nie jest już potrzebny. W dzisiejszych czasach praktycznie zawsze używa się systemu kontroli wersji (np. GIT). Twój kod, który kiedyś w swojej świetności działał idealnie, jest zakopany gdzieś w commitach. Nie ma powodu żeby za nim płakać. Z czasem, szansa na ponowne użycie nieużywanego kodu maleje. Nie musisz go trzymać w każdej iteracji. Odpuść, zrób przysługę sobie w przyszłości i skasuj go. Jeśli był naprawdę ważny i kiedyś zdarzy się sytuacja, gdzie będziesz potrzebował tego kodu, odkopiesz go z czeluści GITa. Tutaj widzę dobrą okazję na przedstawienie jednej z reguły tworzenia oprogramowania w trybie extreme programming: YAGNI (ang. You aren't gonna need it). Mówi nam ona o tym, że mamy pisać tylko i wyłącznie funkcjonalności których potrzebujemy teraz. Nie mamy przewidywać jakich funkcjonalności będziemy potrzebować. Skupiamy się na chwili obecnej. Można to też interpretować w drugą stronę - jeśli czegoś już nie potrzebujesz to skasuj to natychmiast Bibliografia https://stackoverflow.com/questions/15699995/why-unused-code-should-be-deleted https://en.wikipedia.org/wiki/You_aren't_gonna_need_it https://www.infoq.com/news/2017/02/dead-code/
  2. Na prośbę jednego z użytkowników poniżej umieszczam rozpiskę i przykłady zastosowania tekstu w hint i hud. HudText Tekst, który jest wyświetlany bezpośrednio na ekranie gracza. Tekst, który nie jest ani w menu, ani w żadnym z okienek dialogowych. To jest właśnie tzw HudText. Istnieją co najmniej dwa sposoby wyświetlania takiego tekstu. Skupimy się na funkcji ShowHudText, która zawsze idzie w parze z funkcją SetHudTextParams, lub SetHudTextParamsEx. Różnica między tymi dwiema polega na tym, że w pierwszej z nich określamy jeden zestaw kolorów, a w drugiej dwa. Nie będę się w to zagłębiał, bo przyznam szczerze że z drugiej funkcji nie korzystałem bodajże nigdy, więc nie czuję się w tym obszarze ekspertem. W kodzie wygląda to tak, że najpierw należy określić parametry tekstu, a potem można go wyświetlić. Używając wcześniej wspomnianej funkcji SetHudTextParams możemy określić położenie na osiach X i Y, czas wyświetlania tekstu, kolor wraz z alfą i efekt (fade in/out z czasem zanikania). Śmiało mogę powiedzieć, że odpowiednie ustawienie tekstu nierzadko wymaga nakładu pracy. Mamy do czynienia z różnymi rozdzielczościami ekranów graczy, i tylko środek pozostanie środkiem. Dla przykładu - mnie interesuje tekst, który docelowo ma zostać wyświetlony w górnym lewym rogu ekranu. Nie ma mieć żadnego efektu, ma być zielony i w lekko przezroczysty. SetHudTextParams(0.01, 0.20, 0.2, 0, 255, 0, 140); ShowHudText(client, -1, "ŁADUNKI : %i", ilosc_min_gracza[client]); Po ustaleniu parametrów, funkcją ShowHudText wyświetlamy tekst klientowi, na kanale -1 = kanale poprzednio używanym, bądź najprawopodobniej randomowym przy pierwszym użyciu. Trzecim argumentem jest właśnie tekst - może to być wcześniej Formatowany string, może to być tekst w cudzysłowie. Argumenty wypisujemy po przecinku w odpowiedniej kolejności, dokładnie jak w przypadku np funkcji PrintToChat. Przykład zastosowania kodu w timerze, którzy wyświetla tekst zawierający zabójstwa gracza w różnych kolorach, zależnie od ich ilości. Przy śmierci gracza resetujemy te wartości. Hint text Tekst, który jest wyświetlany w okienku z informacją np przy rozbrajaniu bomby. W tej sytuacji sprawa wygląda nieco inaczej, bo mimo używania tylko jednej funkcji możemy kolorować bądź zmieniać wielkość liter używając HTML. Przykład użycia znajdziemy m.in w codmodzie. Wygląda groźnie? To złudzenie. Pierwszym argumentem jest index klienta, któremu wyświetlamy tekst. Jeśli chcemy wyświetlić go wszystkim, użyjemy funkcji PrintHintTextToAll. W tym wypadku nie umieszczamy żadnego ID. Treść zostanie wyświetlona wszystkim. Wracając - po indexie klienta umieszczamy stringa - albo formatowanego tak jak w przypadku HudTextu, albo w cudzysłowie. Możemy również używać \n, czyli skoku linijkę w dół. Co tu dużo mówić, zwyczajny tekst - z tym że formatowanie polega na używaniu HTML, a argumenty wciskane są tak jak w przypadku PrintToChat, i implementowane po cudzysłowie w odpowiedniej kolejności. Nic trudnego, spróbujcie sami 🙂 Co do HudText'u - bardzo pomocnym może okazać się plugin naszego kolegi z forum, @Master. Dzięki temu pluginowi w dość prosty sposób jesteśmy w stanie określić położenie i kolor HUD tekstu, który chcemy wyświetlić. Bardzo polecam to rozwiązanie. W razie pytań piszcie, bo trzasnąłem to dość na szybko i jestem delikatnie zmęczony, ale chciałem dotrzymać słowa i chyba mi się udało 😛
  3. W poradniku podlinkowanym wyżej, znajdziecie informacje na temat samego tłumaczenia, niejako wykorzystywania już gotowych plików *.phrases.txt znajdujących się w folderze addons/sourcemod/translations/ Ja chciałbym zwrócić uwagę na problem od strony kodowania. Jak umieścić tłumaczenie w pluginie, jak doprowadzić do tego, by plugin wczytał nam plik z tłumaczeniem, który mu przygotujemy? Jak zakodować różne komunikaty, z różnymi zmiennymi? Sprawdźmy to! (xd) Całość omówimy na przykładzie pluginu, który losuje dwie osoby na mapkę i daje im flagę "a". No i OK. Zacznijmy od początku. 1. Poinformuj plugin o pliku z tłumaczeniem. W tym celu w funkcji startupu pluginu (OnPluginStart) należy załadować translacje. Użyjemy do tego funkcji LoadTranslations. W naszym przypadku będzie to wyglądało w ten sposób : public void OnPluginStart() { LoadTranslations("free-vip.phrases"); } 2. Napisz funkcję wyświetlającą tekst pobierany z pliku *.phrases.txt Pierwszym i jednocześnie dość istotnym krokiem w tym miejscu będzie zdanie sobie sprawy, że istnieją dwie możliwości zaimplementowania tłumaczenia w kodzie. %t - użyjemy, gdy wyświetlany tekst będzie bezpośrednio do gracza, przykładowo przez funkcję PrintToChat. %T - tego dziada użyjemy, gdy funkcja nie będzie bezpośrednio kierowana do gracza, a do serwera, zatem PrintToServer, LogMessage czy Format zawierający tłumaczenie musi być napisany w tej formie. Ważnym jest, żeby zaznaczyć w kodzie, jakiego języka mamy użyć do translacji. LANG_SERVER - funkcja użyje języka serwera. client(indeks klienta) - w wypadku, gdybyśmy używali przykładowo funkcji Format w celu podstawienia stringa do nazwy menu, funkcja użyje języka klienta. W naszym przykładzie skupimy się na funkcji PrintToChat, bo występuje ona dwa razy, i jako jedyna wyświetla tekst. Jak widać, pierwsza funkcja najpierw wyświetli zdefiniowany na początku pluginu prefiks, potem tekst i dwie zmienne. %N odpowiada za nazwę klienta, którego ID podaliśmy w argumentach za prefiksem. Druga funkcja wyświetli tylko prefiks i tekst. Jako, że prefiks jest zdefiniowany i jest stały, pominiemy go w tłumaczeniu. 3. Stwórz plik z tłumaczeniem Na tym etapie zajmiemy się stworzeniem pliku tekstowego, którego nazwa będzie odpowiadała tej, którą zaznaczyliśmy w naszym pluginie na jego początku. Zatem - tworzymy plik free-vip.phrases.txt, a w nim: "Phrases" //ZAWSZE "Phrases"! { "Gratulacje" { "#format" "{1:N},{2:N}" //ustalamy w odpowiedniej kolejności typy zmiennych, które implementujemy w argumentach funkcji wyświetlającej tekst "en" "Congratz! This map VIP players are: {1} and {2}!" //tłumaczenie dla języka angielskiego "pl" "Gratulacje! VIP'ami na tej mapie zostali: {1} oraz {2}!" //tłumaczenie dla języka polskiego } "Losowanie odroczone" { //tutaj nie trzeba nic formatować, bo nie mamy żadnych zmiennych, więc przechodzimy od razu do tłumaczeń "en" "The draw of 2 free VIPs will be denied. The attempt will be renewed in 20 seconds!" //tłumaczenie dla języka angielskiego "pl" "Losowanie 2 darmowych VIP'ów nie może się teraz odbyć. Próba zostanie ponowiona za 20 sekund!" //tłumaczenie dla języka polskiego } } Plik należy umieścić w folderze addons/sourcemod/translations/ Inne typy zmiennych w "#format" : {1:d},{2:x},{3:f},{4:s},{5:c},{6:t} d lub i : wyświetli liczbę, cyfrę x : wyświetli zmienną w systemie szesnastkowym f : wyświetli zmienną typu float s : wyświetli zmienną typu string c : wyświetli jeden znak (UTF-8) t : służy do załączania kolejnej translacji
  4. Sourcemod oferuje nam bardzo wygodny system językowy, dzięki któremu jeden plugin może posiadać nieskończoną ilość wersji językowych, a wyświetlany język w danej chwili jest zależny od ustawienia serwera. Jednakże to, czy plugin będzie z tego korzystał, zależny tylko i wyłącznie od programisty. Ale niezależnie, czy umiesz programować czy nie, tłumaczenie pluginów jest proste i przyjemne. Jeśli plugin posiada wyżej wymienioną opcję to w paczce w której go pobrałeś powinien znajdować się folder /translations/ a w nim plik językowy z rozszerzeniem .phrases.txt. Jego zawartość jak w każdym pluginie wygląda podobnie: "Phrases" { "Bideo_Game_Dunky" { "en" "i will see you grandpa" "jp" "おじいちゃんに会いましょう" /* tutaj dalsze linie z kodem */ } "Im_Done_With_League_Of_Legends" { "en" "not even close baby" "jp" "赤ちゃんも閉じない" /* tutaj dalsze linie z kodem */ } } Nad pierwszymi klamrami znajduje się słowo kluczowe "Phrases", które mówi pluginowi "hej, to ja jestem ten plik od tłumaczeń". W dalszych blokach możemy zauważyć takie bloki { } jak "Bideo_Game_Dunky" oraz "Im_Done_With_League_Of_Legends". Dla tłumacza, czyli w naszym wypadku nie mają one absolutnie żadnego znaczenia i nie możemy ich zmieniać, ponieważ są one zastosowane jako zmienne w pluginie i ich zmiana tylko zepsułaby tłumaczenie. Dalej, między klamrami { } są już właściwe tłumaczenia, każdy język znajduje się w osobnej linii a format tłumaczenia frazy jest następujący: "kod_kraju" "tłumaczenie" Kod naszego kraju to oczywiście "pl". A więc wystarczy że dopiszemy następujące linie do pliku w ten sposób: "Phrases" { "Bideo_Game_Dunky" { "en" "i will see you grandpa" "jp" "おじいちゃんに会いましょう" "pl" "zobaczę cię dziadku" /* tutaj dalsze linie z kodem */ } "Im_Done_With_League_Of_Legends" { "en" "not even close baby" "jp" "赤ちゃんも閉じない" "pl" "nawet nie blisko dziecko" /* tutaj dalsze linie z kodem */ } } Zapisujemy plik, wgrywamy na miejsce jego oryginału, ustawiamy język serwera na polski i mamy przetłumaczony plugin! Aby zobaczyć jak wygląda normalny plik ze spolszczeniem możecie zajrzec do pluginu runda nożowa. Miłego tłumaczenia! PS. Pojawił się poradnik jak tłumaczyć pliki "solo", które nie posiadają *.phrases.txt. Link:
  5. DataPacki Przeważnie podczas tworzenia funkcji definiujemy pożądaną liczbę parametrów, którą chcemy użyć. Przykład: int Mnozenie(int a, int b) { return a * b; } /////////////// void JakasFunkcja() { PrintToChatAll("5x6 = %d", Mnozenie(5,6)); } Aby zrobić tutaj użytek z funkcji Mnozenie() konieczne było przekazanie dwóch argumentów. Niestety, w niektórych sytuacjach nie mamy komfortu przekazywania dowolnej ilości argumentów - jesteśmy ograniczeni tylko do...jednego! Dotyczy to chociażby asynchronicznych zapytać SQL lub timerów. Przykład: void JakasFunkcja(int client) { int a = 5; int b = 6; CreateTimer(10.0, PomnozCosPozniej, /*TUTAJ TYLKO JEDEN ARGUMENT!*/); } public Action PomnozCosPozniej(Handle timer, any data) { /// co tu zrobic ?! } Gdybyśmy chcieli wykonać operację mnożenia w tym przypadku, niezbędne jest przekazanie dwóch zmiennych. Co robić w takiej sytuacji? Z pomocą przychodzą nam DataPacki! Umożliwiają nam one "upakowanie" dowolnej liczby zmiennych o dowolnym typie do jednego ciągu danych. Cały proces zaczyna się od stworzenia uchwytu do DataPacka: DataPack data = new DataPack(); jesteśmy gotowi do załadowania go danymi. Do tego celu wykorzystuje się kolejno WriteCell, WriteFloat, WriteFunction, WriteString W naszym przykładzie poza dwiema zmiennymi przekażemy dodatkowo komunikat do wyświetlenia, aby pokazać jak posługiwać się ciągami znaków. Nasza funkcja będzie teraz wyglądać tak: void JakasFunkcja(int client) { char helloString[128]; Format(helloString, sizeof(helloString), "Siemanko %N!", client); DataPack data = new DataPack(); data.WriteCell(5); data.WriteString(helloString); data.WriteCell(6); CreateTimer(10.0, PomnozCosPozniej, data); } Celowo umieściłem stringa pomiędzy dwiema liczbami, aby pokazać, że odczyt jest odrobinę bardziej skomplikowany niż zapis. Po pierwsze, każdy DataPack posiada swój specjalny wskaźnik, który pokazuje w którym miejscu ma być przeprowadzany odczyt/zapis. Przeanalizujmy proces zapisu informacji w naszej funkcji JakasFunkcja(int client). Po stworzeniu DataPacka mamy pustą strukturę i wskaźnik znajdujący się na początku: [|] Znak '|' to właśnie nasz wskaźnik Po wywołaniu żądania umieszczenia piątki, proces zaczął się w miejscu gdzie stał nasz wskaźnik - czyli na samym początku: [5|] Po dodaniu inta, wskaźnik przesunął się (troche jak wskaźnik podczas pisania na klawiaturze) Kolejny w kolejce jest string: [5string|] I ostatnia już wartość - 6: [5string6|] W tym miejscu mamy już przygotowanego do wysyłki DataPacka. Zauważmy jednak, że nasz wskaźnik nie zmienił swojej pozycji - jest cały czas ustawiony na końcu struktury. Czy domyślacie się, jak wyglądałby odczyt tych danych? Bez przesunięcia wskaźnika na początek pliku ten proces jest niemożliwy... Na szczęście, istnieje operacja, która może tego dokonać. Nazywa się ona Reset: // zauważmy, że drugi argument funkcji zmienił się na nasz DataPack :) public Action PomnozCosPozniej(Handle timer, DataPack data) { data.Reset(); } Od tego momentu struktura DataPacka wygląda tak: [|5string6] Oznacza to, że jesteśmy gotowi do odczytu ? Istnieje jednak jeszcze jeden haczyk. Wspomniałem wcześniej, że dane w DataPacku przyjmują forme ciągu danych. Oznacza to, że SourceMod widzi je jako swoisty strumień. Właśnie do nas należy zadanie zapanowania nad tym haosem. Do odczytywania danych stosujemy kolejno ReadCell, ReadFloat, ReadFunction i ReadString. W naszym DataPacku nie możemy zacząć wyciągania od np. stringa - wszystko musimy wykonywać w takiej samej kolejności, w jakiej wkładaliśmy dane! Na pierwszy ogień pójdzie więc 5, następnie komunikat, a na samym końcu - 6. A więc pierwszą wartością jest int. Korzystamy z ReadCell: // zauważmy, że drugi argument funkcji zmienił się na nasz DataPack :) public Action PomnozCosPozniej(Handle timer, DataPack data) { data.Reset(); int a = data.ReadCell(); } // Aktualny stan DataPacka: [5|string6] Przyszła pora na stringa. W naszym przypadku nasz łańcuch składa się z 128 znaków i dokładnie tyle zapisaliśmy w DataPacku! Pamiętajmy więc o przygotowaniu odpowiednio dużej tablicy: char helloString[256]; // wielkość tablicy do której zapisujemy może się różnić - ważne, abyśmy pamiętali ile znaków zapisaliśmy WCZEŚNIEJ! data.ReadString(helloString, sizeof(helloString)); I na sam koniec ostatnia liczba: int b = data.ReadCell(); Gotowe! Wszystkie dane zostały pobrane prawidłowo. Nasz efekt końcowy: void JakasFunkcja(int client) { char helloString[128]; Format(helloString, sizeof(helloString), "Siemanko %N!", client); DataPack data = new DataPack(); data.WriteCell(5); data.WriteString(helloString); data.WriteCell(6); CreateTimer(10.0, PomnozCosPozniej, data); } public Action PomnozCosPozniej(Handle timer, DataPack data) { char helloString[256]; data.Reset(); int a = data.ReadCell(); data.ReadString(helloString, sizeof(helloString)); int b = data.ReadCell(); PrintToChatAll("Komunikat: %s", helloString); PrintToChatAll("%d x %d = %d", a, b, a*b); } // stan DataPacka: [5string6|] Oczywiście w razie pojawienia się pytań bądź wątpliwości zapraszam do dyskusji pod spodem ? PS: suplementem do tego materiału jest napisany przez @Vasto_Lorde poradnik o timerach:
  6. Jeżeli spędziłeś już trochę czasu na programowaniu w pawnie, na pewno natknąłeś się na funkcje, które pobierają dane z innych pluginów, np. cod_get_user_class, które zwróci ID postaci, na której aktualnie gramy. Warto zauważyć, że owe informacje wychodzą bezpośrednio z silnika cod moda - następuje więc tutaj bezpośrednia wymiana informacji pomiędzy pluginami. W tym poradniku zajmiemy się po krótce tym zagadnieniem. 1. Funkcje natywne Działanie "natywów" sprowadza się do zdalnego wywołania funkcji i ewentualnego zwrócenia rezultatu: 0 - Nasz plugin posiada funkcję natywną szarego pluginu I - zlecamy wykonanie funkcji II - szary plugin wykonuje polecenie III - szary plugin zwraca otrzymany rezultat IV - rezultat trafia do naszego pluginu Teraz pokażę jak takiego natywa z szarego pluginu stworzyć. Przede wszystkim natywy dodajemy w takiej funkcji: public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) Daje nam to pewność, że załadują się one w odpowiedniej chwili. Warto wspomnieć, że natywy możemy wczytywać pojedynczo, bądź jako biblioteka - tworzyć nasze własne pliki #include. W tym poradniku skupię się tylko na tej drugiej metodzie. Musimy więc najpierw zarejestrować naszą bibliotekę: RegPluginLibrary("NaszaNazwa"); następnie dodajemy natywy w następujący sposób: CreateNative("nazwa_natywu", Funkcja_Ktora_Ma_Sie_Wywolac); na samym końcu zwracamy: return APLRes_Success; Teraz pora na Funkcja_Ktora_Ma_Sie_Wywolac. Natywy pozwalają nam również na bezproblemowe przekazywanie argumentów, jednak funkcja, o której przed chwilą wspomniałem, nie może po prostu tych argumentów przyjmować w nawiasach () - działa to w trochę inny sposób: public int Funkcja_Ktora_Ma_Sie_Wykonac(Handle plugin, int numParams) { int liczba = GetNativeCell(1); return liczba * 2; } po pierwsze, argumenty muszą być takie, jak wyżej - Handle plugin (uchwyt to NASZEGO pluginu), a także numParams (ilość parametrów, które przekazaliśmy) Pobieranie argumentów odbywa się poprzez specjalne funkcje GetNative___ (polecam po prostu wpisać sobie "getnative" a także "setnative" w dokumentacji). Każdorazowo pierwszy argument GetNative__ to numer argumentu z naszego wywołania (wyjątkowo numerujemy tutaj od 1!) W przykładzie powyżej założyłem, że przekazany zostanie jedynie int, który zostanie przemnożony przez 2 i zwrócony. Przykładowe zastosowanie: Pamiętajmy jednak, że ciągle nie stworzyliśmy biblioteki GoCode! Będzie ona wyglądać mniej więcej tak: Tak przygotowany plik możemy zapisać jako GoCode.inc i wrzucić do naszego folderu include w kompilatorze. Koniec ? 2. Forwardy (coming soon)
  7. Czasami zdarza się, że nie mamy pojęcia z jakimi ilościami elementów będziemy mieli do czynienia (np. ile klas w CodMod'ie musimy załadować do pamięci). I owszem, możemy wówczas sprowadzić to do prostego ograniczenia, np.: #define MAX_ILOSC_KLAS 100 int ClassID[MAX_ILOSC_KLAS]; //... Niestety, rodzi to dwa zasadnicze problemy: 1. Jeśli aktualnie nie wykorzystujemy całej zaalokowanej pamięci, marnujemy bez potrzeby miejsce 2. Zawsze jesteśmy ograniczeni przez limit, który sami na siebie nałożyliśmy Rozwiązaniem naszego problemu są tablice dynamiczne Mimo, że działają one nieco wolniej od zwykłych tablic, pozwalają na całkowicie dynamiczną alokację pamięci - oznacza to, że w trakcie trwania programu możemy dowolnie manipulować ilością zarezerwowanej pamięci - zarówno alokując, jak i zwalniając zasoby Korzystanie z nich jest naprawdę proste i wymaga jedynie odrobinę wprawy Na samym początku tworzymy uchwyt (najczęściej globalnie): ArrayList MojUchwyt Do poprawnego działania konieczne jest jeszcze jego zainicjowanie - bez tego niemożliwe jest jego działanie, a serwer będzie sypał errorami. Najczęściej piszemy w OnPluginStart: MojUchwyt = CreateArray(block_size, init_size) Teraz omówię parametry block_size oraz init_size, posługując się strukturą tablicy dynamicznej. Możemy sobie ją przyrównać do takiej oto szafeczki: block_size mówi nam ile komórek zarezerwowanych jest dla jednego poziomu. Wartość raz tam podana pozostanie niezmienna dla danej tablicy (chyba, że użyjemy ResizeArray). Na naszym przykładzie dla każdego poziomu zarezerwowane zostaną 3 komórki. init_size określa ile poziomów zostanie zaalokowane na samym początku. Jego wartość ulega zmianie na przestrzeni trwania programu. Nasza szafeczka ma na start zaalokowane 12 poziomów, jednak w praktyce tego parametru najczęścieć nie stosuje się wogóle - wówczas na starcie nie ma żadnego poziomu i zostaną one dodane dopiero później. Jaką wartość podawać w block_size? Jeżeli wiemy, że w danej tablicy umieszczone zostaną jakieś ciągi znaków, które de facto wymagają więcej niż jednej komórki, wówczas podajemy tam wartość, która pozwoli na zapewnienie odpowiedniej ilości miejsca. Przykładowa inicjalizacja tablicy na imiona graczy może wyglądać na przykład tak: MojUchwyt = CreateArray(MAX_NAME_LENGTH+1) Z wykorzystaniem methodmap: MojUchwyt = new ArrayList(MAX_NAME_LENGTH+1); Polecenie zainicjuje pustą tablicę, która będzie posiadała na każdym poziomie ilość komórek równą wartość stałej MAX_NAME_LENGTH + 1 Niedobrze jest ograniczać się do konkretnych ilości danych (np. klas), jednak już dobrą praktyką jest ograniczanie dopuszczalnej ilości znaków, jak w przypadku limitu w nazwie gracza, zdefiniowanego przez podaną wyżej stałą. Gdyby zdarzyło się, że przekroczymy te ograniczenie, nadmiarowe znaki zostają usuwane... Skoro znamy już podstawy, możemy zapoznać się z procedurą zarządzania tablicą dynamiczną: 1/4. Dodawanie Każdorazowe dodanie elementu powoduje utworzenie się na samej górze nowego poziomu (patrz: przykład z półką) z zaalokowanymi komórkami w ilości block_size. Możemy tam wrzucić pojedyńczą komórkę, ciąg znaków, bądź tablicę. Przykład: 2/4. Modyfikowanie Każdy poziom możemy dowolnie edytować. Musimy jedynie wiedzieć na jakiej wysokości się on znajduje. Ważne jest, że poziomy numerujemy od zera! (dół - zero). Przykład: 3/4. Pobieranie Jeżeli pobieramy komórkę ( GetArrayCell ), zostanie ona zwrócona przez return. W przypadku stringa i tablicy, wartości zostaną skopiowane do podanych przez nas lokalizacji. Przykład: 4/4. Usuwanie Nic prostszego - wystarczy index poziomu. Po usunięciu wszystkie wyższe poziomy spadają o jeden w dół (troche jak ściąganie obrusu z zastawionego stołu ?) 5/4. Reszta SourceMod posiada dużo więcej funkcji obsługujących tablicy dynamiczne. Zapraszam tutaj: https://go-code.pl/dokumentacja-sourcemod/adt_array/ Przykład Poniższy kod dodaje do tablic dynamicznych nazwę i UserId każdego gracza, który wejdzie na serwer. Ponadto, komenda !show pozwala na wyświetlenie zawartości owych tablic, a po wybraniu gracza z menu plugin wypisuje jego status - czy gracz jest połączony, czy też nie (lub wykonał reconnect): To by było na tyle ? Jeżeli pojawią się jakieś pytania z radością na nie odpowiem, a w razie potrzeby zaktualizuję poradnik Pozdrawiam!
  8. Ten temat zawiera spis wszystkich artykułów zamieszczonych w tym dziale 1. Ogólne Komendy admina SourceMod Spis broni CS:GO 2. Optymalizacja Jak pozbyć się lagów w CS:GO 3. Wygląd Jak włączyć panoramę w CS:GO? Jak WYŁĄCZYĆ panoramę w CS:GO? (-legacyscaleformui) Nóż w lewej ręce
  9. Ten temat zawiera spis wszystkich artykułów zamieszczonych w tym dziale 1. Wszystkie linki Opis flag SourceMod Wydanie sourcemoda w wersji 1.9 Jak wgrać ręcznie sourcemoda i metamoda
  10. Ten temat zawiera spis wszystkich artykułów zamieszczonych w tym dziale 1. Poradniki na temat wiedzy ogólnej Składnia nowa czy stara? (#pragma newdecls required) Jak skompilować plugin sourcemod? (linux) Spis errorlogów i co one oznaczają? Najczęściej popełniane błędy Co to backdoor? Jak pisać przejrzysty kod? Optymalizacja warunków Opis notacji węgierskiej 2. Poradniki o strukturach danych Co to bity i jak ich używać? Jak działają tablice dynamiczne? Struktura enum i jak tego używać Co to datapack? 3. Poradniki dotyczące funkcji w dokumentacji Sourcemod Timer's - CreateTimer / TriggerTimer / KillTimer Pobieranie wielkości magazynka Wszystko co dotyczy Menu Kompendium wiedzy na temat Natywów i Forwardów 4. Inne Jak sprawdzić czy gracz używa panoramy? Dodatki do Danger Zone (weapon_axe weapon_hammer weapon_spanner) Jak działają wektory w przestrzeni 3D? Podświetlenie składni Sourcemod w Notepad++ Jak utworzyć licencję na plugin? Jak spolszczyć plugin na gotowym phrases.txt Jak spolszczyć plugin bez pliku phrases.txt Jak spolszczyć plugin dodając do niego kod obsługujący phrases.txt

Nasza historia

Na początku byliśmy małą grupą internetowych znajomych, którzy stwierdzili, że potrzebne jest solidne forum, na którym znajdą się ludzie z dużą wiedzą programistyczną ukierunkowaną na CS:GO. Pomysł powstał na początku 2018 roku, a parę miesięcy później, 19 kwietnia, powstała ta strona internetowa. Jako alternatywna odpowiedź na inne tego typu miejsca, poważnie podeszliśmy do tematu, najpierw tłumacząc angielską dokumentację SourceMod'a na język polski, a potem pisząc rozległe poradniki i wypełniając forum najpotrzebniejszymi rzeczami dla właścicieli serwerów i programistów. Cała nasza Ekipa jest dumna z pracy jaką w to włożyliśmy i cieszymy się że zbierają się wokół nas zarówno ludzie znający tematy sourcepawn'a i konfiguracji, jak i również nowe twarze w tym "biznesie", którym z chęcią niesiemy wiedzę oraz pomoc w rozwiązywaniu problemów.

Największe modyfikacje serwerowe

×
×
  • Create New...