Pytanie o poprawność zapisu w kodzie
Scorpion Flail
02.02.2014
Witam.
Dziś edytując silnik PaintBall z tego tematu natknąłem się na dziwną dla mnie rzecz.
Jak mam rozumieć ten fragment kodu?
public new_round() if (get_pcvar_num(onoff) && get_pcvar_num(strip)) { new ent; while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "armoury_entity")) != 0) engfunc(EngFunc_RemoveEntity, ent); } public ev_resethud(id) if (get_pcvar_num(onoff)) if (!task_exists(id)) set_task(0.3, "player_spawn", id); public player_spawn(id) if (is_user_alive(id)) { if (get_pcvar_num(protc)) { set_pev(id, pev_takedamage, DAMAGE_NO); set_task(float(get_pcvar_num(protc)), "player_godmodeoff", id+100); } if (get_pcvar_num(strip) && !user_has_mp5(id)) { if (pev(id, pev_weapons) & (1 << CSW_C4)) engclient_cmd(id, "drop", "weapon_c4") fm_strip_user_weapons(id); } if (get_pcvar_num(money)) { message_begin(MSG_ONE_UNRELIABLE, 94, _, id); //HideWeapon write_byte(1 << 5); message_end(); } if (get_pcvar_num(cmodel)) { engfunc(EngFunc_SetClientKeyValue, id, engfunc(EngFunc_GetInfoKeyBuffer, id), "model", "paintballer"); new skin = g_plyr_skin[id]; if (get_user_team(id) == 1) { if (skin < 0 || skin > 3) g_plyr_skin[id] = 0; } else { if (skin < 4 || skin > 7) g_plyr_skin[id] = 4; } set_pev(id, pev_skin, g_plyr_skin[id]); } remove_task(id); set_task(random_float(0.9, 1.3), "player_weapons", id); set_task(2.0, "clear_moneyhud", id + 300); } public client_command(id) if (get_pcvar_num(cmodel)) { new command[10], speech[2]; read_argv(0, command, 9); read_argv(1, speech, 1); if (containi(command, "join") != -1) if (equali(command, "jointeam")) g_team_select[id] = str_to_num(speech); else if (equali(command, "joinclass")) g_plyr_skin[id] = (g_team_select[id] == 1) ? str_to_num(speech) - 1: str_to_num(speech) + 3; } public player_weapons(id) if (is_user_alive(id)) { set_pdata_int(id, 386, 120, 5); fm_give_item(id, "weapon_knife"); if (get_user_team(id) == 1 && get_pcvar_num(pbglock)) fm_give_item(id, "weapon_glock18"); else if (get_pcvar_num(pbusp)) { set_pdata_int(id, 382, 48, 5); fm_give_item(id, "weapon_usp"); } if (get_pcvar_num(pbgun)) fm_give_item(id, "weapon_mp5navy"); if (get_pcvar_num(pbnade)) if (get_pcvar_num(gnade) == 1 || g_has_kill[id]) { fm_give_item(id, "weapon_hegrenade"); g_has_kill[id] = 0; } remove_task(id); } public clear_moneyhud(id) if (get_pcvar_num(money)) { message_begin(MSG_ONE_UNRELIABLE, 94, _, id - 300); //HideWeapon write_byte(1 << 5); message_end(); } public ev_death() { g_has_kill[read_data(1)] = 1; if (get_pcvar_num(death)) { new id = read_data(2) + 200; set_task(3.0, "player_spawner", id); set_task(3.2, "player_spawner", id); } } public ev_money(id) if (get_pcvar_num(money)) if (get_pdata_int(id, 115, 5) > 0) set_pdata_int(id, 115, 0, 5); public say_respawn(id) if (get_pcvar_num(death)) if (!is_user_alive(id)) if (get_user_team(id) == 1 || get_user_team(id) == 2) { set_task(1.5, "player_spawner", id + 200); set_task(1.7, "player_spawner", id + 200); } public player_godmodeoff(id) set_pev(id-100, pev_takedamage, DAMAGE_AIM); public player_spawner(id) if (is_user_connected(id - 200)) if (get_user_team(id - 200) == 1 || get_user_team(id - 200) == 2) dllfunc(DLLFunc_Spawn, id - 200);
Chodzi mi przede wszystkim o klamerki otwierające i zamykające public'i.
Plugin w praktyce niby działa, ale czy taki zapis jest poprawny (bez klamerek)?
Adiloveskan
02.02.2014
po każdym publicku, musisz w tej samej lub następnej (więcej bugów) postawić {, a po zakończeniu danego publicka, musisz dać }
Pokaze to na przykładzie
public say_respawn(id)
if (get_pcvar_num(death))
if (!is_user_alive(id))
if (get_user_team(id) == 1 || get_user_team(id) == 2)
{
set_task(1.5, "player_spawner", id + 200);
set_task(1.7, "player_spawner", id + 200);
}
Ten zapis jest niepoprawny, gdyż plugin (Gdyby nie było nowych publicków) ciagnął by się dalej, niby powinno działać, ale zaleca się używanie { i }
public say_respawn(id){
if (get_pcvar_num(death))
if (!is_user_alive(id))
if (get_user_team(id) == 1 || get_user_team(id) == 2)
{
set_task(1.5, "player_spawner", id + 200);
set_task(1.7, "player_spawner", id + 200);
}
}
W tym zapisie, klamra } Ostatecznie zamyka publicka, a więc nie może wystąpić błąd związany z jej brakiem.
Dodatkowo, klamr { musi być w jednym publicku tyle co klamr }, inaczej
public say_respawn(id){1 czerwona
if (get_pcvar_num(death))
if (!is_user_alive(id))
if (get_user_team(id) == 1 || get_user_team(id) == 2)
{2 czerwona
set_task(1.5, "player_spawner", id + 200);
set_task(1.7, "player_spawner", id + 200);
}1 niebieska
}Brak 2 niebieskiej
Ten kod jest niepoprawny, dlatego że są 2 klamry czerwone ( { ), a tylko 1 niebieska ( } ), i plugin nie zostaje zamknięty, bo druga klamra czerwona jest zamykana przez pierwsza niebieską, dlatego że niema pomiędzy nimi żadnych innych klamr. a pierwsza czerwona pozostaje niezamknięta, co wywala Error
Teraz zamykanie
public say_respawn(id){druga para, pomiędzy nimi jest para 1
if (get_pcvar_num(death))
if (!is_user_alive(id))
if (get_user_team(id) == 1 || get_user_team(id) == 2)
{1-sza para, pomiedzy nimi nie ma zadnej innej pary
set_task(1.5, "player_spawner", id + 200);
set_task(1.7, "player_spawner", id + 200);
}1-sza para, pomiedzy nimi nie ma zadnej innej pary
}druga para, pomiędzy nimi jest para 1
Jeżeli jest para 1, i klamry { i } są "kolo siebie" (Nie ma w ich zamknieciu zadnych innych klamr { czy }) to się lączą w pare,
Jeżeli jest para 2, i klamry { i } nie są "kolo siebie" (W ich zamknieciu wystepuja pary) to pary sa eliminowane przy "rozumowaniu"
Jest jeszcze 1 przypadek, lecz ja ci go nie wytłumacze bo nie wiem jak
Gość_21977_* 02.02.2014
po każdym publicku, musisz w tej samej lub następnej (więcej bugów) postawić {, a po zakończeniu danego publicka, musisz dać }
(…)
Nie.
Klamry grupują komendy zawarte wewnątrz nich.
W przypadku, kiedy nie użyjemy klamer, komendy nie zostaną po prostu pogrupowane.
public say_respawn(id) if (get_pcvar_num(death)) if (!is_user_alive(id)) if (get_user_team(id) == 1 || get_user_team(id) == 2) { set_task(1.5, "player_spawner", id + 200); set_task(1.7, "player_spawner", id + 200); }
Kod ten jest poprawny.
Funkcja publiczna say_respawn składa się z jednego ifa, który w przypadku, gdy wartość logiczna get_pcvar_num(death) jest prawdziwa, to wykonuje kolejnego ifa.
Jeśli jego wartość logiczna !is_user_alive(id) jest prawdziwa, to wywołuje kolejnego ifa i jeśli jego wartość logiczna get_user_team(id) == 1 || get_user_team(id) == 2 jest prawdziwa,
to wywołuje on wszystkie zgrupowane instrukcje zawarte wewnątrz klamry, tj. dwa wywołania natywu set_task.
Klamry mamy konieczność stosować jedynie, gdy chcemy zgrupować wiele komend.
W przypadku, gdy wywołujemy jedynie jedną komendę, użycie klamry jest opcjonalne.
Kod zacytowany wyżej w tym poście można napisać również, używając klamer w miejscu, gdzie nie są one potrzebne, tj.:
public say_respawn(id){ if (get_pcvar_num(death)){ if (!is_user_alive(id)){ if (get_user_team(id) == 1 || get_user_team(id) == 2) { set_task(1.5, "player_spawner", id + 200); set_task(1.7, "player_spawner", id + 200); } } } }
Podejrzewam, że z tak właśnie formą zazwyczaj obcowałeś, stąd to pytanie odnośnie klamer.
Podsumowując,forma bezklamrowa jest poprawna dla pojedynczych komend, choć rzadko używana ze względu na czytelność oraz kompatybilność z wieloma, głównie starszymi, środowiskami programistycznymi.
To, czy dany programista używa klamer dla pojedynczych instrukcji, czy nie, jest kwestią osobistą.
Dla jednych czytelniejsza jest forma z klamrami, dla innych bez. Jedni używają klamer w tej samej linii, co przekazywane argumenty funkcji, inni w linii niżej.
Jedni stawiają spacje, tabulacje (6262 robi niezłego mixa ), inni nie. Jest to kwestia estetyki i każdy postrzega ją inaczej.
Scorpion Flail
02.02.2014
Ok.
Czyli jeśli dobrze rozumiem, gdybym tutaj:
public new_round() if (get_pcvar_num(onoff) && get_pcvar_num(strip)) { new ent; while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "armoury_entity")) != 0) engfunc(EngFunc_RemoveEntity, ent); }
Dodał jeszcze innego if'a, np:
public new_round() if (get_pcvar_num(onoff) && get_pcvar_num(strip)) { new ent; while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "armoury_entity")) != 0) engfunc(EngFunc_RemoveEntity, ent); } if (!is_user_alive(id)) //kod
To wtedy zastosowanie klamer byłoby konieczne, ponieważ mam więcej komend, które chcę przypisac do danej funkcji, tak?
Scorpion Flail
02.02.2014
Ok.
Od jakiegoś czasu analizuję przyczynę crashy, które zdarzają się z 1-2x dziennie.. Dzieją się one zawsze w nowej rundzie przy spawnie/chwile po spawnie lub pod sam koniec rundy (przed spawnem) i są związane z silnikiem PB (resztę pluginów wykluczyłem).
Patrząc w ten kod:
public new_round() if (get_pcvar_num(onoff) && get_pcvar_num(strip)) { new ent; while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "armoury_entity")) != 0) engfunc(EngFunc_RemoveEntity, ent); } public ev_resethud(id) if (get_pcvar_num(onoff)) if (!task_exists(id)) set_task(0.3, "player_spawn", id);
Zastanawiam się nie optymalniej i poprawniej byłoby przerzucić wszystko z ev_resethud do new_round (a może odwrotnie?)
W końcu obydwie funkcje wykonują się przy nowej rundzie (oczywiście wiem, że z eventem ResetHUD jest trochę inaczej niż z Round_Start)
Użytkownik Scorpion Flail edytował ten post 02.02.2014 14:48
Adiloveskan
02.02.2014
po każdym publicku, musisz w tej samej lub następnej (więcej bugów) postawić {, a po zakończeniu danego publicka, musisz dać }
(…)
Nie.
Klamry grupują komendy zawarte wewnątrz nich.
W przypadku, kiedy nie użyjemy klamer, komendy nie zostaną po prostu pogrupowane.
public say_respawn(id) if (get_pcvar_num(death)) if (!is_user_alive(id)) if (get_user_team(id) == 1 || get_user_team(id) == 2) { set_task(1.5, "player_spawner", id + 200); set_task(1.7, "player_spawner", id + 200); }
Kod ten jest poprawny.
Funkcja publiczna say_respawn składa się z jednego ifa, który w przypadku, gdy wartość logiczna get_pcvar_num(death) jest prawdziwa, to wykonuje kolejnego ifa.
Jeśli jego wartość logiczna !is_user_alive(id) jest prawdziwa, to wywołuje kolejnego ifa i jeśli jego wartość logiczna get_user_team(id) == 1 || get_user_team(id) == 2 jest prawdziwa,
to wywołuje on wszystkie zgrupowane instrukcje zawarte wewnątrz klamry, tj. dwa wywołania natywu set_task.
Klamry mamy konieczność stosować jedynie, gdy chcemy zgrupować wiele komend.
W przypadku, gdy wywołujemy jedynie jedną komendę, użycie klamry jest opcjonalne.
Kod zacytowany wyżej w tym poście można napisać również, używając klamer w miejscu, gdzie nie są one potrzebne, tj.:public say_respawn(id){ if (get_pcvar_num(death)){ if (!is_user_alive(id)){ if (get_user_team(id) == 1 || get_user_team(id) == 2) { set_task(1.5, "player_spawner", id + 200); set_task(1.7, "player_spawner", id + 200); } } } }
Podejrzewam, że z tak właśnie formą zazwyczaj obcowałeś, stąd to pytanie odnośnie klamer.
Podsumowując,forma bezklamrowa jest poprawna dla pojedynczych komend, choć rzadko używana ze względu na czytelność oraz kompatybilność z wieloma, głównie starszymi, środowiskami programistycznymi.
To, czy dany programista używa klamer dla pojedynczych instrukcji, czy nie, jest kwestią osobistą.
Dla jednych czytelniejsza jest forma z klamrami, dla innych bez. Jedni używają klamer w tej samej linii, co przekazywane argumenty funkcji, inni w linii niżej.
Jedni stawiają spacje, tabulacje (6262 robi niezłego mixa
), inni nie. Jest to kwestia estetyki i każdy postrzega ją inaczej.
Dzięki ze naprostowałeś moje twierdzenie, Lecz i tak uważam, że lepiej i łatwiej do odczytania potem jest, jak się użyje klamr.
@TOPIC tak, lepiej by było gdybyś użył Start_Round, ale jak wspomniałeś, trzeba będzie przepisać
Użytkownik Adiloveskan edytował ten post 02.02.2014 21:21