Skip to content

Commit

Permalink
Initial docfx setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Fexty12573 committed Apr 9, 2024
1 parent 0177ef9 commit 877e4a8
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 41 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/docfx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
on:
pull-request:
branches:
- master
push:
branches:
- master

permissions:
actions: read
pages: write
id-token: write

concurrency:
group: "docs"
cancel-in-progress: false

jobs:
publish-docs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: .NET Setup
uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.x

- run: dotnet tool install -g docfx
- run: docfx docfx.json
working-directory: docs

- name: Upload artifact
uses: actions/upload-artifact@v3
working-directory: ${{env.GITHUB_WORKSPACE}}
with:
path: _site
- name: Deploy
id: deployment
uses: actions/deploy-pages@v4
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ bld/
Generated\ Files/
Generated/
venv/
docs/_site/

# MSTest test Results
[Tt]est[Rr]esult*/
Expand Down
32 changes: 16 additions & 16 deletions docs/Development/CallingNativeFuncs.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
The framework already provides access to a lot of game functions, but sometimes something may not be available.
In these cases you can call native functions directly from your plugin.

!!! warning
Calling native functions can lead to crashes very quickly if done incorrectly.
Make sure you know what you're doing and test your code thoroughly.
> [!WARNING]
> Calling native functions can lead to crashes very quickly if done incorrectly.
> Make sure you know what you're doing and test your code thoroughly.
If you're already familiar with calling function pointers in C++, you can just read the API Reference for the [`NativeFunction`]() class and the [`NativeAction`]() class.

Expand Down Expand Up @@ -51,13 +51,13 @@ var myFunction = new NativeAction<int, float>(0x140000000);
myFunction.Invoke(1, 2.0f);
```

!!! info
The framework also provides a `NativeFunction` class, which is identical to `NativeAction` except it returns a value. If your function doesn't return a value, you can use `NativeAction`,
otherwise you need to use `NativeFunction`.
```csharp
var myFunction = new NativeFunction<int, float, int>(0x140000000);
int result = myFunction.Invoke(1, 2.0f);
```
> [!NOTE]
> The framework also provides a `NativeFunction` class, which is identical to `NativeAction` except it returns a value. If your function doesn't return a value, you can use `NativeAction`,
> otherwise you need to use `NativeFunction`.
> ```csharp
> var myFunction = new NativeFunction<int, float, int>(0x140000000);
> int result = myFunction.Invoke(1, 2.0f);
> ```
You call the native function using the `Invoke` property of the object. This is a bit different from how you would call a normal delegate, but unfortunately, C# doesn't allow overloading the `()` operator so this is the best we can do.
Expand All @@ -70,9 +70,9 @@ var myFunction = new NativeAction<int, float>(0x140000000);
myFunction.InvokeUnsafe(1, 2.0f);
```
!!! warning
`InvokeUnsafe` is unsafe for a reason. When you're calling a function using this there are some things you need to pay attention to.
Due to the fact that the GC does not get transitioned, the native function you are calling is not allowed to call back into managed code. So if the function you are calling happens to be hooked by another C# plugin, your game will crash immediately.

