Debugging (Civ5): Difference between revisions
mNo edit summary |
No edit summary |
||
Line 10: | Line 10: | ||
[[File:SQLiteManager.png|frame|View of the snapshot using SQLiteManager]] | [[File:SQLiteManager.png|frame|View of the snapshot using SQLiteManager]] | ||
=== Checking the logs === | === Checking the logs === | ||
If you correctly set up your [[# | If you correctly set up your [[#Configuration]], whenever you start a game, Civ5 saves some logs under <code>My Games/Sid Medier's Civilization V/cache/Civ5DebugDatabase.db</code>. | ||
* If there were errors with the XML formatting of your data files (wrong column names for example), they will logged in XML.log. | * If there were errors with the XML formatting of your data files (wrong column names for example), they will logged in XML.log. | ||
:<pre>[6904.323] Tag (TXT_KEYMODDING_SHOWDLCMODS) does not start with 'TXT_KEY_'</pre> | :<pre>[6904.323] Tag (TXT_KEYMODDING_SHOWDLCMODS) does not start with 'TXT_KEY_'</pre> | ||
Line 18: | Line 18: | ||
=== Using the snapshots === | === Using the snapshots === | ||
If you correctly set up your [[# | If you correctly set up your [[#Configuration]], whenever you start a game, Civ5 saves a snapshot of the database under <code>My Games/Sid Medier's Civilization V/cache/Civ5DebugDatabase.db</code> | ||
* This allows you to check how your XML and SQL files have been merged with the standard game data. | * This allows you to check how your XML and SQL files have been merged with the standard game data. | ||
Line 24: | Line 24: | ||
== Lua Debugging == | == Lua Debugging == | ||
=== Using the Firetuner console === | === Using the Firetuner console === | ||
If you correctly set up your [[# | If you correctly set up your [[#Configuration]], Civ5 will send all the Lua output to the Firetuner. This includes all the debugging output but also any error that may arise, with their calls stack traces. | ||
<pre> | <pre> | ||
Runtime Error: [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:41: attempt to concatenate local 'name' (a nil value) | Runtime Error: [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:41: attempt to concatenate local 'name' (a nil value) | ||
Line 33: | Line 33: | ||
[C]: ? | [C]: ? | ||
</pre> | </pre> | ||
Here we can see that the main chunk called | Here we can see that a C/C++ code (the game engine) ran the main chunk called (the Lua file), which then called the function ''ScanAll'' on line 188, which then called ''dumpObj'' on line 95. And this one caused an error on line 41. | ||
Note that paths are truncated in the provided example, which makes debugging harder sometimes. This happens when the file is in a {{Type5|context}} registered by the project's ''content'' tab. Here are the workarounds: | |||
* Register only a minimalist context, that will load additional contexts (through the UI LuaContext markup). Do not initiate any action from the root context, let the children context handle everything. | |||
* Provide a custom stack trace, as explained in a further section. | |||
=== Print, assert and error === | === Print, assert and error === | ||
<code>print('''...''')</code> can be used to print anything to the Firetuner output. This allows you to check the flow of a program, or the values of variables. Print calls '''tostring''' on every argument and displays them all on a single line with tabulations as separators between them. Nil values are not displayed, so it is advised you provide expressions such as: <code>(expr or 'nil')</code> | |||
<code>error('''string''' message, '''int''' level = 1)</code> throws an error with the specified message. The execution is then halted and the hand returned to the game engine (or the current protected call if you did use '''pcall''' or '''xpcall'''). The level parameter controls the error position that will be reported. 1 for the line where error is located, 2 for the function call that contained an error, etc. 0 for no position. | |||
<code>assert('''variant''' condition, '''string''' message = "assertion failed")</code> can be used to assert the provided condition is neither nil nor false (everything else is evaluated to true in Lua). Otherwise, an error with the specified message is thrown. You can use them punctually, as a debugging technique. But they may also be used as a defensive programming technique such as [url=http://en.wikipedia.org/wiki/Design_by_contract design-by-contract]: the idea is that whenever your program's correctness relies on an assumption, you should explicitly check it. For example, if a function takes an array as an argument and assumes that it is not empty, you should add two conditions at the beginning: <code>assert(type(t) == "table")</code> and <code>assert(#t > 0)</code>. This makes the code more self-explanatory (implicit assumptions are now explicitly stated) and it allows you to catch bugs as soon as possible, which typically makes them easier to understand and fix. | |||
=== Custom stack traces === | === Custom stack traces === |
Revision as of 09:45, 24 September 2012
This article is under construction, come back in a few days.
Checklist
- Did you correctly import to the VFS the files that need to be?
- Did you correctly set up the actions and content tab in your project?
- Did you restart civ5 after you added new files?
XML Debugging
Checking the logs
If you correctly set up your #Configuration, whenever you start a game, Civ5 saves some logs under My Games/Sid Medier's Civilization V/cache/Civ5DebugDatabase.db
.
- If there were errors with the XML formatting of your data files (wrong column names for example), they will logged in XML.log.
[6904.323] Tag (TXT_KEYMODDING_SHOWDLCMODS) does not start with 'TXT_KEY_'
- If there were errors with the data integrity (missing foreign keys for example - types that reference rows from other tables), they will logged in database.log.
[6903.917] Invalid Reference on Leader_Flavors.LeaderType - "LEADER_HARALD" does not exist in Leaders
Using the snapshots
If you correctly set up your #Configuration, whenever you start a game, Civ5 saves a snapshot of the database under My Games/Sid Medier's Civilization V/cache/Civ5DebugDatabase.db
- This allows you to check how your XML and SQL files have been merged with the standard game data.
Lua Debugging
Using the Firetuner console
If you correctly set up your #Configuration, Civ5 will send all the Lua output to the Firetuner. This includes all the debugging output but also any error that may arise, with their calls stack traces.
Runtime Error: [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:41: attempt to concatenate local 'name' (a nil value) stack traceback: [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:41: in function 'dumpObj' [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:95: in function 'ScanAll' [string "C:\Users\Boss\Documents\My Games\Sid Meier'..."]:188: in main chunk [C]: ?
Here we can see that a C/C++ code (the game engine) ran the main chunk called (the Lua file), which then called the function ScanAll on line 188, which then called dumpObj on line 95. And this one caused an error on line 41.
Note that paths are truncated in the provided example, which makes debugging harder sometimes. This happens when the file is in a context registered by the project's content tab. Here are the workarounds:
- Register only a minimalist context, that will load additional contexts (through the UI LuaContext markup). Do not initiate any action from the root context, let the children context handle everything.
- Provide a custom stack trace, as explained in a further section.
Print, assert and error
print(...)
can be used to print anything to the Firetuner output. This allows you to check the flow of a program, or the values of variables. Print calls tostring on every argument and displays them all on a single line with tabulations as separators between them. Nil values are not displayed, so it is advised you provide expressions such as: (expr or 'nil')
error(string message, int level = 1)
throws an error with the specified message. The execution is then halted and the hand returned to the game engine (or the current protected call if you did use pcall or xpcall). The level parameter controls the error position that will be reported. 1 for the line where error is located, 2 for the function call that contained an error, etc. 0 for no position.
assert(variant condition, string message = "assertion failed")
can be used to assert the provided condition is neither nil nor false (everything else is evaluated to true in Lua). Otherwise, an error with the specified message is thrown. You can use them punctually, as a debugging technique. But they may also be used as a defensive programming technique such as [url=http://en.wikipedia.org/wiki/Design_by_contract design-by-contract]: the idea is that whenever your program's correctness relies on an assumption, you should explicitly check it. For example, if a function takes an array as an argument and assumes that it is not empty, you should add two conditions at the beginning: assert(type(t) == "table")
and assert(#t > 0)
. This makes the code more self-explanatory (implicit assumptions are now explicitly stated) and it allows you to catch bugs as soon as possible, which typically makes them easier to understand and fix.
Custom stack traces
Coroutines stack traces
Handling errors for the end-user
Troubleshooting
Game inspectors
Quick bug reproduction
Configuration
Look for the following files under My Documents/My Games/Sid Meiers' Civilization V
and open them in a text editor like the notepad (not in a word processor).
- config.ini
- Set
LoggingEnabled
to 1. Civ5 will write log files under theLogs
folder. - Set
EnableLuaDebugLibrary
to 1. Civ5 will display stack traces on Lua errors and you will be able to use the debug object. - Set
DebugPanel
to 1. By pressing the ² key (may be ù or something else depending on your computer's language) during a game, Civ5 will display a debug panel.
- Set
- usersettings.ini
- Set
DebugMode
to 1. Needed to enable other features previously mentioned.
- Set