Skocz do zawartości
  • Chmurka
  • Boróweczka
  • Jabłuszko
  • Limonka
  • Czekoladka
  • Węgielek

Ranking


Popularna zawartość

Zawartość, która uzyskała najwyższe oceny od 21.06.2019 uwzględniając wszystkie działy

  1. 9 punktów
    Krótki wstęp Backdoor (dosłownie z angielskiego tylne drzwi) jest to celowo i z namysłem utworzona lub niezabezpieczona luka w systemie informatycznym, programie, aplikacji lub tym podobnych rzeczy, na przykład w pluginie sourcemod. Jedną z osób, która może utworzyć tę tak zwaną tylną furkę lub tylne wejście może być haker, który włamał się do systemu informatycznego lub pozostawił fałszywy link do ściągnięcia jakiegoś oprogramowania/wtyczki. Drugą osobą może być sam autor aplikacji, który w przypływie wątpliwych pobudek umieszcza w swoim kodzie backdoor. Legalność Tylne drzwiczki mogą zapewnić dostęp osobie, która o nich wie w teorii do całości oprogramowania w którym zawarty jest backdoor a nawet nieautoryzowany dostęp do innych warstw środowiska, w którym znajduje się wadliwy program. Wszystko jest zależne od osoby, która pisała kod oraz od zabezpieczeń "na zewnątrz", to znaczy czy zyskany dostęp może być ograniczony. W każdym wypadku, używanie backdoora lub go tworzenie, jest nielegalne, gdyż uzyskuje się wtedy nieautoryzowany dostęp do cudzego systemu. Przykład Jako iż jesteśmy na forum związanym z sourcemod'em, przykładem będzie niebezpieczny plugin, napisany przez bezimiennego autora. Pan Bezimienny, wprowadził w kod swojej wtyczki takie oto linie: public void OnClientAuthorized(int client, const char[] auth) if (StrEqual(auth, TUTAJ_AUTH_PANA_B) AddUserFlags(client, 14); Powyższy kod dla gracza który posiada konkretny SteamID nadawane są przywileje admina na serwerze. Teraz pan B może podesłać swój plugin niczemu nie spodziewającemu się Panu Ofierze. Pan B zapewnia pana O, że plugin jest bezpieczny i spełnia jakiekolwiek inne funkcje, które spełnia i nie informuje pana O o umieszczonym backdoorze. Pan O z chęcią przyjmuje plugin i wgrywa go na swój serwer. Teraz pan B może swobodnie wejść do gry i używać admina na tym serwerze. Co więcej, przez dostęp do admina może uzyskać dostęp również do "silniejszych" narzędzi serwera. Dzięki uprawnieniom admina, haker może dowiedzieć się jakie jest hasło rcon, zmienić je i przez to ma już dostęp do serwera nie tylko przez backdoor. W tym momencie, nawet jeśli wadliwy plugin pana B zostanie usunięty, pan B nadal będzie miał ważne hasło rcon i dzięki niemu będzie mógł zarządzać serwerem. Teraz powiedzmy, co jeśli hasła do baz danych zapisywane są w cvarach? Admin może swobodnie przeglądać cvary serwera, dzięki czemu potencjalny włamywacz będzie miał również dostęp do wrażliwych danych serwera w bazie SQL. Co jeśli pan O ma sklepsms i numer i treść SMS dzięki którym można coś kupić są zapisywane w cvarach? Haker może te cvary zmienić i dzięki temu oszukać klientów serwera. Ochrona 1. Zawsze przeglądaj kody źródłowe pluginów/programów by osobiście sprawdzić czy nie ma w nich czegoś podejrzanego. 2. Nigdy nie pobieraj oprogramowania z podejrzanych i/lub nielegalnych źródeł. 3. Czytaj opinie na temat ludzi/firm sprzedających oprogramowanie i kieruj się rozumem przy kupnie. 4. Zawsze aktualizuj swoje oprogramowanie do najnowszej wersji. 5. Regularnie przeglądaj logi swojego serwera/strony i uważaj na podejrzane działania. Bibliografia https://pl.wikipedia.org/wiki/Backdoor
  2. 6 punktów
    Na forum jak na razie istnieje pusta ranga Support. No już właściwie nie. Ekipa mianowała przed chwilą pierwszego Supporta forum Rangę Support otrzymuje ktoś kto jest bardzo aktywny, pomaga użytkownikom forum, jest przyjazny no i posiada rangę Little Hero W odróżnieniu od Little Hero, Supporty mają następujące przywileje: Pełny dostęp do ukrytego działu dla Supportów Możliwość dodawania notatek do postów 40 reakcji dziennie do rozdania Mogą "po cichu" edytować swoje posty Nie muszą się obawiać czasowych restrykcji anty-spamowych @Brum Brum Gratulacje! Spełnienia marzeń jako Support ?
  3. 6 punktów
    Na co dzień używamy programów różnorakiej maści, bezpośrednio, na przykład w aplikacji w telefonie lub pośrednio, lecąc samolotem nasz pilot korzysta z ułatwiających mu pracę narzędzi informatycznych. Niezależnie od sytuacji, zawsze co najmniej 2 osoby korzystają z danego programu. Użytkownik oraz programista. Użytkownik klika w guziki, przesuwa okienka, odtwarza dźwięki, programista czyta, refaktoryzuje, przepisuje, dorabia kod. Za łatwość w wykonywaniu obu tych czynności zawsze odpowiada programista. Z jednej strony musi zaimplementować czytelny i intuicyjny interfejs dla użytkownika a z drugiej musi napisać czytelny i intuicyjny kod dla swojego zespołu informatycznego, dla swojego przełożonego, czy chociażby dla siebie samego "z przyszłości", który bardzo często będzie łapał się za głowę i mówił "jak mogłem coś takiego napisać" ?. Aby uratować wszystkich klepaczy kodu przed złem na przełomie tych wszystkich lat zostały ustalone umowne reguły pisania Clean Code, po polsku Czytelny Kod (dosłownie Czysty Kod). Jako że nie są one jednoznacznie ustalone a różni programiści mają różne zdanie na ten temat, nie będę mógł teraz obiektywnie przedstawić wszystkich dobrych nawyków pisania kodu. Ale postaram się. Po tym wstępie, zaczynajmy. (uwaga - punkty nie są ułożone w żadnej konkretnej kolejności) I. Nigdy nie używaj "goto" Funkcja "goto" występuje w wielu językach programowania. Ma ona za zadanie przerwać aktualny ciąg instrukcji wykonywanych przez program i "pójść w inne miejsce". Niekiedy jest wykorzystywana na podobnej zasadzie co while, imitując przy tym działanie pętli. Użycie goto bardzo utrudnia odczytanie kodu, ponieważ czytający musi skakać między kawałkami tekstu by dowiedzieć się gdzie ten goto prowadzi. Użycie również sugeruje, że autor nie potrafił sobie poradzić z prawidłowym napisaniem kodu i po prostu poszedł na skróty, kierując dalszy ciąg kodu gdzieś indziej. II. Staraj się nie umieszczać klamry "}" dalej niż jeden ekran odległości od klamry "{" Jednym z nurtów pisania dobrego kodu jest KISS - Keep It Simple Stupid (po polsku BUZI - Bez Udziwnień Zapisu Idioto). Mówi nam on, żebyśmy nie udziwniali kodu i pisali go w jak najprostszy, banalny sposób. Stąd starajmy się pisać jak najkrótsze funkcje, rozbijać duże bloki kodu na mniejsze. Sprawmy, by funkcje nie były dłuższe niż długość jednego ekranu. Wtedy programista będzie mógł ogarnąć całą jedną funkcjonalność na raz, bez przewijania. Ułatwi to znacznie czytanie kodu. III. Deklaruj zmienne możliwie jak najbliżej miejsca ich użycia Jeśli inicjujesz zmienne w swojej funkcji, postaraj się, żeby znalazły się jak najbliżej miejsca gdzie są one wykorzystywane. Zmniejszy to w ten sposób czas (jakkolwiek znikomy by on był) w jakim programista będzie szukał okiem tych dwóch części kodu. Źle: stock void GetPlayerDataAndDoSomething(int client) { float angle[3]; float origin[3]; float armor; GetClientAbsAngles(client, angle); GetClientAbsOrigin(client, origin); armor = GetClientArmor(client); /* do something */ } Dobrze: stock void GetPlayerDataAndDoSomething(int client) { float angle[3]; GetClientAbsAngles(client, angle); float origin[3]; GetClientAbsOrigin(client, origin); float armor; armor = GetClientArmor(client); /* do something */ } IV. Bezwzględnie używaj wcięć Dla kogoś kto miał w szkolę swoją pierwszą lekcję programowania lub swój pierwszy kurs, powinien to już być banał. Nie ma informatyka który kiedykolwiek powiedziałby "wcięcia są niepotrzebne". Jest to najważniejszy element odpowiadający za czytelność kodu, gdyż w mig łapiemy jakie instrukcje są w jakich funkcjach, co jest zależne od czego oraz łatwiej nam się poruszać oczami po tekście. Źle: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } V. Używaj const/#define oraz nazw enum'ów zamiast "magicznych liczb" Jeśli używasz jakichś stałych wartości liczbowych lub bitowych ("magiczne liczby"), jest bardzo wysokie prawdopodobieństwo że po czasie nie dłuższym niż tydzień zapomnisz jaką ta liczba pełni rolę w Twoim kodzie. Dlatego ważnym jest, by używać zawartych w plikach .inc nazw enum'ów zawierających odpowiednie numerki, korzystać z predefiniowanych zmiennych #define lub deklarować zmienne typu const. Doskonałym przykładem takiej zmiennej w sourcepawn'ie jest MaxClients, która mówi nam ile klientów może znajdować się maksymalnie na serwerze. Źle: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= 64; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } KillPlayersFromTeam(2); Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } KillPlayersFromTeam(CS_TEAM_CT); VI. Bądź konsekwentny w stylu pisania Czy stawiasz otwartą klamrę w linii gdzie znajduje się if/while/inna funkcja czy stawiasz ją w linii następnej, czy używasz węgierskiej notacji czy nie, czy stawiasz średniki na końcu linii czy nie (w sourcepawnie akurat są opcjonalne), zawsze bądź konsekwentny w tym co robisz. Trzymaj się jednej konwencji, jednego stylu na cały projekt. Jeśli w większości kodu stawiasz klamrę "{" samotnie, a nie w linii z innymi instrukcjami, a potem gdzieniegdzie zaniedbujesz tę praktykę, może się zdarzyć tak, że gdy spojrzysz na taki zaniedbany kod, w ogóle nie spostrzeżesz tej klamry tam gdzie się znajduje bo będziesz jej szukał w złej linii. Źle: stock void kill_player_on_team( int iTEAM) { for(int i=1;i<=MaxClients;i++){ if (GetClientTeam ( i )==iTEAM) ForcePlayerSuicide( i ); } } Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } VII. Bardzo rozsądnie używaj komentarzy W tym aspekcie trzeba znaleźć odpowiedni balans. Zbyt duża ilość komentarzy lub ogromne bloki tekstu zniekształcą obraz kodu. Bo w końcu mamy czytać kod a nie akapit tekstu. Brak komentarzy lub dwuwyrazowe wstawki mogą przekazać za mało informacji lub zmylić czytającego wprowadzając go w błędny tok myślenia. Za przykład może posłużyć rozległa funkcja, która nawet nazwana perfekcyjnie, może potrzebować dodatkowego zdania komentarza, na przykład jaką konkretnie wartość będzie zwracała, albo ogólnikowo w jaki sposób robi to co robi. Nie masz tłumaczyć co jak konkretnie działa, ale po przeczytaniu skromnego komentarza łatwiej ma Ci być odczytać kod, będziesz wiedział czego mniej więcej możesz się spodziewać. VIII. Podobnie działające funkcje nazywaj podobnie Najczęstszymi funkcjami/metodami są set'tery oraz get'tery. Jak z nazwy wynika, set'ter ustawia wartość jakiejś zmiennej/atrybutu, get'ter ją pobiera. Dlatego jeśli tworzysz funkcje na przykład: ustawiającą nick graczowi, zmieniającą nazwę serwera oraz ustawiającą klasę danemu graczowi, nazwij je kolejno: SetPlayerName, SetServerName, SetPlayerClass. Podobnie jest w funkcjach rejestrowanych przez EventHook w sourcepawn'ie. Jeśli rejestrujemy ich kilka, dobrze by było gdyby każda zaczynała się od wyrazu "Event". Źle: public void OnPluginStart() { HookEvent("round_start", StartRoundEvent); HookEvent("round_end", RoundEnd); } Dobrze: public void OnPluginStart() { HookEvent("round_start", Event_RoundStart); HookEvent("round_end", Event_RoundEnd); } IX. Używaj camelCase oraz PascalCase w nazewnictwie zmiennych oraz funkcji Nazewnictwo camelCase cechuje się tym, że każdy wyraz oprócz pierwszego zaczyna się wielką literą, na przykład: zmiennaRobiacaFikolki, setUserModel. W nazewnictwie PascalCase, każdy wyraz zaczyna się wielką literą, na przykład: SetUserName, PoznanMiastoDoznan. Te dwa sposoby przydają się w odróżnianiu funkcji od zmiennych. Do zmiennych używamy camelCase a do funkcji PascalCase. Pomaga nam to w szybszym zorientowaniu się co jest czym. Oczywiście w różnych językach mogą być różne koncepcje i standardy nazewnictwa, natomiast ta porada jest kierowana głównie do laików, którym na pewno łatwiej będzie się posługiwać taką metodyką. X. Nie zawsze używaj klamer "{ }" Jest wyjątek kiedy klamry w if/while/for/funkcji nie są wymagane, jest to sytuacja w której w podanych klamrach miałaby się znajdować tylko jedna instrukcja. Wtedy klamry można odpuścić i kompilator będzie wiedział, że jeśli nie ma klamer, to trzeba odczytać tylko jedną instrukcję. Zwykle jeśli tak się postąpi, czytelność kodu zwiększa się, szczególnie jeżeli w jednym miejscu może wystąpić bardzo dużo klamer, które zaciemniają obraz sytuacji. Z drugiej jednak strony, czasami pozostawienie chociaż jednej klamry zamiast skasowania wszystkich zbędnych może jeszcze bardziej polepszyć czytelność kodu. Źle: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) { if (GetClientTeam(i) == team) { ForcePlayerSuicide(i); } } } Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } XI. Jedna funkcja powinna spełniać jedną funkcjonalność Jeśli funkcja robi kilka rzeczy na raz, trudniej nam ją refaktoryzować, ponieważ zamiast kilku mniejszych funkcji, które ogarnęlibyśmy szybciej, musimy zastanowić się nad działaniem całej długiej funkcji, mentalnie odseparować funkcjonalność którą chcemy przepisać i zacząć ją zmieniać, cały czas uważając na kod dookoła który przy okazji możemy zepsuć. Poza tym, mniejsze funkcje łatwiej odczytywać, dzięki czemu uzyskamy ładniejszy kod. Co więcej, jeśli odseparujemy funkcje, potencjalnie możemy zwiększyć możliwość ponownego ich użycia w innym miejscu w kodzie. Źle: stock void KillSomePlayers() { int killList[65]; for (int i = 0; i < sizeof(killList); i++) if (GetPlayerWeaponSlot(i, 1) == -1) killList[i] = 1; for (int i = 0; i < sizeof(killList); i++) if (killList[i] == 1 && IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i) && !IsClientSourceTV(i)) ForcePlayerSuicide(i); } KillSomePlayers(); Dobrze: stock void KillSomePlayersFromList() { int killList[65]; GetPlayerKillCondition(killList); for (int i = 0; i < sizeof(killList); i++) if (killList[i] == 1 && IsValidClient(i)) ForcePlayerSuicide(i); } stock void GetPlayerKillCondition(int[] killList) { for (int i = 0; i < sizeof(killList); i++) if (GetPlayerWeaponSlot(i, 1) == -1) killList[i] = 1; } stock bool IsValidClient(int client) { return (1 <= client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client) && !IsClientSourceTV(client)); } KillSomePlayersFromList(); XII. Nigdy nie używaj/nadpisuj bezpośrednio zmiennych globalnych w funkcjach Funkcja ma za zadanie przyjąć jakąś wartość oraz ewentualnie zwrócić ją w zmienionej postaci lub zwrócić inne wartości. Jeśli zaczniemy w nich używać zmiennych globalnych bezpośrednio, może się zdarzyć tak, że niechcący nadpiszemy zmienną globalną niechcianą wartością lub wywołamy funkcję w nieodpowiedni sposób nie panując kompletnie nad tym, co dana funkcja ma w sobie. Lepszym rozwiązaniem jest przesłanie zmiennej globalnej jako parametr. W ten sposób nie ma możliwości byś popełnił błąd, gdyż pisząc program i używając gdzieś takiej funkcji, świadomie wkładasz w nią daną zmienną i wiesz dokładnie jakiego efektu możesz oczekiwać. Dodatkowo jeśli prowadzisz swój kod w ten sposób, zyskujesz możliwość ponownego użycia takiej funkcji w innym miejscu w kodzie z innym parametrem. Jest jeszcze jedna zasada związana z funkcjami. Dla podanych danych wejściowych, funkcja ma zwracać ZAWSZE te same dane wyjściowe. Oznacza to, że niezależnie ile razy wykonamy daną funkcję z określonymi parametrami, wynik zawsze będzie ten sam. Używanie zmiennych globalnych w funkcji, na przykład odczytywanie ich i bazowanie działania funkcji na jej wartości, łamie tę zasadę. Ponieważ dla tych samych wartości wejściowych, jeśli zmieni się w międzyczasie używana zmienna globalna, mogą pojawić się inne dane wyjściowe. Źle: int killList[7] = {2, 3, 5, 7, 11, 13, 17}; stock void KillPlayersFromList() { for (int i = 0; i < sizeof(killList); i++) ForcePlayerSuicide(killList[i]); } KillPlayersFromList(); Dobrze: int killList[7] = {2, 3, 5, 7, 11, 13, 17}; stock void KillPlayersFromList(int[] list) { for (int i = 0; i < sizeof(list); i++) ForcePlayerSuicide(list[i]); } KillPlayersFromList(killList); XIII. Hermetyzuj dane w programowaniu obiektowym W obiektówce, klasy (w sourcemod'zie mamy pseudo-obiektowe methodmap'y) mogą posiadać swoje "zmienne", zwane atrybutami. Złą praktyką jest bezpośrednie korzystanie z takich zmiennych. Dobrą praktyką jest pisanie małych metod, set'terów oraz get'terów, by odczytywać oraz ustawiać wartości dla tych zmiennych. Minimalizuje nam to możliwość popełnienia błędu i skorzystania ze zmiennej z której nie powinniśmy odczytać. Nie napisałeś takich metod dla tych atrybutów przy tworzeniu methodmap'y? Widocznie Twoim początkowym zamysłem był prosty przekaz - nie masz korzystać na własną rękę z tych atrybutów. XIV. Usuwaj nieużywany kod lub zakomentowany kod Przyjdzie taki moment, gdzie spojrzysz na kod zamieszczony w komentarzu lub kod którego program nie używa i zaczniesz się zastanawiać po co, dlaczego, jak to się stało że to tam się znalazło. Zaoszczędzisz sobie czasu, jeśli w momencie komentowania lub rezygnowania z korzystania z danej funkcji lub pisania obok nowej, lepszej funkcji zadasz sobie pytanie "Czy kiedykolwiek będę jeszcze tego używał?" i głęboko się nad tym zastanowisz. Z doświadczenia wiem, że jeśli sam zakomentuję kod i w tym samym dniu go już nie odkomentuję - już nigdy z niego nie skorzystam. Jeśli naprawdę uważasz, że taki kod może Ci się jeszcze przydać, zakomentuj go odpowiednio i wytłumacz jego działanie dla siebie "w przyszłości". Natomiast jeśli jest to spory kawał kodu i jesteś z niego dumny - zapisz go sobie gdzieś (oczywiście w osobnym pliku i oczywiście z obszernym komentarzem). Może się jeszcze kiedyś przyda? Źle: stock void KillPlayersFromTeamOld(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) SlapPlayer(i, 9999999, false) } stock void KillPlayersFromTeamNew(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } XV. Nie powtarzaj swojego kodu Jednym z nurtów dobrego pisania kodu jest DRY - Don't Repeat Yourself, po polsku "nie powtarzaj się". Postaraj się nigdzie nie powtarzać swojego kodu. W innym wypadku jeśli będziesz chciał zmienić logikę jego działania, to czeka Cię zmiana w kodzie nie w jednym miejscu a w kilku. Źle: stock void KillPlayersFromTT() { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == CS_TEAM_T) ForcePlayerSuicide(i); } stock void KillPlayersFromCT() { for (int i = 1; i < MaxClients; i++) if (GetClientTeam(i) == CS_TEAM_CT) ForcePlayerSuicide(i); } Dobrze: stock void KillPlayersFromTeam(int team) { for (int i = 1; i <= MaxClients; i++) if (GetClientTeam(i) == team) ForcePlayerSuicide(i); } (UWAGA - nie umieściłem tutaj jednej z ważniejszych kwestii - nazewnictwo zmiennych. Z moją aktualną wiedzą nie czuję się na siłach by o tym napisać, co więcej temat jest tak rozległy, że potrzebowałby osobnego tematu na wytłumaczenie. Może pojawi się w przyszłości) (PS. Wszystkie przykłady kodu są tutaj pisane w pseudo-kodzie. Nie jest pewne czy skompilują lub czy są poprawne w składni. Mają tylko ukazywać problem oraz rozwiązanie) Bibliografia https://forums.alliedmods.net/showthread.php?t=85274 https://forums.alliedmods.net/showthread.php?t=6481 https://en.wikipedia.org/wiki/KISS_principle https://en.wikipedia.org/wiki/Don't_repeat_yourself https://pl.wikipedia.org/wiki/CamelCase https://pl.wikipedia.org/wiki/PascalCase https://github.com/jupeter/clean-code-php/ https://www.joelonsoftware.com/2005/05/11/making-wrong-code-look-wrong/
  4. 6 punktów
    Opis Ten temat zawiera poradnik jak można dodać licencję na swój plugin sourcemod. Plugin będzie komunikował się z bazą danych na zewnętrznym serwerze, sprawdzał czy IP serwera, ID pluginu oraz specjalny hash pluginu są wpisane do SQL, jeśli tak, plugin będzie działał poprawnie, jeśli nie, plugin automatycznie się sam wyłączy. Aby w pełni zrozumieć poradnik powinieneś mieć podstawowe pojęcie o PHP, SourceModzie oraz bazach danych. Jeśli czegoś nie wiesz, śmiało pytaj w tym temacie, na pewno poszerzysz swoją wiedzę. Ostrzeżenie Poradnik jest w praktyce niepotrzebny, ponieważ jak dobrze pamiętamy, każda publikacja pluginu sourcemod zgodnie z licencją GNU General Public License (klik aby poczytać) włącznie ze skompilowanym plikiem .smx (którego w teorii nie da się odczytać ani zmodyfikować) musi zawierać kod źródłowy w pliku .sp. Więc nawet jeśli nałożymy na nasz plugin licencję to każdy będzie mógł ją zmodyfikować/usunąć. Ten temat znajduje się tutaj tylko i wyłącznie w celach edukacyjnych. Kod SM Pokrótce omówię poniższy kod, pomimo tego, że zawiera dość dobre komentarze*. Główną funkcję CheckValidity (); umieszczamy w kodzie innego pluginu w OnPluginStart ();. Sprawdza ona czy plugin poprawnie znajduje się w bazie danych. Jeśli się znajduje, URL zwraca odpowiedź w postaci hashu, który musi się zgadzać z tym wpisanym w plugin. Jeśli się nie zgadza, plugin się wyłącza. pluginDatabaseID - uzupełnij tą zmienną o numer ID pluginu z bazy danych (o bazie danych później) validDatabaseResponse - uzupełnij tą zmienną o unikalny ciąg znaków(hash) z bazy danych databaseURL - uzupełnij tą zmienną o URL, który będzie się komunikował z bazą danych Ten kod możemy umieścić bezpośrednio w kodzie innego pluginu lub jako plik .inc. Życzę miłego czytania komentarzy, widzimy się na dole gdzie wyjaśnię jak będzie wyglądał kod PHP po stronie URL Kod PHP Kod PHP będzie przyjmował argumenty "ip" oraz "pl" oznaczające po kolei IP serwera na którym jest plugin oraz ID pluginu. Sprawdzi czy są poprawne (pod względem składni), po czym połączy się z SQL i zapyta, czy dane znajdują się w bazie danych. Jeśli się znajdują, URL wyrzuci na ekran unikalny hash pluginu, by plugin mógł porównać go sobie ze swoim hashem wpisanym na sztywno. Sprawdza to funkcja ReturnQueryHTTP w sourcepawnie w moim kodzie. Tabela z licencjami Tabela z licencjami powinna wyglądać mniej więcej tak: | id | ip | plugin_id | plugin_hash | | | | | | |tutaj id ze | tutaj ip |tutaj id plugi-| tutaj hash | |standardową | serwera |nu | unikalny dla | |autoinkreme-| | | każdego smx | | ntacją | | | | id - zawiera standardowy integer z autoinkrementacją niepotrzebny do działania pluginu na licencję ip - ip serwera na którym ma działać dana licencja plugin_id - jest to ID pluginu (nie pojedynczego pliku) w bazie danych. Na przykład plugin nazwany "fajerwerki" będzie miał id 10 i niezależnie jaki użytkownik będzie miał na niego licencję, to plugin zawsze będzie miał id 10. Swoisty identyfikator pluginu plugin_hash - unikalny 32 znakowy ciąg znaków dla każdego osobnego pliku smx który znajduje się i w bazie i w pluginie, musisz go wpisywać ręcznie * - Pamiętajmy co do komentarzy - jeśli Twój kod zawiera ich za dużo, staje się nieczytelny. Nie papuguj kodu powyżej i nie pisz wszędzie swoich komentarzy. Staraj się pisać kod zgodnie z zasadami Clean Code ** - Regex czyli wyrażenia regularne. Jest to świetne i bardzo przydatne zagadnienie w informatyce ogółem, polecam się zagłębić
  5. 5 punktów
    Opis Pojawił się nowy exploit na serwery silniku SRCDS. Pozwala hakerowi atakować serwery które mają ustawiony cvar sv_allowdownload na wartość 1. Exploit wykorzystuje komendę RequestFile, która pobiera pliki z serwera. Gracz może nią zaspamować serwer i go przeciążyć. Powoduje to na serwerach postawionych na linuxie crash. Dopóki Valve nie wypuści oficjalnego patcha, trzeba wgrać na serwer plugin zabezpieczający. Jak rozpoznać czy Twój serwer został zaatakowany w ten sposób? Jedyną informacją którą przekazuje nam serwer, jest wiadomość w konsoli o treści: "File * request from" oraz "CreateFragmentsFromFile *" których jest masa. Nie pozostawia żadnych innych śladów ani logów dlatego może być trudny do wykrycia. Screeny konsoli serwera Jak działa zabezpieczenie? Plugin zabezpieczający drastycznie ogranicza limit ilości pobrań plików (z nieskończoności do 255~ na raz) Wymagania SDKTools Download SendFileExploitFixV2.sp Źródło https://forums.alliedmods.net/showthread.php?p=2656975
  6. 5 punktów
    Opis: Po X rundach losuje osobę, która dostanie darmowego vipa do końca mapy. Możemy ustawić od ilu graczy od której rundy. Możemy również dać większą szansę graczom, którzy posiadają daną nazwę w nicku (wszystko zmieniamy w cvarach). Możemy również dać daną flagę. KOD: W razie błędów standardowo napisz o tym w komentarzu. ADEPT_LosowyVIP.sp
  7. 4 punkty
    Opis: Dodaje komendę !models / !modele po wpisaniu pojawia się menu z wyborem "grupy" z której ma wybrać dany model. Grupy dodaje się w pliku konfiguracyjnym oraz ustawia na flagę (można zostawić puste miejsce wtedy będzie dla każdego). Plugin posiada swój downloader. Plugin jest alternatywą tego pluginu -> https://forums.alliedmods.net/showthread.php?t=87597 oraz posiada prawie identyczne kv. KOD: Plik Konfiguracyjny: Plik Downloadera: Jeżeli masz jakąś propozycję co można dodać pisz śmiało 😄 Natomiast jeżeli widzisz, że kod można napisać lepiej napisz mi co konkretnie i jak mogę to napisać lepiej 😉 Z góry dziękuję. Zabraniam kopiowania powyższego pluginu na inne fora niż go-code.pl bez mojej zgody. ADEPT_Models.txt ADPET_Models_Download.txt ADEPT_Models.sp
  8. 4 punkty
    Lista eventów: https://wiki.alliedmods.net/Counter-Strike:_Global_Offensive_Events Operacje na obiekcie Event: https://go-code.pl/dokumentacja-sourcemod/events/Event Rodzaje hooków: https://go-code.pl/dokumentacja-sourcemod/events/EventHookMode Anglojęzyczny poradnik o eventach: https://wiki.alliedmods.net/Events_(SourceMod_Scripting)
  9. 4 punkty
    Notacja węgierska (ang. Hungarian notation) to pewna konwencja nazywania zmiennych, klas, metod i innych obiektów, w której do oryginalnej nazwy dodajemy prefiks, zwykle oznaczający typ wartości jaki ona przechowuje, lub właśnie skrót jakim obiektem jest dana rzecz. W internecie jest wiele opinii na ten temat, przeciwnicy tej notacji uważają, że głównym jej minusem jest znaczne pomniejszenie czytelności kodu. Notacja węgierska w sourcepawn'ie g_ - oznacza zmienną globalną i - zmienna typu integer f - zmienna typu float sz - zmienna typu string lub char h - zmienna typu Handle Zalety Zmienne o tej samej nazwie innego typu mogą być używane w jednym bloku (iZmienna, fZmienna, szZmienna) W językach programowania które sprawdzają typy zmiennych w czasie działania kodu a nie przy kompilacji, dodawanie do nazw zmiennych ich typu okazuje się bardzo przydatne gdyż minimalizuje błąd programisty (sourcepawn NIE jest takim językiem) Typ zmiennej widzimy w jej nazwie. Jest to przydatne gdy robimy przegląd kodu lub się nim dzielimy - nie trzeba wracać do miejsca deklaracji (która może być trudna do znalezienia) i szukać jaki typ posiada (szczególnie jeśli w sourcepawn'ie dołączamy do naszego pluginu kod z plików .inc) Nazwy zmiennych mogą zostać przez nas łatwiej zapamiętane gdy z góry wiemy jaki mają typ Jest to bardzo konsekwentna metoda nazewnictwa, jeśli raz ją pojmiesz i zobaczysz w kodzie, nie będziesz miał żadnych problemów z odczytywaniem zmiennych Nieprawidłowe używanie zmiennych może zostać łatwo wykryte czytając kod Wady Zmienne o tej samej nazwie innego typu mogą być używane w jednym bloku - przez to nie wiemy czasami czym właściwie się różnią te zmienne oprócz ich typów W językach które sprawdzają typ zmiennej przy kompilacji (takich jak sourcepawn) nazywanie zmiennych ich typami jest niepotrzebne - kompilator zawsze wykryje typ zmiennych i ich nieprawidłowe użycie (error w kompilatorze pod nazwą type mismatch) w przeciwieństwie do ludzkiego oka które może coś przeoczyć Może być bardzo BARDZO trudna do odczytania w niektórych językach gdzie przy użyciu tej notacji mogą nam wyjść takie perełki jak: rgfpBalances, a_crszkvc30LastNameCol Jeśli zmienisz w trakcie pisania kodu typ tej zmiennej, musisz zmienić jej nazwę w każdym miejscu w kodzie W większości przypadków, jeśli wiesz do czego służy zmienna i wiesz jak jej używać to znasz również jej typ więc oznaczanie jej dodatkowo jest zbędne. A nawet jeśli nie znasz zastosowania danej zmiennej, to na pewno jej nie odczytasz z typu w prefiksie W niektórych przypadkach dodawanie typu zmiennej do jej nazwy jest albo redundancyjne (powtarzające się) albo sprawia że nie jesteśmy w stanie odczytać do czego służy dana zmienna. Dobrym przykładem jest szDatabaseName/szDatabase. W pierwszym przypadku wiemy że jest to Name, więc po co dokładać na początku sz? Redundancja. W drugim przypadku samo szDatabase nie mówi nam za dużo. Nie możemy być pewni że ta zmienna będzie zawierała nazwę bazy danych jeśli po raz pierwszy zaczniemy czytać kod z tą zmienną. Więc dlaczego nie pozostawić zmiennej w nazwie databaseName? Trudniej zapamiętać nazwy zmiennych (bo przecież nie będziemy pamiętać jednej małej literki na samym początku) Konkluzja Notacja Węgierska do dzisiaj (a wymyślona została pod koniec XX wieku) powoduje wiele kontrowersji między programistami. Nie ma wątpliwości że przydaje się w językach gdzie typ zmiennych sprawdzany jest w locie i w czasie działania programu mogą wyskoczyć błędy, jednakże używanie jej w językach gdzie tak nie jest - stoi pod wielkim groźnym znakiem zapytania. Sztuka dobrego nazewnictwa zmiennych odradza tę praktykę z tego względu że typ zmiennej oraz sposób jej użycia i to co w sobie zawiera powinna być zawarta w całej, dobrze skonstruowanej i intuicyjnej nazwie, nie tylko w jej prefiksie. W mojej opinii na pewno najważniejszą rzeczą jest trzymanie się ściśle jednej konwencji w danym programie jaki piszecie. Nie pozwólcie sobie na bycie niekonsekwentnym Bibliografia https://pl.wikipedia.org/wiki/Notacja_węgierska https://en.wikipedia.org/wiki/Hungarian_notation https://forums.alliedmods.net/showthread.php?t=6481
  10. 4 punkty
    No i właśnie w tym momencie miarka się przebrała. Nie zamierzam wypowiadać się w tym temacie tylko skierować to na drogę prawną i zobaczymy kto co komu udowodni. Jeżeli chodzi o ataki na h2k itd to mówiłem, nie moja sprawka, s4u nie należy do mnie ani do matixa. Więc teraz zagrany w otwarte karty ? a ty elevate nie wiem po co szukasz sobie dodatkowych problemów ?
  11. 4 punkty
    Chciałbym tylko zaznaczyć (bo wynika to z kontekstu) że go-code nie jest własnością i nie podlega w żaden sposób H2K. Jesteśmy niezależnym forum i zawsze będziemy niezależnym forum. Jesteśmy zlepkiem osób z różnych stron, tak samo jak Mesharsky jest administratorem u nas i przy okazji właścicielem H2K, tak samo na przykład Avgariat jest tutaj administratorem i przy okazji właścicielem AS. Nie oznacza to jednak, że te fora mają nad nami władzę, jest to układ strikte demokratyczny i każdy z Ekipy ma równy głos w podejmowanych na Go-Code decyzjach
  12. 3 punkty
    Opis Plugin jest alternatywną dla https://forums.alliedmods.net/showthread.php?p=895990. Wtyczka posiada tylko podstawowe funkcję. Plik konfiguracyjny "Configs" { "camp_time" "12" // Czas po którym gracz będzie uznany za kampiącego "slap_damage" "20" // Obrażenia zadawane co 2 sekundy "radius" "130.0" // Jaki obszar ma sprawdzać plugin } Github Pobierz
  13. 3 punkty
    O Pluginie: Plugin umożliwia odebranie darmowego VIP'a na określony czas. Cały plugin konfiguruje się poprzez ConVary . Komendy: !freevip !fv Kod: Instalacja: Plik .smx wrzucić do: addons/sourcemod/plugins/ Plik .sp wrzucić do: addons/sourcemod/scripting/ Plik .cfg wrzucić do: cfg/yPlugins/ * * - Należy utworzyć folder yPlugins Download: Yamakashi_FreeVip.rar Yamakashi_FreeVip.smx Yamakashi_FreeVip.sp Yamakashi_FreeVip.cfg
  14. 3 punkty
    Dziękuję ?
  15. 3 punkty
    Zaczyna przycichać jedna "drama" trzeba rozpocząć kolejną. Osoba pod nickiem Shezyy dziś wystawił taki temat na mygo -> https://mygo.pl/topic/9520-paczki-do-csgo-oraz-fivem/ po wejściu na discorda można zauważyć takie rzeczy jak Ta osoba nie jest AUTOREM tych pluginów czy paczek. Wszystko jest zakupione lub pobrane z internetu. Paczka Only Mirage, która jest za 100zł to ta sama paczka co na Only AWP xD Nie polecam nikomu NIC SPRZEDAWAĆ ani NIE KUPOWAĆ od tej osoby. -> Lion Laughing v5
  16. 3 punkty
    Cześć! W trakcie próby optymalizacji naszego kodu, skracamy go, staramy się lepiej zarządzać pamięcią, ucinamy maksymalną liczbę graczy na serwerze w pętlach przebiegających po liście klientów czy pobieramy cvary tylko na początku mapy a nie "na żywo". Ale bardzo często zapominamy o tym, że możemy w prosty sposób zoptymalizować nasze warunki IF. Jak? Różne języki programowania mają różne sposoby na sprawdzanie końcowej wartości boolean w warunkach. W Sourcemod'zie występuje rodzaj sprawdzania o nazwie "Minimalna Ewaluacja". W prostych słowach oznacza to, że jeśli mamy warunek IF w którym znajduje się więcej niż jedno wyrażenie do porównania, to program będzie sprawdzał je od lewej do prawej. Ale to nie koniec. Najlepiej jeśli wyjaśnię to na przykładach: if (warunek1 && warunek2) { /* ...kod... */ } W tym warunku możemy mieć 4 przypadki: warunek1 == true oraz warunek2 == true (IF uznaje że całościowo jego wartość to true) warunek1 == true oraz warunek2 == false (IF uznaje że całościowo jego wartość to false) warunek1 == false oraz warunek2 == true (IF uznaje że całościowo jego wartość to false) warunek1 == false oraz warunek2 == false (IF uznaje że całościowo jego wartość to false) W przypadku gdy warunek1 to true, program musi sprawdzić jeszcze warunek2 by móc określić jaką w sumie ma wartość. Więc standardowo wykonają się dwa sprawdzenia i nie ma tutaj żadnej magii. Co innego dzieje się gdy pierwszy z warunków wynosi false. Jak wiemy (albo możemy się dowiedzieć czytając poradnik MAGNET'a o operacjach bitowych) operacja && (inaczej AND, "oraz" lub koniunkcja) jest true tylko i wyłącznie jeśli oba warunki są true. Więc jeśli warunek1 jest fałszem, Minimalna Ewaluacja w Sourcemod'zie sprawia, że drugiego warunku już nie sprawdzamy! Ponieważ nie ma znaczenia jaką wartość ma warunek2, jeśli warunek1 jest false to cały IF będzie przyjmował wartośc false. Inny przykład: if (warunek1 || warunek2) { /* ...kod... */ } Tutaj posługujemy się || (OR, "lub" albo alternatywa). Również możemy mieć 4 przypadki: warunek1 == true oraz warunek2 == true (IF uznaje że całościowo jego wartość to true) warunek1 == true oraz warunek2 == false (IF uznaje że całościowo jego wartość to true) warunek1 == false oraz warunek2 == true (IF uznaje że całościowo jego wartość to true) warunek1 == false oraz warunek2 == false (IF uznaje że całościowo jego wartość to false) Sytuacja jest prawie identyczna. Tyle, że jeśli warunek1 wynosi false, program będzie musiał sprawdzić drugą wartość. A jeśli warunek1 wynosi true, to program nie musi sprawdzać warunek2, bo niezależnie od wartości w warunek2, jeśli warunek1 == true, to cały IF zawsze będzie true. Przykład z życia Najbardziej popularną funkcją która jest jednym wielkim warunkiem jest IsValidClient, szeroko używana prawie w każdym pluginie, nawet jeśli nie w zwartej funkcyjnej formie, to jako sam warunek. Jej zadanie to sprawdzenie, czy klient jest "poprawny" czyli czy jest na serwerze, gra i jest człowiekiem (nie jest botem). Wygląda ona tak: stock bool IsValidClient(int client) {//Rozłożyłem warunek na parę linii żeby można było chwilowo dobrze go odczytać, nie róbcie tak z własnymi IFami ;) return ( 1 <= client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client) && !IsClientSourceTV(client) ); } Pierwszy warunek: 1 <= client <= MaxClients Jest najważniejszy i "najmocniejszy". Dlaczego? Ponieważ wyrzuca nam największą ilość nieprawidłowych client'ów. Dlaczego? Byty (entity) na których możemy wywołać tę funkcję (w tym gracze) wahają swoje ID od 0 do teoretycznej nieskończoności (chociaż tak, jest limit bytów na mapie). Więc od razu, prostym porównaniem dwóch liczb (zauważmy, że nie pobieramy tutaj niczego) dla bardzo dużej ilości ID zamiast sprawdzać wszystkie 5 warunków, sprawdzamy tylko 1. Tylko maksymalnie 64 ID mogą przejść do sprawdzenia następnego warunku: IsClientConnected(client) && IsClientInGame(client) && Te dwa warunki omówimy razem ponieważ są bardzo podobne. Connected sprawdza, czy gracz łączy się lub jest już połączony z serwerem. InGame sprawdza, czy jest już w grze. W teorii, InGame może wyeliminować nam więcej nieprawidłowych ID (ponieważ jeśli gracz już jest w grze to na pewno jest połączony, więc nie musimy sprawdzać już czy jest połączony) ale niestety jeśli gracz nie jest połączony z serwerem, to InGame wywala nam error w konsoli. Dzięki tym warunkom, eliminujemy załóżmy połowę nieprawidłowych ID jeśli serwer jest tylko w połowie zapełniony. Następne warunki eliminują jeszcze mniej przypadków: !IsFakeClient(client) && !IsClientSourceTV(client) IsFakeClient sprawdza, czy klient nie jest botem. Może nam to wyeliminować parę nieprawidłowych ID, chociaż 90% serwerów nie używa botów. No i ostatni warunek sprawdzający czy ID jest GOTV, może nam wyeliminować maksymalnie jeden przypadek. Dlatego znajduje się na końcu. Przykład z życia 2 W niektórych przypadkach, możemy jeszcze bardziej zoptymalizować nawet tak dobrze zrobiony warunek jak IsValidClient. Na myśl przychodzi mi konkretnie Nowy Cod by Linux oraz jego klasy. W praktycznie każdej klasie codmod znajduje się zmienna "ma_klase[client]", która określa czy dany klient ma daną klasę i czy może korzystać z jej umiejętności. Oczywiście będziemy również tam używali IsValidClient. Ale inaczej! Mamy kod: public Action OnTakeDamage(client, int &attacker, int &inflictor, float &damage, int &damagetype) { if(!IsValidClient(attacker) || !IsValidClient(client) || GetClientTeam(client) == GetClientTeam(attacker)) return Plugin_Continue; if (ma_klase[attacker]) { damage *= 1.5; return Plugin_Changed; } return Plugin_Continue; } Ten kod, który zaraz będziemy optymalizować na pierwszy rzut oka nie ma żadnych wad. Standardowo sprawdzamy czy klienci związani z akcją są na serwerze oraz czy nie są w tej samej drużynie, potem sprawdzamy czy atakujący posiada odpowiednią klasę, jeśli tak, to powiększamy zadane przez niego obrażenia o 50%. Przedstawiam bardziej zoptymalizowaną wersję: public Action OnTakeDamage(client, int &attacker, int &inflictor, float &damage, int &damagetype) { if(1 <= attacker <= MaxClients && ma_klase[attacker] && !IsFakeClient(attacker) && !IsClientSourceTV(attacker)) { if(!IsValidClient(client) || GetClientTeam(client) == GetClientTeam(attacker)) return Plugin_Continue; damage *= 1.5; return Plugin_Changed; } return Plugin_Continue; } 1. Zamiast korzystać ze standardowego IsValidClient, modyfikujemy tę funkcje tak, by zaraz po sprawdzeniu czy ID klienta mieści się w przedziale 1-64 sprawdzało się czy gracz ma klasę. Dlaczego? W trybie cod, jest dużo klas, minimalnie 7 jeśli nie 30. W najgorszym przypadku (7 klas) jeśli wybór klas przez graczy jest równomierny, przy pełnym serwerze 64 slotowym eliminujemy aż 64/7 ~ = 90% przypadków! Ten procent zwiększa się im klasa jest mniej popularna/im więcej klas jest na serwerze (im mniej graczy gra daną klasą w danym momencie tym więcej przypadków ten IF wyeliminuje). 2. Ponadto ten warunek jest "naturalny", nie pobiera żadnych danych tylko działa na zapisanych już w pluginie wartościach. 3. Rezygnujemy kompletnie z IsClientInGame oraz IsClientConnected. Dlaczego? Ponieważ jeśli jakikolwiek ID gracza atakującego (1 <= attacker <= MaxClients) oraz posiadającego klasę zadało jakiekolwiek obrażenia (jesteśmy przypominam w OnTakeDamage, funkcji która wywołuje się tylko jeśli ktoś otrzyma obrażenia) to musi być ten gracz podłączony do serwera! Podobnie moglibyśmy zrobić z IsValidClient sprawdzającego ID client'a. Jeśli ID otrzymuje obrażenia i ma ID klienta (w przedziale 1-64) to na pewno jest żywy i połączony z serwerem Bibliografia https://forums.alliedmods.net/showthread.php?t=313306 https://forums.alliedmods.net/showthread.php?t=188033 https://en.wikipedia.org/wiki/Short-circuit_evaluation
  17. 3 punkty
    jeżeli chcesz od razu po wyjęciu noża to możesz np. tak
  18. 3 punkty
    No ale z czym masz problem? Ze znalezieniem dokumentacji, z pobraniem kompilatora, z edycją plików czy samą kompilacją? Jak ktoś będzie wszystko za Ciebie robił, to niczego się nie nauczysz ?
  19. 3 punkty
    Witam wszystkich czytających ten temat! Jeśli tu trafiłeś (lub niemiły moderator Cię tutaj odesłał) zapewne chcesz się dowiedzieć jak poprawnie zatytułować swój temat który kiedyś napiszesz na naszym forum! Wbrew pozorom (i wbrew długości tego posta) koncepcja jest bardzo prosta i zrozumiała. Na pewno każdy załapie o co się tutaj rozchodzi i załapie jak ważne są tytuły nie tylko na forum ale także wszędzie indziej. 1. Po pierwsze musimy sobie odpowiedzieć na pytanie "Do czego w ogóle służy nazwa tematu?". Odpowiedzi są zwięzłe i jest ich kilka: Ten krótki tekst jest pogrubionym, największym i najbardziej wyróżniającym się elementem Twojego tematu. Dlatego ważnym jest, abyś zwrócił nim uwagę osób do których kierujesz swoją treść Poza zwróceniem na siebie uwagi, ważnym jest żebyś zwrócił uwagę tych konkretnych osób, które mogą być zainteresowane tematem. Jeśli nazwiesz temat zbyt ogólnikowo, masa użytkowników po przeczytaniu treści może pomyśleć sobie 'eh, to znowu nie to...', zirytują się i stracą swój czas Jeśli jednak nazwiesz swój temat konkretnie, zawierając w nim konkretny problem lub niszową dziedzinę, możesz znaleźć dużo ludzi, którzy pomyślą sobie ' Hej! To jest to w czym jestem dobry/tym jestem zainteresowany!", będą więc bardziej chętni do odwidzenia Twojego tematu i napisania w nim czegoś Od strony technicznej, przez nazwę tematu tworzy się link URL do strony oraz główny tytuł strony umieszczony w pasku przeglądarki. I dzięki dobrej nazwie, Twój temat może lepiej się pozycjonować w przeglądarkach. Pomagasz nam tym samym dotrzeć do większej liczby użytkowników oraz sprawiasz, że Twój rozwiązany problem zawarty w temacie pomoże jeszcze większej liczbie osób 2. Po drugie, możemy zadać sobie pytanie "Jakie są wytyczne jakie mam zastosować przy tytułowaniu?". Tutaj możemy zajrzeć do naszego regulaminu, "Pisanie postów" punkt 2: "Nazywaj tematy zgodnie z ich treścią. Po odczytaniu nazwy tematu każdy użytkownik powinien orientować się co jest w nim zawarte." Mówi nam to, żeby nie odbiegać treścią tematu od treści posta. Musi być spójnośc między obydwoma tekstami. Co więcej, każdy użytkownik po przeczytaniu nazwy powinien wiedzieć jaka jest mniej więcej treść całości. Oznacza to, że pewne konkretne rzeczy lub ważne informacje zawarte w poście muszą być zawarte w tytule. 3. Po trzecie mógłbyś zadać pytanie "...A są jakieś wytyczne jak NIE pisać tytułów?". No pewnie! Już mówię jakie są najczęstsze najgorsze z możliwych ogólników jakie można sobie wyobrazić: "Pomocy" - Ten tytuł pojawia się najczęściej. Nie mówi absolutnie NIC. Jeśli piszesz temat, to najprawdopodobniej potrzebujesz pomocy. Nie musisz pisać rzeczy oczywistych. Z czym potrzebujesz pomocy? Czego nie potrafisz zrobić? Gdzie konkretnie się coś zdarzyło? "Błąd/Error/Problem" - Tak, ta sama zasada co wyżej. Jeśli tytułujesz tak temat, nie załączasz absolutnie żadnych informacji. Równie dobrze mógłbyś nazwać temat kropką. ".". I nie byłoby różnicy. Gdzie jest błąd? Jaka jest treść błędu? Jak często występuje? Błąd w czym? "Crash " - Crash czego? Jakie są błędy? Kiedy występuje/Co go aktywuje? 4. Po czwarte "Czy są jakieś przykłady złych tytułów?" Oczywiście: https://go-code.pl/temat/508-crash/ https://go-code.pl/temat/342-temat-lamie-regulamin-ws-i-knife/ https://go-code.pl/temat/682-temat-lamie-regulamin-szukam-pluginu/ Jak widzimy, po tytule tematu nie można się ABSOLUTNIE domyślić o co może chodzić autorowi. Poprawne nazwy powinny brzmieć: "Crash serwera co parę minut (Exception reported: Native is not bound)" "Jak mam zainstalować plugin na skiny?" "Szukam pluginu na rangi !lvl" 5. "Jeśli miałbyś powiedzieć komuś w kilku słowach jak napisać dobrą treść tematu, co byś powiedział?" Po odczytaniu nazwy tematu każdy wszyscy powinni orientować się co jest w nim zawarte; Nazwa tematu powinna zawierać esencję problemu w nim zawartego; Skróć treść posta do jednego zdania nie pomijając przy tym ważnych kwestii; Zawrzyj najważniejszą techniczną treść w nazwie tematu;
  20. 3 punkty
    Opis Convary potrafią się nadpisać, dlatego warto sprawdzić czy na pewno posiadają pożądaną wartość. Plik z komendami należy umieścić w "configs/Master/Master_ConVars.txt". Nie ma potrzeby przeładowania pluginu, gdy chcemy dodać nowe komendy, gdyż wtyczka za każdym razem otwiera ponownie plik. Komenda sm_testcvar - wymagana flag "z" Plugin Przykładowy Config Przykładowy output dla powyższych komend Master_ConVars.sp Master_ConVars.txt
  21. 3 punkty
    Amunicję dodaje w timerze Timer_SetEquipAmmo wywoływanym przez Hook_OnWeaponEquipPost. Tam możesz sobie podebugować ile wynosi pierwotna (przed powiększeniem) wartość magazynku. Zakładam, że po prostu jeśli dostajesz tę samą broń do ręki, gra nie rejestruje żadnych zmian (to znaczy reset magazynku do pierwotnej wartości) natomiast nadal wykonuje się event equip'a broni, co za tym idzie jest wykonywana linia Weapon_SetPrimaryClip(weapon, Weapon_GetPrimaryClip (weapon)+iClipIncrease); która do aktualnego magazynku (już powiększonego) dodaje powiększenie. Rozwiązanie? A. Wklepać tablicę stałych wartości magazynku dla każdej broni i zamiast korzystać z Weapon_GetPrimaryClip();, korzystać ze stałej wartości pełnego magazynku wpisanego do tablicy. B. Zmienić plugin na skiny tak, by przed dodaniem "skina" (czyli nowej, tej samej broni) kasował tą poprzednią broń
  22. 3 punkty
    Zamień na: W tym momencie "if(g_cvDM_hp_vip_start.IntValue != 120)" jeżeli wartość Cvara nie jest równa 120 to wykona się akcja SetEntityHealth, a aktualnie jest równa 120, więc nic się nie wykona ;).
  23. 2 punkty
    Macie bo się kur** ośmieszacie tą grafiką widać ze robił to grafik w paint.exe
  24. 2 punkty
    O stary XD Te zmienne alokują jakieś 15MB pamięci 😮 Musisz to koniecznie poprawić, opierając kod na tablicach dynamicznych tak jak wyżej wspomniał @masnuwa_ni
  25. 2 punkty
    Widzę w tym pluginie sporo zapożyczeń z tego pluginu -> https://forums.alliedmods.net/showthread.php?t=87597 Praktycznie taki sam układ pliku konfiguracyjnego, część kodu, może dobrze byłoby podać źródło? Mimo to plus dla Ciebie za wykonaną pracę, nie omieszkam sprawdzić Twojej wersji
  26. 2 punkty
    https://forums.alliedmods.net/showthread.php?p=2537196
  27. 2 punkty
    @ErwinH2K wystarczy zakupić reklamę gracze wrócą. Po za tym to nie była moja winna, samo się to zrobiło.
  28. 2 punkty
    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!
  29. 2 punkty
    Wystarczyło poświęcić 5 minut, proszę bradzo. Deagle_Damage.smx Deagle_Damage.sp
  30. 2 punkty
    Cześć, Z tej strony Piotr. Po dość sporej przerwie w branży jednak tak się nie da. Nadmiar wolnego czasu i stare hobby powróciło, bez cs'a się jednak nie da. A więc wracam na stare śmieci i poszukuję jakiegoś ambitnego projektu związanego ze starym dobrym cs'em, (najlepiej jego najnowszą odsłoną, cs;go) Szukam czegoś z dojrzałą administracją, nie zamierzam walczyć z napalonymi 13 latkami, którzy nie potrafią nic samemu wykonać, oprócz uciążliwego piszczenia do mikrofonu, tylko zlece to jemu to tamtemu itp. Nie interesują mnie puste sieci, czy serwery które 24/7 świecą pustkami, a mają 6 slotów... Mam nadzieję, że wakacyjne oferty nie będą nawet zaśmiecały mi skrzynki... Szanuje Wasz cenny czas więc mam nadzieję, że i Wy mój. Coś o mnie: chłopaczek, ze sporym doświadczeniem w tej dziedzinie (student kierunku ściśle związanego z IT - PwR, programista z zawodu, wcześniej trochę sieci. Także takie bawienie się w sieć to nie jest żaden problem). Jestem osobą dość mocno dyspozycyjną, wiadomo aktywność spada w czasem, wiadomo każdy ma własne życie prywatne. Karabiny nie dadzą wyżyć a człowiek też czasem musi się odhamić. Ale poza tym prawie 24/7, bo praca przy komputerze plus często h/o(home office), po bliższym zapoznaniu podam kontakt telefoniczny i w razie "W" zawsze można do siebie przedzwonić. Rozważę każda propozycję co do sieci, lecz wiadomo interesuje mnie projekt gdzie mogę coś dać od siebie, pomóc doświadczeniem i wiedzą jaką już uzyskałem przez parę lat zabawy w tejże branży. Pozdrawiam i miłego piątku ?
  31. 2 punkty
    Nie wiem czemu, ale zrobiłeś mi dzień tym komentarzem XD.
  32. 2 punkty
    Kozak grafika
  33. 2 punkty
    To dobrze bo musiałbym się nieprzychylnie wypowiedzieć ^^ Powodzenia w szukaniu
  34. 2 punkty
    Dzień dobry czy administracja zawiera osoby które były właścicielami tej sieci ~5 lat temu?
  35. 2 punkty
    Witam wszystkich czytających ten temat! Jeśli tu trafiłeś (lub niemiły moderator Cię tutaj odesłał) zapewne chcesz się dowiedzieć jak poprawnie wybrać dział dla tematu który kiedyś napiszesz na naszym forum! Zaczynajmy! I. Kategorie Struktura naszego forum opiera się na kategoriach oraz działach. Nazwy kategorii to tytuły bloków zawierających działy. Określają one główną tematykę jaka jest omawiana w tematach zawartych w tych działach. Możemy je zobaczyć tutaj: Na naszym forum mamy parę kategorii które teraz wymienię i opiszę: "Nasze Sprawy" - Tutaj mają się znajdować wszystkie sprawy dotyczące naszego forum jako społeczności. Ekipa informuje tutaj o nowościach, można podyskutować o danym aspekcie, przywitać się z nowymi użytkownikami oraz zaproponować coś "Sourcemod Scripting" - Ta kategoria przechowuje ściśle programistyczne tematy. Użytkownicy mogą tutaj pisać artykuły dotyczące programowania w sourcepawnie, pomagać mniej zdolnym informatykom oraz wklejać przydatne stocki. Znajduje się tu również główny dział kanału Magneta na YouTube "Konfiguracja pluginów" - Kategoria dotyczy pluginów lecz nie od strony programistycznej, a bardziej od strony wgrywania na serwer, konfiguracji przez cvary i tym podobne. Użytkownicy tutaj mogą szukać pluginów lub paczek serwerowych. Tutaj przechowujemy również nasz zbiór pluginów. "Konfiguracja serwera" - Tutaj zamieszczone jest wszystko co dotyczy zarządzania serwerem. Metamod oraz Sourcemod, konfiguracja plików typu .cfg, aktualizacja serwera do najnowszej wersji to rzeczy tam należące. "Counter-Strike: Global Offensive" - Ta kategoria mieści w sobie wszystko co związane z grą CS:GO od strony gracza, czyli aktualizacje, nowinki, mistrzostwa, nowe tryby oraz publikacje serwerów publicznych. II. Działy Działy to bloki w których można pisać swoje tematy. Prawie każdy dział posiada swój rozległy opis, dlatego nie będę tutaj po kolei ich wypisywał. Dział wygląda tak: III. Jak wybrać poprawne miejsce na temat? Przejrzyj nazwy wszystkich kategorii i wybierz tę najbliższą Twojemu problemowi. Następnie przeczytaj nazwy działów w niej zawartych oraz ich opisy. Na pewno wybierzesz właściwie! Jeśli masz wątpliwości skontaktuj się z kimś z naszej ekipy. I nie martw się, nawet jeśli gdzieś popełnisz błąd, moderator postara się go naprawić!
  36. 2 punkty
    Rangi jak najbardziej bardzo pozytywne, warte ceny. Pozdro ?
  37. 2 punkty
    Możliwe, że już nie Laguje, kompletnie tam nie zaglądam na ich forum od bardzo dawna, sugerowałem się opiniami osób co zakupiły plugin, że ich serwer normalnie już chodzi bez skoków VAR. Wiem o tym. Jest ona ważna jedynie dla mnie, że jak ktoś ją złamie, nie otrzyma wsparcia i aktualizacji. Wartość prawna mnie nie interesuje.
  38. 2 punkty
    mp_playercashawards 0 <- Wtedy nie zarabiają gotówki i nie ma komunikatów
  39. 2 punkty
    Tutaj masz gotowe rozwiązania https://mygo.pl/topic/5448-skrypt-pod-gotv/?tab=comments#comment-21050 lub za pomocą pluginu https://forums.alliedmods.net/showthread.php?t=162910.
  40. 2 punkty
    Lepszy sposób na sprawdzenie czy gracz posiada daną flagę. int GetFlag() { char flag[10]; gc_VIPFlag.GetString(flag, sizeof(flag)); return ReadFlagString(flag); } Edit: Również nie ma potrzeby deklarować dynamicznej tablicy globalnie, gdyż tylko niepotrzebnie zajmuje pamięć. Dobrym nawykiem jest również. bool IsWarmup() { return (GameRules_GetProp("m_bWarmupPeriod") == 1); } bool IsValidClient(int iClient) { return (1 <= iClient <= MaxClients && IsClientInGame(iClient) && IsClientConnected(iClient) && !IsFakeClient(iClient) && !IsClientSourceTV(iClient)); } bool HaveWebSite(int client) { if (!IsValidClient(client)) return false; char name[MAX_NAME_LENGTH]; GetClientName(client, name, sizeof(name)); return (StrContains(name, WEB) != -1); } bool HaveFlag(int client) { int flag = GetFlag(); return view_as<bool>(GetUserFlagBits(client) & flag); } Nierówność przy pętli przechodzącej przez wszystkich graczy ma być domknięta. for (int i = 1; i <= MaxClients; i++)
  41. 2 punkty
    Hello, Temat powstaje dzięki kilku informatorom, którzy byli tak mili i udostępnili troszku dowodów na Pana który kryje się pod nickiem Roberrt. Znajdziecie tutaj również troszku informacji dot. użytkownka znanego pod nazwą Matix. Temat również zaprezentuje w jaki sposób wymienione osoby nabywają pieniądze poprzez sprzedawanie swoich kreacji do Sourcemod'a & jak bardzo niebezpieczne dla użytkowników one są. W pluginach znajdziemy między innymi rzeczy typu backdoory, tak też wasze serwery nie są bezpieczne! ? Na sam początek poniżej znajdziecie kilka informacji dot. Pana o nazwie Roberrt & jego sociale takie jak steam, discord, strony www pod jego nadzorem itp. Strony www; Serv4u.pl Pluginysm.pl Profile: Discord: Roberrt#8892 Steam: https://steamcommunity.com/id/imroberrt Facebook: Na sam początek zacznijmy od ataków na fora. Jednym z przykładów będzie dość popularne forum csgo, mowa tutaj o How2Kill.pl który niestety padł ofiarą zabaw pana Roberrt'a i jego kolegów. Otóż forum H2K jest w szerokim paśmie bardzo dobrze zabezpieczone, jednym z dość popularnych typów ataku na owe forum będzie atak strukturze L7 GET / który w bardzo prosty i łatwy sposób crashuje fora na silnikach takich jak apache, a nawet i nginx jeśli nie zostały dobrze skonfigurowane. Sądząć po samej konfiguracji serwera pana Roberrt'a możemy się dowiedzieć, że nie jest on zabardzo zjawiskową & doświadczoną osobą, kiedy owa osoba niestety nie zna podstawowej konfiguracji CloudFlare, która pomogła nam uzyskać kolejne adresy IP do analizy & porównania. Osobiście nie wiem jak daleko chcą owe osoby zajść poprzez tworzenie hostingu, który stoi na innym - jeszcze gorszym gównie, gdzie serwery sięgają kosztów 30zł. Stawianie swoich serwisów na hostingach takich jak mydevil czy ultimahost(webh) i staranie się udowodnić komuś, jaki to on i jego zespół jest profesjonalny, kiedy najprostrzej rzeczy takiej jak poprawna konfiguracja cloudflare'a jest dla nich problemem. www.serv4u.pl | 104.27.165.98 < - IP Cloudflare podpięte jedynie pod domene mail.serv4u.pl | 185.238.72.65 < - IP Główne serwera Mailowego pop.serv4u.pl | 185.238.72.65 < - IP Głowne serwera Pop smtp.serv4u.pl | 185.238.72.65 < - IP Główne serwera SMTP ns1.serv4u.pl | 185.238.72.65 < - DNS'y pointujące do serwera gdzie znajduje się główna domena ns2.serv4u.pl | 185.238.72.65 < - DNS'y pointujące do serwera gdzie znajduje się główna domena Samo to dało mi do myślenia, że jednak nie mamy tutaj doczynienia z kimś zaawansowanym, więc śmiechłem i oplułem. Kolejnym ku******m zachowaniem ze strony Pana Roberrt'a & Matixa to walenie w strony, (go-code) i powodowanie downtimeów z powodu takiego, że administracja Go-Code zabroniła udostępniania pluginów z Pluginysm.pl na stronie go-code z powodu naruszenia bezpieczeństwa użytkowników. Pan Roberrt postanowił wykorzystać ową słabość H2K & atakować forum powodując downtime & stwarzając problemy administracji h2k. Niżej podaje Wam mały wicinek logów pozyskanch od H2K: [Wed Jun 26 02:17:16.883292 2019] [core:crit] [pid 17918] (13)Permission denied: [client 137.74.1.24:0] AH00529: /home/xxxxx/public_html/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable and that '/home/xxxxx/public_html/' is executable, referer: https://go-code.pl/profil/60-linux/aktywnosc/?type=forums_topic_post&change_section=1 IP Atakującego --> 137.74.1.24 - - [26/Jun/2019:02:04:21 +0200] "GET /sitemap.php HTTP/1.1" 403 - "https://go-code.pl/profil/60-linux/aktywnosc/?type=forums_topic_post&change_section=1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36 OPR/60.0.3255.151" IP Atakującego zostało przeanalizowane & doprowadziło najpierw do strony panelu ( http://137.74.1.24/auth/login ). Z początku nie mówiło nam to wiele, jako owym adres IP nie prowadził do niczego. Lecz po jakimś czasie zorientowaliśmy się do czego tak naprawdę jest owym Panel poprzez analizę front-endu samego Panelu. Informacje, jakie mogliśmy tam zgromadzić prowadziły prosto do strony https://serv4u.pl która jest pod okiem Roberrt'a. Oczywiście po zorientowaniu się, że pan Robert zostawił w tytule strony nazwę domeny serv4u usuną ją aby ominąć problemów, jednak zmiana tytułu mało troszku tutaj daje, no bo jednak co wchodzi do internetu; niestety tam zostaje. Po analizie ciasteczek strony możemy w prosty sposób wywnioskować, jak wyglądała strona & jakie zmiany zostały dodane do naszych ciasteczek w ostatnim czasie. Content: "Zjg3ZWNkYzViMWExOWNmYzRmZjU4MjE4In0%3D" --> Cookie content GET /: content"Zjg3ZWNkYzViMWExOWNmYzRmZjU4MjE4In0%3D" --> Cookie content GET /: content"http://137.74.1.24/auth/login" --> Webserver content HTTP/1.1 Connection = "137.74.1.24" ":" 1#(Zjg3ZWNkYzViMWExOWNmYzRmZjU4MjE4In0%3D) --> Webserver content vs Cookie content timed out HTTP/1.1 Cached content weburi/1.1"https://serv4u.pl/" --> Cached content Można jeszcze pobawić się w kilka innych sposobów; wynik jest taki sam, zabawę pozostawiam wam. Alegacje dot. pluginów sprzedawanych z backdoorami również nie są rzeczą, którą powinniśmy pomijać jako, że Wasze serwery są skazane na ataki/przekierowania itp. jeśli używaliście/używacie pluginów ze strony pluginysm.pl, niżej znajdziecie małe adnotacje dot. owych alegacji. Post użytkowników Allienmods.net Osoby używające lub te, które za swoich czasów używały pluginów z owej strony są proszone o wyczyszczenie serwerów z tego śmietnika i dokładny skan plików & zmianę danych aby uniknąć nieprzyjemności. Niżej dodaje kilka screenów z rozmowy pomiędzy Roberrt'em a Mesharskim (właścicielem H2K) Osobiście nie polecam, jebie i pluje.
  42. 2 punkty
    Pozwolę sobie jeszcze specjalnie dla tego tematu przypomnieć wszystkim niektóre punkty regulaminu:
  43. 2 punkty
    Tak, miałem dostęp do konta Mesharskiego przez ~15 minut na przeczytanie całej konwersacji z Robertem. Całkiem zabawna konwersacja daje okejke ? https://imgur.com/a/1ij1jSq a tutaj link do ss`a podanego tam https://i.imgur.com/wI1RuHE.png
  44. 2 punkty
    Tak to jest 100% prawda i słuszna uwaga. Chciałbym zaznaczyć, że ataki na go-code były w momencie, kiedy na początku pluginysm.pl się u nas chciało reklamować i tematy zostały u nas skasowane, wtedy poprzez skrypt na serwerze dedykowanym pan Robert oraz pan Matix crashowali stronę, PRZEZ CO padła druga strona, która również była na hostingu go-code bądź nawet dalej jest (Tak byłem wtedy na ich serwerze Discord i sami przez mikrofon mi się o tym chwalili więc wyjebane mam jak się tutaj wybronią wiem jak jest, i sporo innych osób też o tym wie). Atakowanie mojego serwera Dedykowanego, na którym stoją 3 domeny jest ciosem powyżej pasa bo moje forum ma gówno wspólnego z wszystkim a w sumie z niczym bo tak naprawdę kompletnie nic im nie robię, oni szukają dram na siłę i nie wiadomo czego jeszcze, szczeniackie zachowanie na tych forach i nic więcej, podczas godzinnej rozmowy z panem Robertem na discordzie, całą rozmowę widział,@Brum Brum bo otrzymał dostęp do mojego konta Discord, nie otrzymałem odpowiedzi na żadne z moich pytań, i zostało potwierdzone wiele rzeczy, cała ta akcja to jest po prostu wstyd i szukanie konfliktów ze mną na siłę. Jestem osobą uczciwą i nie mam zamiaru dawać sobą pomiatać, jeżeli kiedyś coś robiłem w przeszłości, bo mam swoje za plecami (Każdy ma swoje głupoty za plecami) o tym również wie @Brum Brum za to mogę przeprosić czyli rok 2k16 i 2k17. Ode mnie to tyle, spędziliśmy sporo dni, by zebrać w kupę wszystko i przeanalizować wszystkie ataki i tak dalej, nie ma argumentu tutaj który mógłby wybronić pana Roberta, oczywiście całą rozmowę od A do Z mogę wysłać na pw komu tam chce, żadnych przeróbek ani nic, mogę udostępnić na x minut nawet dostęp do konta, nie mam zamiaru brać udziału w tym cyrku na tym community. PS: Przed napisaniem do niego na discordzie tutaj na tym SS było zamiast napisu Panel, był napis serv4u.pl I Przekierowanie na stronę hostingową, po czym Robert od razu zmienił nazwę i usunał przekierowanie, dziwny zbieg okoliczności... :D
  45. 2 punkty
    Kilka pomysłów/porad: - Sprawdź najpierw, czy samo usunięcie broni Ci działa, możliwe że błąd w konsoli (który oznacza że byt broni tworzymy w innym bycie który jest stały, SOLID) właśnie tego dotyczy - Dlaczego tworzysz broń jak byt? Nie prościej jest po prostu... dać graczowi tę broń którą kasujesz i nadać jej odpowiednie właściwości? Przecież te właściwości i tak nadajesz po stworzeniu bytu, więc nie powinno to mieć zbytniej różnicy, a zmniejszy ilość operacji - Jeśli nadajemy bytowi broni jakieś właściwości, to dlaczego dopiero w połowie ich nadawania sprawdzamy czy IsValidEdict? To samo pytanie dotyczy się dania klientowi broni, dlaczego dzieje się to w połowie funkcji a nie na jej końcu? - Jeśli zamiast g_iClientKnife/g_iClientAK47 użyłbyś g_iClientWeapon[id_broni][client] (dwu wymiarowej tablicy zawierającej ID skinu dla każdego klienta oraz każdej broni zamiast dla każdej broni używać nowej zmiennej), mógłbyś wtedy użyć CS_AliasToWeaponID i zamiast masy else if'ów kod na nadanie skina nowej broni wyglądałby mniej więcej tak: SetEntProp(weapon, Prop_Send, "m_nFallbackPaintKit", g_iClientWeapons[CS_AliasToWeaponID(sWeapon)][client]); I ta jedna linia obsługiwałaby wszystkie bronie. Minus jest taki, że nadal tablica g_iClientWeapons jest tworzona dla wszystkich broni więc zajmuje na pewno więcej pamięci, bo zajmuje miejsce nawet dla broni dla których skinów nie używasz. Ale jeśli nawet byś jej użył to możesz ją lekko "zoptymalizować" i skrócić tablicę bo według listy broni CSWeaponID nie trzeba przecież nadawać skinów dla granatów które akurat znajdują się na samym końcu. Wtedy tablica skraca się z 55 miejsc na 51 - Możesz ukrócić sobie pracę w elseifach i zamiast podwójnie sprawdzać M4A1, użyj StrContains na string "weapon_m4a1"
  46. 2 punkty
    Oto wycinek z naszej dokumentacji: /** * Flagi dostêpu dla admina. */ enum AdminFlag { Admin_Reservation = 0, /**< Rezerwacja slota */ Admin_Generic, /**< Prawa standardowego admina */ Admin_Kick, /**< Daj graczowi kicka */ Admin_Ban, /**< Zbanuj gracza */ Admin_Unban, /**< Odbanuj gracza */ Admin_Slay, /**< Zgladz/zabij/zadaj obrazenia innemu graczowi */ Admin_Changemap, /**< Zmien mape */ Admin_Convars, /**< Zmiana podstawowych convarow */ Admin_Config, /**< Zmiana konfiguracji */ Admin_Chat, /**< Specjalne przywileje przy pisaniu na czacie */ Admin_Vote, /**< Specjalne przywileje przy glosowaniu */ Admin_Password, /**< Ustawianie hasla serwera */ Admin_RCON, /**< Uzywanie RCON */ Admin_Cheats, /**< Zmiana komendy sv_cheats i uzywanie jej komend */ Admin_Root, /**< Domyslnie dostep do wszystkiego */ Admin_Custom1, /**< Pierwsza flaga specjalna */ Admin_Custom2, /**< Druga flaga specjalna */ Admin_Custom3, /**< Trzecia flaga specjalna */ Admin_Custom4, /**< Czwarta flaga specjalna */ Admin_Custom5, /**< Piata flaga specjalna */ Admin_Custom6, /**< Szosta flaga specjalna */ /* --- */ }; Admin_Root ma w tym enumie numer 14
  47. 1 punkt
    Sądząc po stylu wypowiedzi i rozumowania to jakiś max 12 latek, on przez "autorski plugin" rozumie chyba - napisany przez kogoś obcego a podpisany jego nickiem Tak można wywnioskować gdy napisał to wyślij mi taką bez "yamakashi" czyli de facto nawet nie wie jak zmienić autora?
  48. 1 punkt
    Halo halo @MAGNET nie ma tutaj zdefiniowanego IsValidClient!
  49. 1 punkt
    Spis errorlogów i co one oznaczają? Poniżej będzie znajdował się spis wszystkich errorlogów, ich polskie tłumaczenie oraz jak właściwie zabrać się za rozwiązanie problemów, które ukazują. Oryginał znalazłem tutaj. Zachęcam do pomocy w tłumaczeniu, temat jest długi jeśli otworzy się spoiler, więc proszę o cierpliwość jeśli będziecie przewijać w dół ? Legenda Jak używać tego tematu? Jak pomóc z uzupełnianiem błędów? Spis errorów 001-182 183-196 200-240 Hej! Uwaga! Jeśli nadal nie jesteś pewny co oznacza pewien błąd, napisz osobny temat w dziale Pytania na temat programowania z prośbą o dogłębne wytłumaczenie problemu! Na pewno pomożemy!
  50. 1 punkt
    #include <sdkhooks> #pragma semicolon 1 #pragma newdecls required bool g_bGoodMap; public void OnMapStart() { g_bGoodMap = false; char sMap[128]; GetCurrentMap(sMap, sizeof(sMap)); if(StrEqual(sMap, "Twoja_Mapa") || StrEqual(sMap, "Twoja_Mapa2")) { g_bGoodMap = true; } } public void OnClientPutInServer(int client) { SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); } public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) { if(!g_bGoodMap) return Plugin_Continue; if(damagetype & DMG_FALL) { if(float(GetClientHealth(victim)) - damage < 1.0) { SetEntityHealth(victim, 1); return Plugin_Handled; } } return Plugin_Continue; }
Ten Ranking jest ustawiony na Warszawa/GMT+02:00

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

×
×
  • Dodaj nową pozycję...