It also should not run for more than 1 microsecond. You can see a full list of constraints for this [here](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.suppressgctransitionattribute?view=net-8.0).
> [!WARNING]
> `InvokeUnsafe` is unsafe for a reason. When you're calling a function using this there are some things you need to pay attention to.
>
> Due to the fact that the GC does not get transitioned, the native function you are calling is not allowed to call back into managed code. So if the function you are calling happens to be hooked by another C# plugin, your game will crash immediately.
>
> It also should not run for more than 1 microsecond. You can see a full list of constraints for this [here](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.suppressgctransitionattribute?view=net-8.0).
14 changes: 7 additions & 7 deletions docs/Development/FunctionHooking.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ Let's break this down. First, we declare a delegate type with the same signature
```csharp
private delegate void ReleaseResourceDelegate(nint resourceManager, nint resourcePtr);
```
!!! info
Type marshalling is very limited for function hooks. Generally the only type that is automatically marshalled is `string`. You can also
add the `UnmanagedFunctionPointer` attribute to the delegate to specify the character set, but this is not required.
> [!NOTE]
> Type marshalling is very limited for function hooks. Generally the only type that is automatically marshalled is `string`. You can also
> add the `UnmanagedFunctionPointer` attribute to the delegate to specify the character set, but this is not required.
Next we declare a hook object. This object needs to be kept alive by the plugin, otherwise the hook will be removed. It also allows dynamically enabling and disabling the hook.
```csharp
Expand All @@ -64,10 +64,10 @@ private void ReleaseResourceHook(nint resourceManager, nint resourcePtr)
_releaseResourceHook.Original(resourceManager, resourcePtr);
}
```
!!! warning
Once you create a `Resource` object around a `cResource` pointer, it will automatically increment the resources reference count by 1. Once the `Resource` object is collected by the garbage collector, it will decrement the reference count by 1 again. If the reference count reaches 0, the resource will be unloaded.
This means that so long as you hold a reference to a `Resource` object, the resource will never be unloaded (unless the game force-unloads it for some reason, but that should generally not be the case).
> [!WARNING]
> Once you create a `Resource` object around a `cResource` pointer, it will automatically increment the resources reference count by 1. Once the `Resource` object collected by the garbage collector, it will decrement the reference count by 1 again. If the reference count reaches 0, the resource will be unloaded.
>
> This means that so long as you hold a reference to a `Resource` object, the resource will never be unloaded (unless the game force-unloads it for some reason, but that should generally not be the case).
Of course, you can also use a lambda expression instead of a separate method for the detour. This makes the code a bit more compact for simple hooks.
```csharp
Expand Down
14 changes: 7 additions & 7 deletions docs/Development/GameObjects.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ public class EquipWork : MtObject
public EquipWork() { }
}
```
!!! info
The parameterless constructor is only required if you want to use this object with `NativeWrapper.GetObject<T>()` (and similar), as those methods
require a parameterless constructor.
> [!NOTE]
> The parameterless constructor is only required if you want to use this object with `NativeWrapper.GetObject<T>()` (and similar), as those methods
> require a parameterless constructor.
Now we can add the fields we want to access. We can use the methods provided by `NativeWrapper` (which `MtObject` inherits from) to read and write data to the native object.
```csharp
Expand Down Expand Up @@ -147,14 +147,14 @@ By 'heap-allocated array' I mean an array where the containing object only holds
```csharp
public Span<int> Array => new Span<int>(GetPtr(0x20), 10);
```
!!! info
If you want to use a native array in an async or an iterator method, you can use `NativeArray<T>` instead.
> [!NOTE]
> If you want to use a native array in an async or an iterator method, you can use `NativeArray<T>` instead.
#### Inline arrays
Inline arrays are arrays that are stored directly inside the object. The approach here is similar to the one for heap-allocated arrays, except that you use `GetPtrInline` instead of `GetPtr`.
```csharp
public Span<int> Array => new Span<int>(GetPtrInline(0x20), 10);
```

!!! warning
Both `Span<T>` and `NativeArray<T>` must **not** be used with any reference types. This includes `MtObject`. Instead use `Span<nint>` or `NativeArray<nint>` and simply construct an object when you need it (e.g. `new MtObject(span[i])`).
> [!WARNING]
> Both `Span<T>` and `NativeArray<T>` must **not** be used with any reference types. This includes `MtObject`. Instead use `Span<nint>` or `NativeArray<nint>` and simply construct an object when you need it (e.g. `new MtObject(span[i])`).
8 changes: 4 additions & 4 deletions docs/Development/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Alternatively you can install the package from the command line using the `dotne
dotnet add package SharpPluginLoader.Core
```

!!! info
It is also recommended to enable unsafe code in the project properties, as it is required for some features such as native function wrappers.
> [!TIP]
> It is also recommended to enable unsafe code in the project properties, as it is required for some features such as native function wrappers.
## Entry point
Each plugin has an entry point class, which must implement the `IPlugin` interface inside the `SharpPluginLoader.Core` namespace.
Expand Down Expand Up @@ -51,8 +51,8 @@ public void OnLoad()

In the `Initialize` method you need to return a `PluginData` object, which contains some optional details about the plugin.

!!! info
You should not do any game-related initialization in the `Initialize` method, as it is called before the game is fully loaded. Use the `OnLoad` method for that.
> [!NOTE]
> You should not do any game-related initialization in the `Initialize` method, as it is called before the game is fully loaded. Use the `OnLoad` method for that.
The `OnLoad` method is where you will normally do any setup that you need to do when the plugin is loaded. This method is called every time the plugin is loaded, so it's a good place to initialize any resources that you need.

Expand Down
14 changes: 14 additions & 0 deletions docs/Development/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- name: Getting Started
href: GettingStarted.md
- name: Game Objects
href: GameObjects.md
- name: Function Hooking
href: FunctionHooking.md
- name: Calling Native Functions
href: CallingNativeFuncs.md
- name: Rendering with ImGui
href: ImGui.md
- name: Rendering
href: Rendering.md
- name: Native Components
href: NativeComponents.md
8 changes: 4 additions & 4 deletions docs/Examples/API/DirectMemoryAccess.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ using (var myArray = NativeArray<int>.Create(10))
// Do something with the array
} // The array is freed here
```
!!! warning
If you don't use `using`, you have to call `Dispose` manually, otherwise the array will not be freed.
> [!WARNING]
> If you don't use `using`, you have to call `Dispose` manually, otherwise the array will not be freed.
If performance is critical, you can also use `Span<T>` to wrap existing arrays.
```csharp
Expand Down Expand Up @@ -105,8 +105,8 @@ MemoryUtil.GetRef<int>(memory + 0x10) = 42;
// Free the memory
MemoryUtil.Free(memory); // Do not forget this!
```
!!! warning
Allocating native memory is dangerous, as it can cause memory leaks if not freed properly.
> [!WARNING]
> Allocating native memory is dangerous, as it can cause memory leaks if not freed properly.
## Utility
There are some utility methods in the `MemoryUtil` class that can be helpful in certain scenarios.
Expand Down
6 changes: 6 additions & 0 deletions docs/Examples/API/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- name: Direct Memory Access
href: DirectMemoryAccess.md
- name: Logging
href: Logging.md
- name: User Input
href: UserInput.md
6 changes: 6 additions & 0 deletions docs/Examples/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- name: Quest End Skip
href: Plugins/QuestEndSkip.md
- name: Idle Monsters
href: Plugins/IdleMonsters.md
- name: API Examples
href: API/toc.yml
6 changes: 3 additions & 3 deletions docs/Installation.md → docs/Install/Installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ If you installed everything correctly you should now find `winmm.dll` in the sam
Any C# plugins will be placed directly into the `CSharp` directory. The plugin loader will automatically load all DLLs in this directory.
Subdirectories are also supported, so you can organize your plugins however you want.

