[ROZWIĄZANE] Usuwanie stworzonego 'ent...
Najlepsza odpowiedź sebul 15.01.2015 23:06
psilocybe
15.01.2015
Nie mogę znaleźć dobrego przykładu.
Sprawa wygląda tak:
Na mapie tworzy się jakaś liczba entity 'info_target' ze zmienionym stringiem 'classname', na koniec rundy usuwam w pętli enty z tym 'classname' i wszystko jest ok.
Teraz chcę napisać funkcję która usunie mi mój entity np. 5 sekund po jego spawnie, myślałem że to proste będzie ale coś jest bardzo nie tak
Moment utworzenia entity:
new ent = create_entity("info_target") entity_set_string(ent, EV_SZ_classname, "w_box")
No i tu dałem taska za 5 sekund, a funkcja którą uruchamiał to coś takiego:
public killBox(ent) { if(is_valid_ent(ent)) { remove_entity(ent); } }
Funkcja usuwała wybranego enta który "uruchomił" task, ale np. w losowym momencie (ok. 1-2 minut od startu mapy) crash serwera, brak logów a w konsoli serwera tylko 'Segmentation Fault'.
Jeszcze raz w skrócie, tworzę enta (create_entity), nadaję mu swój classname (w_box) i nakazuje mu za 5 sekund (set_task) zniknąć z mapy (remove_entity)
Jak to wykonać?
MAGNET
15.01.2015
Była taka fajna funkcja od pobierania id enta przez nazwę i było to w klasie Replikant CODMOD. Piszę z tel i nie mam jak tam to podejrzeć.
DarkGL
15.01.2015
psilocybe
15.01.2015
Dark'u na pewno przez to, sprawdziłem.
Co do tworzenia samego enta to ciekawego nic tam nie ma:
new Float:fVelocity[3], Float:fOrigin[3] entity_get_vector(id, EV_VEC_origin, fOrigin) VelocityByAim(id, 34, fVelocity) fOrigin[0] += fVelocity[0] fOrigin[1] += fVelocity[1] VelocityByAim(id, 300, fVelocity) new ent = create_entity("info_target") entity_set_string(ent, EV_SZ_classname, "w_box") entity_set_model(ent, "models/w_box3.mdl") entity_set_int(ent, EV_INT_movetype, MOVETYPE_TOSS) entity_set_int(ent, EV_INT_solid, SOLID_TRIGGER) entity_set_vector(ent, EV_VEC_origin, fOrigin) entity_set_vector(ent, EV_VEC_velocity, fVelocity) entity_set_float(ent, EV_FL_nextthink, halflife_time() + 0.01) set_task( 2.0, "killBox", ent )
Teraz w tasku killBox dałem sprawdzenie współrzędnych enta który powstał.
public killBox(ent) { if(is_valid_ent(ent)){ new vec[3]; entity_get_vector(ent,EV_VEC_origin,Float:vec); client_print(0, print_chat, "[ORIGIN] x: %f y: %f z: %f",vec[0], vec[1], vec[2]); } }
No i śmieszna sytuacja bo współrzędne mi pokazuje prawidłowe, za każdym razem inne, czyli zakładam że prawidłowo pobiera origins entity który uruchomił task.
Wystarczy że dodam pod client_print funkcję remove_entity(ent) i usuwa mi tego ent'a - ale serwer za chwile crashuje, losowo ale nigdy od razu.
wooDy.
15.01.2015
public killBox(ent) { if(is_valid_ent(ent)){ new Float:vec[3]; entity_get_vector(ent,EV_VEC_origin,vec); client_print(0, print_chat, "[ORIGIN] x: %.2f y: %.2f z: %.2f",vec[0], vec[1], vec[2]); remove_entity(ent); } }
Nie tak powinno być?
Petpat
15.01.2015
public killBox(ent) { if(is_valid_ent(ent)){ new Float:vec[3]; entity_get_vector(ent,EV_VEC_origin,vec); client_print(0, print_chat, "[ORIGIN] x: %.2f y: %.2f z: %.2f",vec[0], vec[1], vec[2]); remove_entity(ent); } }Nie tak powinno być?
Czytaj ze zrozumieniem napisał wyraźnie
"Wystarczy że dodam pod client_print funkcję remove_entity(ent) i usuwa mi tego ent'a - ale serwer za chwile crashuje, losowo ale nigdy od razu."
wooDy.
15.01.2015
psilocybe
15.01.2015
@wooDy, print_chat tylko do testów używam więc tu nie ma to znaczenia.
Wszystko zdaje się być ok, a to że crashuje sprawdzałem i lokalnie i na serwerze, po "zablokowaniu" wykonywania funkcji która usuwa enta plugin nie crashuje (kilka godzin bez żadnego erroru już działa).
Poza tym, usuwam enty na koniec rundy, przy 'touch' itp. nigdy nie crashuje - problem jest z tym taskiem.
Mi się wydaje że po prostu brakuje tu czegoś, jakiś szczegół albo nie wiem, brak warunku else?
Teraz dałem taką testową funkcję:
public killBox(ent) { if(is_valid_ent(ent)){ new vec[3]; entity_get_vector(ent,EV_VEC_origin,Float:vec); new name[64]; //dla pewności 64 entity_get_string(ent,EV_SZ_classname,name,63); client_print(0, print_chat, "[TEST] x: %f y: %f z: %f name: %s",vec[0], vec[1], vec[2], name); client_print(0, print_chat, "[TEST] Usuwam entity o ID: %d", ent); remove_entity(ent); } else{ client_print(0, print_chat, "[TEST] Nie znaleziono entity o ID: %d", ent); } return PLUGIN_HANDLED }
No i pokazuje prawidłowe współrzędne, prawidłowy 'classname', prawidłowe ID enta, usuwa, ent znika - no i crash następuje tak jak pisałem losowo w ciągu około minuty, czasem dłużej, czasem przy nowej rundzie. Brak error_log, debug włączony, w konsoli 'Segmentation Fault'
Dodam, że jeżeli stworzę 10 entów w odstępach co 1 sekundę to usuwa po kolei tak jak chciałem - nie wiem co jest nie tak. Może w końcu debug wypluje jakieś logi
sebul
15.01.2015
I taka uwaga, o ile to może i działa
new vec[3]; entity_get_vector(ent,EV_VEC_origin,Float:vec);to jednak prawidłowo powinno się pisać tak
new Float:vec[3]; entity_get_vector(ent,EV_VEC_origin,vec);Przy tworzeniu zmiennej powinno być widać jaki to będzie "typ".
psilocybe
15.01.2015
@sebul, poprawione, mój błąd Wracając do usuwania w innych momentach to najczęściej tak:
register_touch("w_box", "player", "touch_box");
public touch_box(ent, id) { if(!is_valid_ent(ent) || !is_user_alive(id)) { return PLUGIN_CONTINUE } if(is_user_alive(id)) { client_cmd(id, "spk %s", beep); remove_entity(ent) } return PLUGIN_CONTINUE }
Kod jest bardziej uwarunkowany ale usunąłem to co nie ma znaczenia.
Najlepsza odpowiedź
sebul
15.01.2015
psilocybe
16.01.2015
Czyli przed usunięciem enta w innych funkcjach dodaje:
if( task_exists(ent) ) { remove_task(ent); }
Poczekałem 50 minut dla pewności, nie crashuje
Możliwe że to jest to. Raczej na pewno.
Jeszcze dla jasności pytanie, bo na koniec rundy też usuwam wszystkie enty ale wygląda to nieco inaczej, pytanie czy dobrze dodałem usuwanie task'a? Ma to sens?
To jest w funkcji round_end:
new wBox = find_ent_by_class(-1, "w_box"); // Wyszukuje ID enta po classname while( wBox> 0 && is_valid_ent(wBox) ) { remove_entity(wBox); wBox= find_ent_by_class(-1, "w_box"); if( task_exists(wBox) ) { remove_task(wBox); } }
"Komplikować" to się "komplikuje" ale czy poprawnie to jest napisane?
sebul
16.01.2015
new wBox = -1 // Wyszukuje ID enta po classname while( (wBox = find_ent_by_class(wBox, "w_box")) && is_valid_ent(wBox) ) { remove_entity(wBox); remove_task(wBox); }ale dobrze by było, żebyś też tego taska jakoś przerobił na bardziej unikalnego, czyli daj sobie gdzieś na górę
#define TASK_KILLENT 473825i potem tego wszędzie do taska używasz, czyli chociażby
public killBox(ent) { ent -= TASK_KILLENT; if(is_valid_ent(ent)) { remove_entity(ent); } }
GwynBleidD
16.01.2015
Nope!Tak krócej
new wBox = -1 // Wyszukuje ID enta po classname while( (wBox = find_ent_by_class(wBox, "w_box")) && is_valid_ent(wBox) ) { remove_entity(wBox); remove_task(wBox); }
remove_task powinno być PRZED remove entity. remove_entity zmienia wartość wBox na -1! Przez co nie usuniemy taska, bo taki nie istnieje.
ale dobrze by było, żebyś też tego taska jakoś przerobił na bardziej unikalnego, czyli daj sobie gdzieś na górę
#define TASK_KILLENT 473825i potem tego wszędzie do taska używasz, czyli chociażbypublic killBox(ent) { ent -= TASK_KILLENT; if(is_valid_ent(ent)) { remove_entity(ent); } }
Ma to sens TYLKO wtedy, gdy mamy kolizję numerów tasków w jednym pluginie. Inne pluginy, jeśli nie szukają specjalnie, tasków obcych nie widzą. A nawet jeśli to szkoda się silić na wymyślanie cyferek typu 473825, wystarczy po prostu policzyć ile ID tasków użyjemy i zachować ciągłość. Jeśli nie jesteśmy w stanie przewidzieć (np jak w tym przypadku, entów może być naprawdę sporo i mogą mieć różne ID) to taką grupę tasków warto dać na końcu. Gorzej jeśli mamy 2 takie grupy...
sebul
16.01.2015
enum (+= 200) { TASK_PIERWSZY = 2000, TASK_DRUGI, TASK_TRZECI // itd. };
A co to za wysiłek?A nawet jeśli to szkoda się silić na wymyślanie cyferek typu 473825
psilocybe
17.01.2015
Dzięki za wyjaśnienie, problem rozwiązany.
Crashe bez logów, gdzie w konsoli było tylko 'Segmentation fault' to prawdopodobnie efekt próby usunięcia entity o ID 0 lub mniejszego od 32. Nadal nie jestem pewny bo nie udało się uzyskać logów nawet przy wszystkich dostępnych komendach debugowania serwera i amx'a. Jednego jestem pewny - miało to związek z usuwaniem tych entity.
sebul
17.01.2015
Ten temat został zamknięty przez moderatora.
Powód: Pomoc udzielona
Jeśli się z tym nie zgadzasz, raportuj ten post, a moderator lub administrator rozpatrzy go ponownie.
Z pozdrowieniami,
Zespół AMXX.PL