Modding:C Sharp Scripting: Difference between revisions

m Added location for Mods.csproj on Linux. Unsure if this location is different on Debian based distros, but on Arch Linux, this should be the correct directory.
fix typo: cproj -> csproj
 
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:Script Modding]]{{Modding Info}}
[[Category:Modding]][[Category:Modding Resources]]{{Modding Info}}
==Overview==
Caves of Qud loads a majority of its content via reflection. You may add new files to its database of reflectable objects by including .cs files in your mod. These files are compiled at runtime into an assembly and the type resolver will first check for types in the mod assembly before checking the Caves of Qud game assembly, thus you may add new types or override existing types by including classes with the right naming convention in your mod.


Since your mod runs with full privileges, users must approve mods each time they change, to allow any changes in code to be screened before they execute. This approval mechanism is currently only available via the overlay UI so it either must be enabled or mod approval must be disabled for scripting mods to work properly. If your mod scripts are not approved, no files in your mod will be loaded, to prevent definitions from not having the appropriate classes available in the mod's assembly.
Caves of Qud is programmed in the C Sharp v9.0 language (commonly abbreviated to "C#" or "cs"). Caves of Qud loads a majority of its content via reflection. You may add new files to its database of reflectable objects by including .cs files in your mod. These files are compiled at runtime into an assembly, meaning that adding new C# code is technically as simple as including <code>.cs</code> files somewhere in your mod directory.
==Nosing Around==
There's no official DLL to assemble against or open source project but if you want to dig around in the source code you can use [https://github.com/icsharpcode/ILSpy/releases ILSpy], [https://www.jetbrains.com/decompiler/ dotPeek], or [http://stackoverflow.com/questions/2646707/something-better-than-net-reflector one of various other decompilation tools] on <code>Caves of Qud\CoQ_Data\Managed\Assembly-CSharp.dll</code>


The XRL.World.Parts namespace contains all the part definitions in the game, so it's a good place to start digging.
C Sharp mods run with the full privileges of the base game. As such, they represent a security risk if any mod were to include malicious code. Whenever a C Sharp mod is changed, users are required to approve the mod to run before it can be loaded. The user will be prompted with a mod approval popup before creating or loading a save file. If the mod is not approved none of its files will be loaded, including files other than <code>.cs</code> files.


===Cross-Platform (Including Linux)===
==Obtaining the Source Code==