!!! warning
Putting plugins inside the `nativePC\plugins\CSharp\Loader` directory will **not** work. The plugin loader will not load them.
See [below](#directory-structure-examples) for an example of a valid directory structure.
> [!NOTE]
> Putting plugins inside the `nativePC\plugins\CSharp\Loader` directory will **not** work. The plugin loader will not load them.
> See [below](#directory-structure-examples) for an example of a valid directory structure.
Once you have all your plugins installed you can simply start the game. The plugin loader will automatically load all plugins.
Depending on the plugins you have installed you might also see an overlay/UI appear on the screen.
Expand Down
46 changes: 46 additions & 0 deletions docs/docfx.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"metadata": [
{
"src": [
{
"src": "../SharpPluginLoader.Core",
"files": [
"SharpPluginLoader.Core.csproj"
]
}
],
"dest": "API/Generated"
}
],
"build": {
"content": [
{
"files": [
"**/*.{md,yml}"
],
"exclude": [
"_site/**"
]
}
],
"resource": [
{
"files": [
"images/**"
]
}
],
"output": "_site",
"template": [
"default",
"modern"
],
"postProcessors": ["ExtractSearchIndex"],
"globalMetadata": {
"_appName": "SharpPluginLoader",
"_appTitle": "SharpPluginLoader",
"_enableSearch": true,
"pdf": false
}
}
}
4 changes: 4 additions & 0 deletions docs/docs/_site/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"source_base_path": "C:/dev/SharpPluginLoader/docs",
"files": []
}
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
---
_layout: landing
---

<div align="center">
<h1>SharpPluginLoader</h1>
</div>
Expand Down
8 changes: 8 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- name: Installation
href: docs/Install/Installation.md
- name: Plugin Development
href: docs/Development/
- name: API Reference
href: docs/API/Generated/
- name: Examples
href: docs/Examples/
File renamed without changes.

0 comments on commit 877e4a8

Please sign in to comment.