[ROZWIĄZANE] Dużo zmiennych, dużo modeli,...
oeN.
30.05.2015
Witam,
Znowu przychodzę z problemem odnośnie wielu zmiennych które mnie zaczynają irytować. Szybki opis:
Posiadam plugin który w bazie zapisuje graczowi jakie posiada modele, aktualnie struktura tabeli wygląda mniej więcej tak:
Nick | skin1 | skin2 | skin3 | skin4 | skin5 [...] skin12
I już jest lipa bo serwer odczuwa jak ma nagle to wszystko zapisywać.
Druga sprawa to zmienne...
new g_PlayerSkin1[33], g_PlayerSkin2[33], g_PlayerSkin3[33], g_PlayerSkin4[33], g_PlayerSkin5[33]; new g_PlayerSkin6[33], g_PlayerSkin7[33], g_PlayerSkin8[33], g_PlayerSkin9[33], g_PlayerSkin10[33]; new g_PlayerSkin11[33], g_PlayerSkin12[33];
No jest lipa, prawda? Czym bardziej że mam zamiar dodawać ich więcej a boję się że w końcu będzie się źle działo i crash na crashu.
I teraz tak, można by to jakoś skrócić bez problemu gdyby nie jedna rzecz, menu w którym wybieramy jaki model chcemy używać i wybrany model się zapisuje do zmiennej aby go używać aż się nie zmieni, tutaj ok, mam do tego jedną zmienną ale żeby wybrać model najpierw trzeba go mieć, więc używam tego:
if(item == 0) return ITEM_ENABLED; else if(item == 1 && !g_PlayerSkin1[id]) return ITEM_DISABLED; else if(item == 2 && !g_PlayerSkin2[id]) return ITEM_DISABLED; else if(item == 3 && !g_PlayerSkin3[id]) return ITEM_DISABLED; else if(item == 4 && !g_PlayerSkin4[id]) return ITEM_DISABLED; else if(item == 5 && !g_PlayerSkin5[id]) return ITEM_DISABLED; else if(item == 6 && !g_PlayerSkin6[id]) return ITEM_DISABLED; else if(item == 7 && !g_PlayerSkin7[id]) return ITEM_DISABLED; else if(item == 8 && !g_PlayerSkin8[id]) return ITEM_DISABLED; else if(item == 9 && !g_PlayerSkin9[id]) return ITEM_DISABLED; else if(item == 10 && !g_PlayerSkin10[id]) return ITEM_DISABLED; else if(item == 11 && !g_PlayerSkin11[id]) return ITEM_DISABLED; else if(item == 12 && !g_PlayerSkin12[id]) return ITEM_DISABLED; return ITEM_ENABLED;
No i właśnie, co z tym zrobić? Ktoś coś podpowie?
Rivit
31.05.2015
Popatrz jak w stockowym cod mod są przechowywane bronie gracza, minusem jest tylko to że ograniczenie jest do 32 lub 31
sebul
31.05.2015
wiwi249
31.05.2015
g_PlayerSkin[33][12]
Ale wtedy musialbys liczyc skiny od 0 albo od 1 i ustawić rozmiar drugiego indeksu na 13.
I wtedy ten callback można zrobić pętlą.
oeN.
31.05.2015
Myślałem właśnie nad sumą bitową ale byłby wtedy problem z zapisem do bazy, tak mi się wydaje.
Tu nawet nie trzeba sumy bitowej czy tablic dynamicznych, po prostu zapisuj do jakiejś zmiennej jakąś wartość na podstawie której będziesz komuś dawał określony model.
Właśnie to robię, mam w cholerę zmiennych i każda zmienna to inny model, tylko pomyśleć co by było przy 30 modelach, armageddon.
g_PlayerSkin[33][12]Ale wtedy musialbys liczyc skiny od 0 albo od 1 i ustawić rozmiar drugiego indeksu na 13.
I wtedy ten callback można zrobić pętlą.
To nie jest taki głupi pomysł i na 99% wygląda na to że się sprawdzi.
Rivit
31.05.2015
Myślałem właśnie nad sumą bitową ale byłby wtedy problem z zapisem do bazy, tak mi się wydaje.
No właśnie nie...
1<<x, (gdzie x to jakaś liczba) to nic innego jak zwykła liczba, poczytaj o przesunięciu bitowym, także w zapisie tych skinów będziesz miał tylko jedną wartość, czyli sumę bitową wszystkich skinów.
Przetestuj to i zobacz co Ci wypisze na czacie:
#include amxmodx public plugin_init() { register_plugin("","","") register_clcmd("say /bitsuma", "a") } public a(id) { client_print(id, 3, "1<<2 to tak naprawdę: %i", 1<<2) client_print(id, 3, "1<<12 to tak naprawdę: %i", 1<<12) client_print(id, 3, "1<<30 to tak naprawdę: %i", 1<<30) }
oeN.
31.05.2015
Ja wiem jak działają operacje na sumach bitowych, jest to optymalne i w ogóle ale też się ciężko na nich operuje.
Edited by oeN., 31.05.2015 18:56.
GwynBleidD
01.06.2015
Ja wiem jak działają operacje na sumach bitowych, jest to optymalne i w ogóle ale też się ciężko na nich operuje.
No raczej nie...
Czy sprawdzanie czy gracz posiada daną flagę uprawnień jest niewygodne w AMXX? A działa to właśnie na bitach.
Zamiast tego:
new g_PlayerSkin1[33], g_PlayerSkin2[33], g_PlayerSkin3[33], g_PlayerSkin4[33], g_PlayerSkin5[33]; new g_PlayerSkin6[33], g_PlayerSkin7[33], g_PlayerSkin8[33], g_PlayerSkin9[33], g_PlayerSkin10[33]; new g_PlayerSkin11[33], g_PlayerSkin12[33];
umieszczasz to:
new g_PlayerSkins[33];
Zamiast tego:
if(item == 0) return ITEM_ENABLED; else if(item == 1 && !g_PlayerSkin1[id]) return ITEM_DISABLED; else if(item == 2 && !g_PlayerSkin2[id]) return ITEM_DISABLED; else if(item == 3 && !g_PlayerSkin3[id]) return ITEM_DISABLED; // ... i tak dalej i tak dalej ...
umieszczasz to:
if (item > 0 && item <= 32 && !g_PlayerSkins[id] & (1<<(item - 1)) { return ITEM_DISABLED; return ITEM_ENABLED; // NIC WIĘCEJ!
Dalej twierdzisz, że jest na tym operować gorzej?
Jak nie lubisz posługiwać się operatorami bitowymi to można sobie odpowiednie aliasy i funkcje do tego utworzyć.
Polecam stworzyć kilka funkcji:
/** 1. sprawdzenie czy gracz posiada model: */ stock user_hasSkin(id, skin) { return g_PlayerSkins[id] & (1 << skin) == (1 << skin) // porównanie jest dodane po to, by zawsze otrzymywać 1 lub 0, co czasem może mieć znaczenie } /** 2. przypisanie graczowi modelu: */ stock user_giveSkin(id, skin) { g_PlayerSkins[id] |= (1 << skin) } /** 3. odebranie graczowi modelu: */ stock user_takeSkin(id, skin) { g_PlayerSkins[id] &= ~(1 << skin) } /** 4. wyczyszczenie graczowi modeli: */ stock user_takeSkin(id, skin) { g_PlayerSkins[id] = 0; } // 2 dodatkowe funkcje, wydają się na pozór mało przydatne ale za chwilę się okaże do czego służą /** 5. export modeli (do zapisu w nvault, bazie danych itp): */ stock user_writeSkin(id, string[], length) { num_to_str(g_PlayerSkins[id], string, length); } /** 6. import modeli (z bazy danych, nvault itp): */ stock user_readSkin(id, string[]) { g_PlayerSkins[id] = str_to_num(string); }
W ten sposób posługujesz się bardzo wygodnymi funkcjami.
Mówią ludzie o limicie do 32 czy tam do 31 itemów. Owszem istnieje taki. Nie jestem pewien czy maksymalnie możemy przechować 32 czy 31 bitów (ostatni bit jest wykorzystywany jako znak liczby i może stanowić problemy, ale nigdy tego w praktyce w AMXX nie sprawdzałem) ale...
new g_PlayerSkins[33][2];
już mamy 62 itemy maksymalnie I tu się wyjaśnia dlaczego stworzyłem 2 dodatkowe funkcje (5 i 6) do eksportu i importu. Wystarczy teraz te 6 funkcji zmodyfikować:
/** 1. sprawdzenie czy gracz posiada model: */ stock user_hasSkin(id, skin) { return g_PlayerSkins[id][skin/31] & (1 << (skin % 31)) == (1 << (skin % 31)) // porównanie jest dodane po to, by zawsze otrzymywać 1 lub 0, co czasem może mieć znaczenie } /** 2. przypisanie graczowi modelu: */ stock user_giveSkin(id, skin) { g_PlayerSkins[id][skin/31] |= (1 << (skin % 31)) } /** 3. odebranie graczowi modelu: */ stock user_takeSkin(id, skin) { g_PlayerSkins[id][skin/31] &= ~(1 << (skin % 31)) } /** 4. wyczyszczenie graczowi modeli: */ stock user_takeSkin(id, skin) { for (new i=0; i<2; ++i) g_PlayerSkins[id][i] = 0; } // 2 dodatkowe funkcje, wydają się na pozór mało przydatne ale za chwilę się okaże do czego służą /** 5. export modeli (do zapisu w nvault, bazie danych itp): */ stock user_writeSkin(id, string[], length) { new count = 0; for (new i=0; i<2; ++i) { count += num_to_str(g_PlayerSkins[id][i], string[count], length); string[count] = ' '; } string[count] = '^0'; } /** 6. import modeli (z bazy danych, nvault itp): */ stock user_readSkin(id, string[]) { new count = 0; new left[16], right[256]; for (new i=0; i<2; ++i) { strtok(right, left, 15, right, 255) g_PlayerSkins[id][i] = str_to_num(left); } }
W ten sposób nie musisz nic więcej zmieniać w kodzie (no może prócz wielkości tablicy na string do zapisania w nvault).
Pamiętaj tylko, żeby istniejący nvault przekonwertować. Możesz to zrobić w prosty sposób:
1. stwórz oddzielny plugin
2. zainstaluj i użyj w nim nVault Utility
3. wymyśl sobie jakiś specjalny klucz w którym będziesz przechowywał wersję pliku (musi być on unikalny - upewnij się żeby dla żadnego gracza się taki klucz nie zapisał. Dla przykładu użyj na jego początku czegoś, co nigdy nie wystąpi w nicku gracza, adresie IP ani steam ID)
4. odczytaj klucz wcześniej wymyślony, jeśli go nie ma to przyjmij że nvault jest w starej (pierwotnej) wersji. Jeśli jest, odczytaj wartość żeby się dowiedzieć jaką wersję masz.
5. Dokonaj konwersji (jeśli konieczna), lecąc po wszystkich kluczach w nvault (za pomocą Utility) i zmieniając format.
Plugin po udanej konwersji wyłączyć. Na przyszłość jak coś będziesz w pliku zmieniał to masz gotową bazę i zapisaną wersję
Rivit
01.06.2015
I czy zamiast tworzenia bool[33] to mogę właśnie na sumach bitowych? Czy braknie miejsca dla ostatniego
GwynBleidD
01.06.2015
Gwyn, kocham Cię, te stocki wykorzystam do czegoś, jak zbadać jaki jest limit?
Jaki limit? Limit tego ile możesz przechować bitów w 1 zmiennej? Spróbować przechować i sprawdzić czy wyszło
I czy zamiast tworzenia bool[33] to mogę właśnie na sumach bitowych? Czy braknie miejsca dla ostatniego
Zabraknie...
oeN.
01.06.2015
Wszystko za wszystkich robisz
No co mogę powiedzieć, dziękuje Ci bardzo, problem rozwiązany, można zamknąć.
MAGNET
04.06.2015
Ten temat został zamknięty przez moderatora.
Powód: Pomoc udzielona
Jeśli się z tym nie zgadzasz,

Z pozdrowieniami,
Zespół AMXX.PL