[https://www.monodevelop.com/ MonoDevelop], which is cross-platform (and in particular runs on Linux), comes with its own disassembly tool.
There is not a public repository of Caves of Qud's source code. However, there are several third-party tools available for decompiling <code>.dll</code> files into equivalent <code>.cs</code> files. Due to the nature of decompilation the decompiled file will be somewhat different from the original: Names of variables, objects, and methods may be different and there will be no code comments.


# Run MonoDevelop.
[https://github.com/icsharpcode/ILSpy/releases ILSpy] can be used to decompile the source code. Point it at <code>Assembly-CSharp.dll</code>, which can be found in the [[File_locations | QudLibPath]] directory. From here the code can be browsed from within ILSpy, or you can save the decompiled code and open it with another program. Note that the decompiled code will normally have errors due to being removed from its intended context.
# Go to File→Open….
# Locate the abovementioned assembly file and open it. This will open the Assembly Browser.
# In the dropdown next to where it says "Language", select "C#".
# Now you can start digging in the disassembled C# source code by selecting some of the game's classes from the sidebar.


====Working on Mac====
==Setting Up a Development Environment==


Sometimes, Monodevelop/Visual Studio do not render the assembly properly when you munge in the raw DLL.
While in theory any plaintext editor can be used for C# programming, this setup guide will detail using [https://visualstudio.microsoft.com/ Microsoft Visual Studio]. Visual Studio natively supports the C# language and ships with the [https://github.com/icsharpcode/ILSpy ILSpy] .NET decompilation engine included. As such, there is no need to install any extra plugins or third-party tools to start programming with Visual Studio. Note that Microsoft Visual Studio is an entirely seperate program from Microsoft Visual Studio '''Code'''.


To get around this, use ILSpy to decompile the code:
===Visual Studio Setup Guide===


# Install Visual Studio: http://visualstudio.microsoft.com/vs/mac/
# Create a folder somewhere to act as your modding folder, and create a folder inside of that for your specific mod. This will serve as the working directory for the mod. It is not recommended that this be inside the Mods folder of the game, as this folder will also contain some auto-generated files from Visual Studio that are not necessary to include in your finished mod.
#* Make sure you have the [https://download.visualstudio.microsoft.com/download/pr/19f39d7d-3296-4ed2-af75-f0190d074d43/84949e2b33ccdc6b7c51d5835df2844e/dotnet-sdk-2.2.301-osx-gs-x64.pkg .net Core SDK]
# Launch Caves of Qud. In the settings menu, navigate to the "Modding" section and enable "Enable Mods (restart required.)", "Select enabled mods on new game.", and "Allow scripting mods. Scripting mods may contain malicious code!". <br>[[File:CoQ_cs_ModdingSettings.png|1024px]]
# Open up a terminal and install ilspycmd: <code>dotnet tool install ilspycmd -g</code>
# Close and re-open the game to allow mods to be enabled. In the bottom-right corner of the title screen, there will be two new options: "Installed Mod Configuration" and "Modding Utilities". Click "Modding Utilities", then select "Write Mods.csproj file". This will create a <code>Mods.csproj</code> file in your [[File_locations | configuration files directory]]. <code>.csproj</code> files are C# project files that Visual Studio can load to configure your development environment.
# Find the directory Caves of Qud is installed in - for Steam this is <code>$HOME/Library/Application Support/Steam/steamapps/common/Caves of Qud/CoQ.app</code>
# Copy <code>Mods.csproj</code> into the folder that you created as a working directory for your mod, then open it in Visual Studio. Visual Studio will automatically create <code>obj</code>, <code>bin</code>, and <code>.vs</code> directories, which are metadata used by Visual Studio and can be ignored.
# Using the full path of the Assembly file, run the following in a terminal:
# From here, you are fully set-up to start coding. However, you may want to make some edits to <code>Mods.csproj</code>. Changing its name will change the project name in Visual Studio, which may be helpful for distinguishing multiple projects. You can also edit the fields of the file in order to change your Author title, AssemblyName, or other fields. <br>Due to [https://bitbucket.org/bbucklew/cavesofqud-public-issue-tracker/issues/9116 Issue #9116], you may see approximately 50 warnings in the error list. This is because <code>Mods.csproj</code> erroneously contains references to files which do not actually exist in the public release of Caves of Qud. These warnings may safely be ignored, or the erroneous references can be deleted from the <code>Mods.csproj</code> file.
#* <code>ilspycmd -p -o ~/Qud_Code "$HOME/Library/Application Support/Steam/steamapps/common/Caves of Qud/CoQ.app/Contents/Resources/Data/Managed/Assembly-CSharp.dll"</code>
# You can press F12 in order to navigate to the definition of a selected object, variable, or method. If the definition is in the source code, Visual Studio will automatically decompile and open the relevant file.
#* You can replace <code>~/Qud_Code</code> with any other directory, if you have a certain place you want to put it.
# Open Visual Studio, then open the csproj file at ~/Qud_Code/Assembly-CSharp.csproj


== Mod Development Setups ==
== Debugging ==
{{Cleanup | These instructions were found to contain errors and need to be revised for further errors.}}
'''Modding Using Visual Studio Code (Quick Setup)'''
 
Follow these steps in order to get Visual Studio Code to correctly parse and include the base game methods in Intellisense and similar tools (assuming you have the C# VSCode Extension):
 
# On the Caves of Qud main menu, with Mouse Overlay UI toggled on, go to "Modding Utilities" and select "Write Mods.csproj File". This will automatically create an XML file describing the setup needed that VSCode can read.
#Find the Mods.csproj file in your CoQ save data folder. On Windows, this is located in <code>%UserProfile%\AppData\LocalLow\Freehold Games\CavesOfQud</code>. On Linux, this is located in <code>~/.config/unity3d/Freehold Games/CavesOfQud/</code>
#Move it to your main modding directory you intend to work from. It is not recommended that this be a mod folder itself, as that will include both this csproj file and additional VSCode-generated files in the mod itself - it is a better idea to keep mods in their own folders and place the Mods.csproj and other exterior files into a parent folder. If you want to keep your Mods folder tidy, you can create your individual Mod folder elsewhere and then create a hardlink/junction to that folder inside of the Mods folder.
#Open VSCode in the folder that contains the Mods.csproj, you should now be able to reference Qud namespaces, classes and methods from your own code. As this just links directly to the DLLs, however, you will only get metadata information about those classes and such, which tends to include function signatures, variable names and similar, but not the actual code within those functions. You can look at the actual code using a decompiler as mentioned above, or if you want your code to directly reference the decompiled code follow the optional step 5.
#(Optional) In order to reference the decompiled code rather than the real DLLs, take save the decompiled code into a folder in the same directory as your mods then, to prevent conflicts, delete the "Assembly-CSharp.dll" line from your Mods.csproj. You will have to repeat this step each time the game updates if you want to be working with the most recent code, whereas the DLL links should stay updated. This is similar to the first two steps in the following section.


Note: I sometimes have issues with VSCode or Visual Studio attempting to pull in additional dependencies, which often leads to errors and are not necessary for Qud modding. I do not recommend clicking the "Resolve Dependencies" button if it appears, and if it does you may have to delete the generated ".vs" and "bin" folders in order to get it to work properly again.
Debug statements can be written directly to the message log using:


<syntaxhighlight lang="c#">
XRL.Messages.MessageQueue.AddPlayerMessage("Hello world!")
</syntaxhighlight>


'''Modding Using Visual Studio (Manual Setup)'''
Messages can also be written to <code>Player.log</code> using:


Follow these steps in order to get Visual Studio to correctly parse and include the decompiled code while you are writing your mod code (there are other methods, but this is the one I used):
<syntaxhighlight lang="c#">
 
UnityEngine.Debug.LogError("Hello world!")
# Using ILSpy, decompile Assembly-CSharp.dll as described above.
</syntaxhighlight>
# Right click on the "Assembly-CSharp" folder in the sidebar and select "Save Code", and then save it as a Visual Studio Project wherever you want, ideally outside of your mod code or the base game files, as otherwise things could get confused quick.
# In Visual Studio, create a new project from existing code, and select the folder that contains your mod.
# Once that project is open, go to File > Add > Existing Project and select the Visual Studio Project you saved your disassembled code as. You should now have both the disassembled code and your mod folder open as projects in a single solution.
# Go to Project > Project Dependencies and add the decompiled code project as a dependency of your mod project
# Right click on your mod project in the Solution Explorer, and select Add > Reference, and then go to "Projects" in the sidebar and select the disassembled code, before clicking "OK"
# Congrats, Visual Studio should now correctly parse your mod scripts against the existing game scripts. 
 
You may also want to add a reference to UnityEngine.CoreModule.dll in CoQ_Data/Managed if you want to have Visual Studio correctly include Unity code, and the same goes for any of the other dll's used by Qud, though I have found that just including UnityEngine.CoreModule.dll has been enough for all of my purposes.
 
== Debugging ==
Logging can be done either by outputting text to the in-game player console like this:<syntaxhighlight lang="c#">
XRL.Messages.MessageQueue.AddPlayerMessage("Hello, Im a message!")
</syntaxhighlight>Or can be output to the player.log file like this:<syntaxhighlight lang="c#">
UnityEngine.Debug.LogError()
</syntaxhighlight>Or by using other standard UnityEngine.Debug methods, as detailed here[https://docs.unity3d.com/ScriptReference/Debug.html]. Various options for ingame error popups and such can be found in the Debug section of the ingame options.


Errors that occur during the initial build of the game, when all the dependencies such as mods are pulled in are included in build-log.txt which can be useful to look at if there is no useful information in the player.log.  
Other <code>UnityEngine.Debug</code> methods are detailed [https://docs.unity3d.com/ScriptReference/Debug.html here] and can also be used to write to <code>Player.log</code>.


==Detailed Scripting Topics==
Errors that occur during the initial building-in of your mod files are logged in <code>build-log.txt</code>. These errors will usually cause a mod to be unable to build, which prevents it from being enabled by the player.
* [[Modding: Adding Code to the Player|Adding Code to the Player]]
* [[Modding: Creating New Mutations|Creating new mutations]]
* [[Modding: Activated Abilities|Adding active abilities]]


{{Modding Navbox}}
{{Modding Navbox}}