HU/Debugging: Difference between revisions
No edit summary |
mNo edit summary |
||
(48 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
Scriptelés során gyakran találkozhat olyan hibákkal, amelyek nem azonnal nyilvánvalóak. Ez az oldal megpróbál rámutatni néhány alapvető stratégiára, hogy megtalálja a hibát. | |||
==Hibakereső konzol== | ==Hibakereső konzol== | ||
Az MTA tartalmaz beépített hibakereső konzolt | Az MTA tartalmaz egy beépített hibakereső konzolt, mely a scriptekből, vagy az MTA-ból származó hibákat jeleníti meg. Vegye figyelembe, hogy Admin hozzáféréssel kell, hogy rendelkezzen (hacsak nem módosítja ezt az ACL-ben), megnyithatja a hibakereső konzolt a ''debugscript *x*'' beírásával, ahol az x a hibakeresési szintet jelöli: | ||
* '''1:''' csak hibákat | |||
* '''2:''' hibákat és figyelmeztetéseket | |||
* '''3:''' hibákat, figyelmeztetéseket és információs üzeneteket | |||
* '''1:''' | A ''debugscript 3'' beírásával az összes üzenet látható. A 3-as és a 2-es szint a legtöbb helyzetben ajánlott. A ''debugscript''-nek engedélyezettnek kell lennie, amikor teszteli a scriptjeit, ez segíteni fog, hogy könnyedén észrevegye és megoldja az esetleges gépelési hibákat, vagy más problémákat. | ||
* '''2:''' | |||
* '''3:''' A '' | |||
===Példa=== | ===Példa=== | ||
Ez a példa tartalmaz két hibát: | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function | function SayHello(message, player) | ||
if (getPlayerName(player) == " | if (getPlayerName(player) == "Fedor") | ||
outputChatbox(" | outputChatbox("Hello Fedor") | ||
end | end | ||
end | end | ||
addEventHandler("onChatMessage", root, | addEventHandler("onChatMessage", root, SayHello) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Ha ezt a kódot lefuttatjuk akkor ezt a hibaüzenetet fogjuk kapni: | Ha ezt a kódot lefuttatjuk akkor ezt a hibaüzenetet fogjuk kapni: | ||
:{{Debug info|Loading script failed: myResource\script.lua:2: 'then' expected near ´outputChatbox'}} | :{{Debug info|Loading script failed: myResource\script.lua:2: 'then' expected near ´outputChatbox'}} | ||
Ez azt jelenti, hogy a scriptet nem lehet elemezni, mert szintaktikai hiba volt benne. Ez megmutatja a script elérési útját a resource könyvtárból, így azonosítani tudja azt a scriptet, ahonnan a hiba származik. A fájlnév után egy kettőspontot és egy számot jelenít meg, ez a szám azt a sorszámot jeleníti meg, ahol megtalálhatja hol van a hiba a script-ben. Azután pedig a hibaüzenet, mely a létrejövő hibától függően változik. Ha megnézzük a hibaüzenetet, akkor könnyen megállapíthatjuk, hogy a hiba a '''myResource''' könyvtárból származik, és a '''script.lua''' fájljának a második sorából. A hibaüzenet tisztán mutatja, hogy elfelejtettük a "then"-t! De ezt könnyedén kijavíthatjuk! | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function | function SayHello(message, player) | ||
if (getPlayerName(player) == " | if (getPlayerName(player) == "Fedor") then | ||
outputChatbox(" | outputChatbox("Hello Fedor") | ||
end | end | ||
end | end | ||
addEventHandler("onChatMessage", root, | addEventHandler("onChatMessage", root, SayHello) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Most a script szépen be fog töltődni és semmilyen hibaüzenetet nem fog visszaadni mindaddig, míg egy 'Fedor' nevű játékos nem ír ki valamit a chat-ba, ebben a pillanatban a hibakereső konzól ezt fogja visszaadni: | |||
:{{Debug error|myResource\script.lua:2: attempt to call global 'outputChatbox' (a nil value)}} | :{{Debug error|myResource\script.lua:2: attempt to call global 'outputChatbox' (a nil value)}} | ||
Ez az error azt jelenti, hogy | Ez az error azt jelenti, hogy az '''outputChatbox''' egy nil érték, az-az, nem létezik. Ez azért van, mert a funkciót [[outputChatBox]]-nak hivják, és nem [[outputChatbox]]-nak. Figyeljen a nagy 'B' betűre: | ||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function SayHello(message, player) | function SayHello(message, player) | ||
if (getPlayerName(player) == " | if (getPlayerName(player) == "Fedor") then | ||
outputChatBox(" | outputChatBox("Hello Fedor") | ||
end | end | ||
end | end | ||
Line 44: | Line 41: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Természetesen ez csak egy példa, és csak a hibaüzeneteknek a felszínét érintettem. Nagyon sok más üzenet és eshetőség létezik, de egy általános elképzelést kell kapnia. | |||
==Szerver & Cliens hibakeresési napló= | ==Szerver & Cliens hibakeresési napló== | ||
====Szerver==== | ====Szerver==== | ||
Menjen a: ''(MTA mappa)>server>mods>deathmatch'' mappába | |||
Van itt két majdnem azonos fájl. | Van itt két majdnem azonos fájl. | ||
* A local.conf a beállításokat tartalmazza | * A local.conf fájl a "host game" menü item-re vonatkozó beállításokat tartalmazza, mely az MTA főmenüjében van. Ez egy gyors és egyszerű módja az ideiglenes szerver indításának a client oldaláról. Ha a client (host) leáll, akkor a server is leáll. | ||
* | *Az mtaserver.conf akkor van használatban, amikor az "MTA Server.exe" végrehajtódott az (MTA fő mappa)>server-ből. Ez futtatja a szervert a saját konzolablakában, mely nem igényli a client meglétét vagy futtatását. Ez akkor lehet hasznos, ha hosszabb időre szeretne szervert futtatni. | ||
Attól függen, hogy milyen módon futtat, aszerint kell szerkeszteni ezeket a fájlokat. A kérdéses beállítások a következők: | |||
<syntaxhighlight lang="xml"><!-- | <syntaxhighlight lang="xml"><!-- Megadhatja a debugscript log fájl helyét és nevét. Ha üresen hagyja, akkor a server nem fogja elmenteni ezt a fájlt --> | ||
<scriptdebuglogfile>logs/scripts.log</scriptdebuglogfile> | <scriptdebuglogfile>logs/scripts.log</scriptdebuglogfile> | ||
<!-- | <!-- Megadhatja a log fájl debug szintjét! Lehetséges értékek: 0, 1, 2, 3. Ha nincs beállítva, akkor automatikusan 0. --> | ||
<scriptdebugloglevel>0</scriptdebugloglevel></syntaxhighlight> | <scriptdebugloglevel>0</scriptdebugloglevel></syntaxhighlight> | ||
Bizonyosodjon meg arról, hogy megvan-e adva a log név. Azt is meg tudja határozni, hogy a hibák melyik szintje legyen naplózva. Ha ez 0, akkor semmi nem lesz naplózva. A szintek magyarázata a cikk tetején található. Ha a naplózási szint megváltozott 3-ra, akkor ebben az esetben minden szerver oldali script hibát a (MTA fő mappa)>server>mods>deathmatch>logs>scripts.log fájlba fogja naplózni. | |||
====Kliens==== | ====Kliens==== | ||
Menjen a: ''(MTA mappa)>server>clientscript.log'' | |||
Ez a file az összes '''kliensoldali''' | Ez a file az összes '''kliensoldali''' script hibákat naplózza. Ez alapértelmezetten naplózásra van beállítva, nincs szükség beállításra. | ||
==Hibakeresési stratégiák== | ==Hibakeresési stratégiák== | ||
Line 76: | Line 72: | ||
===Hasznos funkciók=== | ===Hasznos funkciók=== | ||
Vannak olyan funkciók, amelyek jól jöhetnek a hibakereséshez. | Vannak olyan funkciók, amelyek jól jöhetnek a hibakereséshez. | ||
* [[outputDebugString]] vagy [[outputChatBox]] ( | * [[outputDebugString]] vagy [[outputChatBox]] bármilyen információ kiírásához (használja az outputDebugString a technikai kiíráshoz) | ||
* [http://www.lua.org/manual/5.1/manual.html#pdf-tostring tostring()] Hasznos, ha az érték nem szám vagy string. | * [http://www.lua.org/manual/5.1/manual.html#pdf-tostring tostring()] egy változó, amely az értéket egy string-re változtatja. Hasznos, ha az érték nem egy szám vagy egy string. | ||
* [[inspect]] visszaad egy az ember számára olvasható stringet bármilyen adattípusról, beleértve a táblákat, nem elemi felhasználói adatokat, mint az ACL groupok, felhasználók, elemeke, stb. | |||
* [[iprint]] hasonló az ellenőrzéshez, kivéve, hogy annyi paramétert vesz igénybe, amennyi szökséges, majd kiírja őket a debugscript-be. | |||
* [[getElementType]] ellenőrzni az MTA elem típusát. | |||
* [[isElement]] ellenőrzi, hogy az MTA elem létezik-e. | |||
===Adjon meg debugmessage-t annak ellenőrzéséhez, hogy mikor, illetve milyen gyakran hajtja végre a kód egy részét=== | |||
Egy tipikus példa igazolja, hogy az ''if''-rész az végrehajtódott-e, vagy sem. Ehhez csak adjon hozzá egy olyan üzenetet, amit majd később fel fog ismerni az '' if '' -részben. | |||
=== | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
if (variable1 == variable2) then | if (variable1 == variable2) then | ||
Line 91: | Line 88: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Egy másik használata a változó értékek módosításának ellenőrzése lenne. Először keresse meg a szerkeszteni kívánt változó összes előfordulását, majd addjon hozzá egy üzenetet. | |||
=== | ===Adjon hozzá debugmessage-t egy változó értékének ellenőrzéséhez=== | ||
Tegyük fel, hogy létre szeretne hozni egy markert, de nem abban a pozícióban jelenik meg, mint amire számított. Az első dolog, amit érdemes lehet ellenőrizni, hogy a [[createMarker]] függvény lefutott-e. De amíg ezt használja, közben azokat az értékeket is tudja ellenőrizni, amik a [[createMarker]] funkcióban vannak használva. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
outputChatBox("posX is: "..x.." posY is: "..y.." posZ is: "..z) | outputChatBox("posX is: "..x.." posY is: "..y.." posZ is: "..z) | ||
createMarker(x,y,z) | createMarker(x,y,z) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Ez mind a három változót kiírja, melyek a marker kordinátájaként lettek használva. Feltételezve, hogy kiolvassa ezeket a map fájlból, most már össze tudja hasonlítani a debug kiírást a kívánt értékekkel. A [http://www.lua.org/manual/5.1/manual.html#pdf-tostring tostring()] gondoskodni fog arról, hogy a változók értékei összefűzhetőek legyenek stringként, még akkor is, ha ez egy logikai érték. | |||
== | ==Példa== | ||
Képzelje el, hogy valahol létrehozott egy [[Colshape|collision shape]]-t, és szeretné, ha valami végrehajtódna miután a játékos tíz másodpercig benne marad: | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function colShapeHit(player) | function colShapeHit(player) | ||
Line 117: | Line 114: | ||
addEventHandler("onColShapeLeave", root, colShapeLeave) | addEventHandler("onColShapeLeave", root, colShapeLeave) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Amikor a játékos belép a colshape-be, a debugscript a következő üzenetet fogja kiírni: | |||
:{{Debug error|..[path]: attempt to index global 'colshapeTimer' (a nil value)}} | :{{Debug error|..[path]: attempt to index global 'colshapeTimer' (a nil value)}} | ||
Ez azt jelenti, hogy megpróbált rámutatni egy olyan táblára, ami nem létezik (mert a tábla egy nil értékű, nem létezik). Ez akkor történik, amikor a timer id-jét a táblába akarja helyezi. Hozzá kell adnunk egy ellenőrzést, hogy a tábla létezik-e, és ha nem, akkor hozzon létre egyet. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
Line 139: | Line 136: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Még mindig figyelmeztetést fogunk kapni, amikor a játékos belép a colshape-be, várjon az üzenetre, majd lépjen ki belőle (colshape-ből): | |||
:{{Debug warning|[..]: Bad argument @ 'killTimer' Line: ..}} | :{{Debug warning|[..]: Bad argument @ 'killTimer' Line: ..}} | ||
Ettől eltekintve (erről majd később beszélünk) minden jónak tűnik. A játékos belép a colshape-be, a timer elindul, ha ott marad az üzenet megjelenik, ha kilép, a timer megsemmisül. | |||
=== | ===Egy kevésbé észrevehető hiba=== | ||
De valami oknál fogva az üzenet kétszer jelenik meg amikor a colkörben marad egy autóban ülve. Úgy tűnik, hogy valamennyi kód kétszer hajtódik végre, ezért debug üzenetet adunk hozzá, hogy ezt ellenőrizze. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
Line 170: | Line 167: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Most észre vesszük, hogy mindkét handler functions kétszer hajtódik végre, amikor egy járműben vagyunk, de csak egyszer, ha gyalogosok vagyunk. Úgy tűnik, hogy a jármű meghívja a colshape-t is. Az elmélet megerősítése érdekében biztosítjuk, hogy a ''player'' változó valójában egy játékoselemre hivatkozzon. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
Line 194: | Line 191: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
A debug elmondja nekünk, hogy az egyik ''player'' változó az egy játékos, a másik pedig egy jármű elem. Mivel csak arra akarunk reagálni, ha egy játékos lép be a colshape-be, ezért hozzáadunk egy ''if''-et, mely megakadájozza, hogy a function lefusson, ha ez nem egy játékos elem. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
Line 222: | Line 219: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Most a scriptnek a kívánt módon kell működnie, de továbbra is kiírja a fent említett hibaüzenetet. Ez azért van, mert az időzítő, melyet ki akarunk kapcsolni mikor egy játékos elhagyja a colshape-et, már nem létezik mikor elérte a 10 másodpercet (és ezáltal lefutott a tizedik másodperc után). Különböző módokon tudunk megszabadulni ezektől a figyelmeztetésektől (mivel tudjunk, hogy a timer már nem létezik, és csak akkor akarjuk megsemmisíteni, ha létezik). Az egyik mód az, hogy ellenőrizzük, tényleg létezik-e a táblázatban szereplő timer. Ehhez használnunk kell az [[isTimer]]-t, amit akkor fogunk használni, amikor megsemmisítettük a timert: | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
if (isTimer(colshapeTimer[player])) then | if (isTimer(colshapeTimer[player])) then | ||
Line 229: | Line 226: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Tehát a teljes működő kód így nézne ki: | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function colShapeHit(player) | function colShapeHit(player) | ||
Line 258: | Line 255: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
==Teljesítménybeli problémák elhárítása== | |||
Ha a szervere több erőforrást használ el, mint kelle, vagy csak azt szeretné, hogy a scriptjei hatékonyak legyenek, megtalálhatja a probléma forrását egy nagyszerű eszköz használatával, amely az alapértelmezett resource csomaggal együtt érkezik: [[Resource:Performancebrowser|performancebrowser]]. Elindíthatja a ''''start performancebrowser''''-el. Ha ez nem létezik, akkor letöltheti a legfrissebb resourcet a [https://github.com/multitheftauto/mtasa-resources GitHub repository]-ról. Ez az eszköz hihetetlen mennyiségű információt nyújt a teljesítménybeli hibakereséshez. Memória szivárgások, elem szivárgások, CPU igényes scriptek könnyedén megtalálhatóak a teljesítményböngészőn keresztül. Ha a ''''d'''' opciót használja a Lua időzítőben, akkor láthatja, hogy mely function-ök használja a CPU-t. | |||
A teljesítményböngésző eléréséhez megkell nyitni a web böngészőt, és beírni a következő címet: http://serverIPHere:serverHTTPPortHere/performancebrowser/ Vegye figyelembe, hogy a vége az szükséges. Például: http://127.0.0.1:22005/performancebrowser/ Be kell jelentkeznie egy játékbeli admin felhasználóval, vagy egy olyan felhasználóval mely jogosult a ''''resource.performancebrowser.http'''' és ''''resource.ajax.http'''' belépéshez. | |||
A legtöbb szükséges információ a Lua időzítőben és a Lua memória kategóriákban található, olyan értékeket keressen, amelyek sokkal magasabbak, mint a többi érték. | |||
=== | ===Példák olyan scriptekre, amelyek teljesítményproblémákat okozhatnak=== | ||
Adatok hozzáadása egy táblához, de nem távolítja el sosem. Ez hónapokba/évekbe telhet, mielőtt problémákat okozna. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
local someData = {} | local someData = {} | ||
Line 279: | Line 276: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Az elem szivárgás lehetséges, ha ideiglenes colshape-eket használ, és nem távolítja el azokat. Ez idővel sávszélességi, CPU és memória teljesítménybeli problémákat okozhat. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function useTemporaryCol() | function useTemporaryCol() | ||
Line 292: | Line 289: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Magas CPU igényes szerverek FPS dropokat eredményezhetnek, amitől a szerver játszhatatlanná válik. Ez egy forgalmas szerveren 24 órán belül nagy károkat okozhat. A "refs" mennyisége a Lua időzítőben felismeri az ilyen fajta scripteket, meglepő módon a Lua időzítő nem segített ebben az esetben, de a Lua memória igen. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
addEventHandler("onPlayerJoin", root, function() | addEventHandler("onPlayerJoin", root, function() | ||
Line 303: | Line 300: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Egy function túl intenzíven használja a processzorját, mert bármit is csinál az sok időt vesz igénybe. Ez csak egy function, ami sok időt vesz igénybe a befejezéshez. Teljesítményböngésző nélkül nem tudná, hogy mi okozza, de a teljesítményböngészővel láthatja a Lua időzítőben, hogy a resource sok CPU-t használ. Ha beírja az Options mezőbe a ''''d''''-t, akkor még a fájl nevét is megmondja, és a function első vonalánál, hogy mennyi CPU-t használ. | |||
<syntaxhighlight lang="lua"> | <syntaxhighlight lang="lua"> | ||
function someDodgyCode() | function someDodgyCode() | ||
Line 312: | Line 309: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== | ==Fordította== | ||
'''2018.11.05.''' <font size="3">'''[https://wiki.multitheftauto.com/wiki/User:Surge Surge]'''</font> | |||
''' | '''2017.04.17.''' <font size="3">Kevin</font> | ||
[[Category:Scripting Concepts]] | [[Category:Translated/Scripting Concepts]] | ||
[[en:Debugging]] | [[en:Debugging]] | ||
[[it:Guida al Debug]] | [[it:Guida al Debug]] | ||
[[ru:Debugging]] | [[ru:Debugging]] | ||
[[zh-cn:脚本调试教程]] | [[zh-cn:脚本调试教程]] | ||
[[Category:Tutorials]] | [[Category:Tutorials]] |
Latest revision as of 20:25, 21 February 2021
Scriptelés során gyakran találkozhat olyan hibákkal, amelyek nem azonnal nyilvánvalóak. Ez az oldal megpróbál rámutatni néhány alapvető stratégiára, hogy megtalálja a hibát.
Hibakereső konzol
Az MTA tartalmaz egy beépített hibakereső konzolt, mely a scriptekből, vagy az MTA-ból származó hibákat jeleníti meg. Vegye figyelembe, hogy Admin hozzáféréssel kell, hogy rendelkezzen (hacsak nem módosítja ezt az ACL-ben), megnyithatja a hibakereső konzolt a debugscript *x* beírásával, ahol az x a hibakeresési szintet jelöli:
- 1: csak hibákat
- 2: hibákat és figyelmeztetéseket
- 3: hibákat, figyelmeztetéseket és információs üzeneteket
A debugscript 3 beírásával az összes üzenet látható. A 3-as és a 2-es szint a legtöbb helyzetben ajánlott. A debugscript-nek engedélyezettnek kell lennie, amikor teszteli a scriptjeit, ez segíteni fog, hogy könnyedén észrevegye és megoldja az esetleges gépelési hibákat, vagy más problémákat.
Példa
Ez a példa tartalmaz két hibát:
function SayHello(message, player) if (getPlayerName(player) == "Fedor") outputChatbox("Hello Fedor") end end addEventHandler("onChatMessage", root, SayHello)
Ha ezt a kódot lefuttatjuk akkor ezt a hibaüzenetet fogjuk kapni:
- INFO: Loading script failed: myResource\script.lua:2: 'then' expected near ´outputChatbox'
Ez azt jelenti, hogy a scriptet nem lehet elemezni, mert szintaktikai hiba volt benne. Ez megmutatja a script elérési útját a resource könyvtárból, így azonosítani tudja azt a scriptet, ahonnan a hiba származik. A fájlnév után egy kettőspontot és egy számot jelenít meg, ez a szám azt a sorszámot jeleníti meg, ahol megtalálhatja hol van a hiba a script-ben. Azután pedig a hibaüzenet, mely a létrejövő hibától függően változik. Ha megnézzük a hibaüzenetet, akkor könnyen megállapíthatjuk, hogy a hiba a myResource könyvtárból származik, és a script.lua fájljának a második sorából. A hibaüzenet tisztán mutatja, hogy elfelejtettük a "then"-t! De ezt könnyedén kijavíthatjuk!
function SayHello(message, player) if (getPlayerName(player) == "Fedor") then outputChatbox("Hello Fedor") end end addEventHandler("onChatMessage", root, SayHello)
Most a script szépen be fog töltődni és semmilyen hibaüzenetet nem fog visszaadni mindaddig, míg egy 'Fedor' nevű játékos nem ír ki valamit a chat-ba, ebben a pillanatban a hibakereső konzól ezt fogja visszaadni:
- ERROR: myResource\script.lua:2: attempt to call global 'outputChatbox' (a nil value)
Ez az error azt jelenti, hogy az outputChatbox egy nil érték, az-az, nem létezik. Ez azért van, mert a funkciót outputChatBox-nak hivják, és nem outputChatbox-nak. Figyeljen a nagy 'B' betűre:
function SayHello(message, player) if (getPlayerName(player) == "Fedor") then outputChatBox("Hello Fedor") end end addEventHandler("onChatMessage", root, SayHello)
Természetesen ez csak egy példa, és csak a hibaüzeneteknek a felszínét érintettem. Nagyon sok más üzenet és eshetőség létezik, de egy általános elképzelést kell kapnia.
Szerver & Cliens hibakeresési napló
Szerver
Menjen a: (MTA mappa)>server>mods>deathmatch mappába
Van itt két majdnem azonos fájl.
- A local.conf fájl a "host game" menü item-re vonatkozó beállításokat tartalmazza, mely az MTA főmenüjében van. Ez egy gyors és egyszerű módja az ideiglenes szerver indításának a client oldaláról. Ha a client (host) leáll, akkor a server is leáll.
- Az mtaserver.conf akkor van használatban, amikor az "MTA Server.exe" végrehajtódott az (MTA fő mappa)>server-ből. Ez futtatja a szervert a saját konzolablakában, mely nem igényli a client meglétét vagy futtatását. Ez akkor lehet hasznos, ha hosszabb időre szeretne szervert futtatni.
Attól függen, hogy milyen módon futtat, aszerint kell szerkeszteni ezeket a fájlokat. A kérdéses beállítások a következők:
<!-- Megadhatja a debugscript log fájl helyét és nevét. Ha üresen hagyja, akkor a server nem fogja elmenteni ezt a fájlt --> <scriptdebuglogfile>logs/scripts.log</scriptdebuglogfile> <!-- Megadhatja a log fájl debug szintjét! Lehetséges értékek: 0, 1, 2, 3. Ha nincs beállítva, akkor automatikusan 0. --> <scriptdebugloglevel>0</scriptdebugloglevel>
Bizonyosodjon meg arról, hogy megvan-e adva a log név. Azt is meg tudja határozni, hogy a hibák melyik szintje legyen naplózva. Ha ez 0, akkor semmi nem lesz naplózva. A szintek magyarázata a cikk tetején található. Ha a naplózási szint megváltozott 3-ra, akkor ebben az esetben minden szerver oldali script hibát a (MTA fő mappa)>server>mods>deathmatch>logs>scripts.log fájlba fogja naplózni.
Kliens
Menjen a: (MTA mappa)>server>clientscript.log
Ez a file az összes kliensoldali script hibákat naplózza. Ez alapértelmezetten naplózásra van beállítva, nincs szükség beállításra.
Hibakeresési stratégiák
Számos stratégia létezik, amelyek támogatják a hibakeresést. Legtöbbjük közé tartozik a kimenő Hibaüzenetek, a különböző információktól függően helyezkednek el.
Hasznos funkciók
Vannak olyan funkciók, amelyek jól jöhetnek a hibakereséshez.
- outputDebugString vagy outputChatBox bármilyen információ kiírásához (használja az outputDebugString a technikai kiíráshoz)
- tostring() egy változó, amely az értéket egy string-re változtatja. Hasznos, ha az érték nem egy szám vagy egy string.
- inspect visszaad egy az ember számára olvasható stringet bármilyen adattípusról, beleértve a táblákat, nem elemi felhasználói adatokat, mint az ACL groupok, felhasználók, elemeke, stb.
- iprint hasonló az ellenőrzéshez, kivéve, hogy annyi paramétert vesz igénybe, amennyi szökséges, majd kiírja őket a debugscript-be.
- getElementType ellenőrzni az MTA elem típusát.
- isElement ellenőrzi, hogy az MTA elem létezik-e.
Adjon meg debugmessage-t annak ellenőrzéséhez, hogy mikor, illetve milyen gyakran hajtja végre a kód egy részét
Egy tipikus példa igazolja, hogy az if-rész az végrehajtódott-e, vagy sem. Ehhez csak adjon hozzá egy olyan üzenetet, amit majd később fel fog ismerni az if -részben.
if (variable1 == variable2) then outputDebugString("variable1 is the same as variable2!") -- do anything end
Egy másik használata a változó értékek módosításának ellenőrzése lenne. Először keresse meg a szerkeszteni kívánt változó összes előfordulását, majd addjon hozzá egy üzenetet.
Adjon hozzá debugmessage-t egy változó értékének ellenőrzéséhez
Tegyük fel, hogy létre szeretne hozni egy markert, de nem abban a pozícióban jelenik meg, mint amire számított. Az első dolog, amit érdemes lehet ellenőrizni, hogy a createMarker függvény lefutott-e. De amíg ezt használja, közben azokat az értékeket is tudja ellenőrizni, amik a createMarker funkcióban vannak használva.
outputChatBox("posX is: "..x.." posY is: "..y.." posZ is: "..z) createMarker(x,y,z)
Ez mind a három változót kiírja, melyek a marker kordinátájaként lettek használva. Feltételezve, hogy kiolvassa ezeket a map fájlból, most már össze tudja hasonlítani a debug kiírást a kívánt értékekkel. A tostring() gondoskodni fog arról, hogy a változók értékei összefűzhetőek legyenek stringként, még akkor is, ha ez egy logikai érték.
Példa
Képzelje el, hogy valahol létrehozott egy collision shape-t, és szeretné, ha valami végrehajtódna miután a játékos tíz másodpercig benne marad:
function colShapeHit(player) -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit", root, colShapeHit) function colShapeLeave(player) -- kill the timer when the player leaves the colshape killTimer(colshapeTimer[player]) end addEventHandler("onColShapeLeave", root, colShapeLeave)
Amikor a játékos belép a colshape-be, a debugscript a következő üzenetet fogja kiírni:
- ERROR: ..[path]: attempt to index global 'colshapeTimer' (a nil value)
Ez azt jelenti, hogy megpróbált rámutatni egy olyan táblára, ami nem létezik (mert a tábla egy nil értékű, nem létezik). Ez akkor történik, amikor a timer id-jét a táblába akarja helyezi. Hozzá kell adnunk egy ellenőrzést, hogy a tábla létezik-e, és ha nem, akkor hozzon létre egyet.
function colShapeHit(player) if (colshapeTimer == nil) then colshapeTimer = {} end -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit", root, colShapeHit) function colShapeLeave(player) -- kill the timer when the player leaves the colshape killTimer(colshapeTimer[player]) end addEventHandler("onColShapeLeave",root,colShapeLeave)
Még mindig figyelmeztetést fogunk kapni, amikor a játékos belép a colshape-be, várjon az üzenetre, majd lépjen ki belőle (colshape-ből):
- WARNING: [..]: Bad argument @ 'killTimer' Line: ..
Ettől eltekintve (erről majd később beszélünk) minden jónak tűnik. A játékos belép a colshape-be, a timer elindul, ha ott marad az üzenet megjelenik, ha kilép, a timer megsemmisül.
Egy kevésbé észrevehető hiba
De valami oknál fogva az üzenet kétszer jelenik meg amikor a colkörben marad egy autóban ülve. Úgy tűnik, hogy valamennyi kód kétszer hajtódik végre, ezért debug üzenetet adunk hozzá, hogy ezt ellenőrizze.
function colShapeHit(player) if (colshapeTimer == nil) then colshapeTimer = {} end -- add a debug message outputDebugString("colShapeHit") -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit",getRootElement(),colShapeHit) function colShapeLeave(player) -- add a debug message outputDebugString("colShapeLeave") -- kill the timer when the player leaves the colshape killTimer(colshapeTimer[player]) end addEventHandler("onColShapeLeave",getRootElement(),colShapeLeave)
Most észre vesszük, hogy mindkét handler functions kétszer hajtódik végre, amikor egy járműben vagyunk, de csak egyszer, ha gyalogosok vagyunk. Úgy tűnik, hogy a jármű meghívja a colshape-t is. Az elmélet megerősítése érdekében biztosítjuk, hogy a player változó valójában egy játékoselemre hivatkozzon.
function colShapeHit(player) if (colshapeTimer == nil) then colshapeTimer = {} end -- add a debug message, with the element type outputDebugString("colShapeHit "..getElementType(player)) -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit",getRootElement(),colShapeHit) function colShapeLeave(player) -- add a debug message, with the element type outputDebugString("colShapeLeave "..getElementType(player)) -- kill the timer when the player leaves the colshape killTimer(colshapeTimer[player]) end addEventHandler("onColShapeLeave",getRootElement(),colShapeLeave)
A debug elmondja nekünk, hogy az egyik player változó az egy játékos, a másik pedig egy jármű elem. Mivel csak arra akarunk reagálni, ha egy játékos lép be a colshape-be, ezért hozzáadunk egy if-et, mely megakadájozza, hogy a function lefusson, ha ez nem egy játékos elem.
function colShapeHit(player) if (colshapeTimer == nil) then colshapeTimer = {} end -- add a check for the element type if (getElementType(player) ~= "player") then return end -- add a debug message, with the element type outputDebugString("colShapeHit "..getElementType(player)) -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit",getRootElement(),colShapeHit) function colShapeLeave(player) -- add a check for the element type if (getElementType(player) ~= "player") then return end -- add a debug message, with the element type outputDebugString("colShapeLeave "..getElementType(player)) -- kill the timer when the player leaves the colshape killTimer(colshapeTimer[player]) end addEventHandler("onColShapeLeave",getRootElement(),colShapeLeave)
Most a scriptnek a kívánt módon kell működnie, de továbbra is kiírja a fent említett hibaüzenetet. Ez azért van, mert az időzítő, melyet ki akarunk kapcsolni mikor egy játékos elhagyja a colshape-et, már nem létezik mikor elérte a 10 másodpercet (és ezáltal lefutott a tizedik másodperc után). Különböző módokon tudunk megszabadulni ezektől a figyelmeztetésektől (mivel tudjunk, hogy a timer már nem létezik, és csak akkor akarjuk megsemmisíteni, ha létezik). Az egyik mód az, hogy ellenőrizzük, tényleg létezik-e a táblázatban szereplő timer. Ehhez használnunk kell az isTimer-t, amit akkor fogunk használni, amikor megsemmisítettük a timert:
if (isTimer(colshapeTimer[player])) then killTimer(colshapeTimer[player]) end
Tehát a teljes működő kód így nézne ki:
function colShapeHit(player) if (colshapeTimer == nil) then colshapeTimer = {} end -- add a check for the element type if (getElementType(player) ~= "player") then return end -- add a debug message, with the element type outputDebugString("colShapeHit "..getElementType(player)) -- set a timer to output a message (could as well execute another function) -- store the timer id in a table, using the player as index colshapeTimer[player] = setTimer(outputChatBox,10000,1,"The player stayed 10 seconds in the colshape!") end addEventHandler("onColShapeHit",getRootElement(),colShapeHit) function colShapeLeave(player) -- add a check for the element type if (getElementType(player) ~= "player") then return end -- add a debug message, with the element type outputDebugString("colShapeLeave "..getElementType(player)) -- kill the timer when the player leaves the colshape if (isTimer(colshapeTimer[player])) then killTimer(colshapeTimer[player]) end end addEventHandler("onColShapeLeave",getRootElement(),colShapeLeave)
Teljesítménybeli problémák elhárítása
Ha a szervere több erőforrást használ el, mint kelle, vagy csak azt szeretné, hogy a scriptjei hatékonyak legyenek, megtalálhatja a probléma forrását egy nagyszerű eszköz használatával, amely az alapértelmezett resource csomaggal együtt érkezik: performancebrowser. Elindíthatja a 'start performancebrowser'-el. Ha ez nem létezik, akkor letöltheti a legfrissebb resourcet a GitHub repository-ról. Ez az eszköz hihetetlen mennyiségű információt nyújt a teljesítménybeli hibakereséshez. Memória szivárgások, elem szivárgások, CPU igényes scriptek könnyedén megtalálhatóak a teljesítményböngészőn keresztül. Ha a 'd' opciót használja a Lua időzítőben, akkor láthatja, hogy mely function-ök használja a CPU-t.
A teljesítményböngésző eléréséhez megkell nyitni a web böngészőt, és beírni a következő címet: http://serverIPHere:serverHTTPPortHere/performancebrowser/ Vegye figyelembe, hogy a vége az szükséges. Például: http://127.0.0.1:22005/performancebrowser/ Be kell jelentkeznie egy játékbeli admin felhasználóval, vagy egy olyan felhasználóval mely jogosult a 'resource.performancebrowser.http' és 'resource.ajax.http' belépéshez. A legtöbb szükséges információ a Lua időzítőben és a Lua memória kategóriákban található, olyan értékeket keressen, amelyek sokkal magasabbak, mint a többi érték.
Példák olyan scriptekre, amelyek teljesítményproblémákat okozhatnak
Adatok hozzáadása egy táblához, de nem távolítja el sosem. Ez hónapokba/évekbe telhet, mielőtt problémákat okozna.
local someData = {} function storeData() someData[source] = true -- There is no handling for when a player quits, this is considered a memory leak -- Using the Lua timing tab you can detect the RAM usage of each resource. end addEventHandler("onPlayerJoin", root, storeData)
Az elem szivárgás lehetséges, ha ideiglenes colshape-eket használ, és nem távolítja el azokat. Ez idővel sávszélességi, CPU és memória teljesítménybeli problémákat okozhat.
function useTemporaryCol() local col = createColCircle(some code here) if (normally this should happen) then destroyElement(col) end -- But sometimes it didn't so the script ended but the collision area remained and over time -- you may end up with hundreds to thousands of pointless collision areas. -- The Lua timing tab allows you to see the amount of elements each script has created. end
Magas CPU igényes szerverek FPS dropokat eredményezhetnek, amitől a szerver játszhatatlanná válik. Ez egy forgalmas szerveren 24 órán belül nagy károkat okozhat. A "refs" mennyisége a Lua időzítőben felismeri az ilyen fajta scripteket, meglepő módon a Lua időzítő nem segített ebben az esetben, de a Lua memória igen.
addEventHandler("onPlayerJoin", root, function() -- Code for joiner addEventHandler("onPlayerQuit", root, function() -- Code for when they have quit -- See the problem? It's bound to root which the event handler is being added again and again and again end) end)
Egy function túl intenzíven használja a processzorját, mert bármit is csinál az sok időt vesz igénybe. Ez csak egy function, ami sok időt vesz igénybe a befejezéshez. Teljesítményböngésző nélkül nem tudná, hogy mi okozza, de a teljesítményböngészővel láthatja a Lua időzítőben, hogy a resource sok CPU-t használ. Ha beírja az Options mezőbe a 'd'-t, akkor még a fájl nevét is megmondja, és a function első vonalánál, hogy mennyi CPU-t használ.
function someDodgyCode() for i=1, 100000 do -- some code end end
Fordította
2018.11.05. Surge
2017.04.17. Kevin