You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: contrast NonPublicized vs Publicized in two plugins
Split the example into two RocketMod plugins pinned to the SAME game build
(3.26.3.3), differing only in the redist package:
- NonPublicized -> RocketModFix.Unturned.Redist.Server (public API only)
- Publicized -> ...Server.Publicized + AllowUnsafeBlocks, reads the
non-public Provider.isDedicatedUGCInstalled
Verified the contrast: the non-public field fails to compile against the plain
redist (CS0117). Add a classic .sln (builds on any SDK), build both in CI, and
have Dependabot ignore the two redist packages so the pinned versions stay in
lockstep.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+37-21Lines changed: 37 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,33 +1,48 @@
1
1
# RocketModFix.Unturned.Redist.Example
2
2
3
-
A minimal [RocketMod](https://github.com/RocketModFix/RocketModFix)plugin showing how to consume the RocketModFix NuGet packages in an Unturned server plugin — in particular the [`RocketModFix.Unturned.Redist`](https://github.com/RocketModFix/RocketModFix.Unturned.Redist)**`.Publicized`** package, which lets a plugin read members that are non-public in the stock game.
3
+
Two minimal [RocketMod](https://github.com/RocketModFix/RocketModFix)plugins that show how to consume the RocketModFix NuGet packages in an Unturned server plugin — and, side by side, exactly what the [`RocketModFix.Unturned.Redist`](https://github.com/RocketModFix/RocketModFix.Unturned.Redist)**`.Publicized`** package changes.
4
4
5
-
> This is an example **consumer**plugin. Its own namespace is `UnturnedRedistExample` — i.e. what *you'd* write in your own plugin — it just **references** the RocketModFix packages.
5
+
> These are example **consumer**plugins — their namespaces (`UnturnedRedistExample.*`) are what *you'd* write in your own plugin; they just **reference** the RocketModFix packages.
6
6
7
-
## What it demonstrates
7
+
## The two plugins
8
8
9
-
[`UnturnedRedistExamplePlugin.cs`](UnturnedRedistExamplePlugin.cs) is one class. On load it reads `SDG.Unturned.Provider.isDedicatedUGCInstalled` — a field that is **non-public** in the stock `Assembly-CSharp.dll` — and logs it:
Both reference the **same game build** (`3.26.3.3`) and are otherwise identical RocketMod plugins. The redist package is the only meaningful difference — that's the whole lesson.
15
+
16
+
### `NonPublicized` — public API only
17
+
18
+
Reads a **public** member and logs it. The non-public member is shown commented out, because it does **not** compile against the plain redist:
10
19
11
20
```csharp
12
-
protectedoverridevoidLoad()
13
-
{
14
-
// non-public in stock Unturned; reachable only via the .Publicized redist
- It **compiles** only because the project references `RocketModFix.Unturned.Redist.Server.Publicized` (the publicizer rewrites that field to public).
23
-
- It **runs** only because the `.csproj` sets `<AllowUnsafeBlocks>true</AllowUnsafeBlocks>`, which lets Unturned's Mono runtime skip the access check.
38
+
This compiles only because the `.Publicized` package rewrites that member to public, and runs only because the `.csproj` sets `<AllowUnsafeBlocks>true</AllowUnsafeBlocks>` (which lets Unturned's Mono runtime skip the access check).
24
39
25
-
## Packages used
40
+
## Packages used (both plugins)
26
41
27
42
| Package | Why |
28
43
| --- | --- |
29
-
|[`RocketModFix.Rocket.Unturned`](https://www.nuget.org/packages/RocketModFix.Rocket.Unturned)|The RocketMod API — provides the `RocketPlugin` base class and `Logger`. |
30
-
|[`RocketModFix.Unturned.Redist.Server.Publicized`](https://www.nuget.org/packages/RocketModFix.Unturned.Redist.Server.Publicized)| Unturned's server assemblies, **publicized** so the plugin can touch non-public members. Use [`…Server`](https://www.nuget.org/packages/RocketModFix.Unturned.Redist.Server) (without `.Publicized`) if you don't need that. |
44
+
|[`RocketModFix.Rocket.Unturned`](https://www.nuget.org/packages/RocketModFix.Rocket.Unturned)| RocketMod API — the `RocketPlugin` base class and `Logger`. |
|[`RocketModFix.UnityEngine.Redist`](https://www.nuget.org/packages/RocketModFix.UnityEngine.Redist)| UnityEngine assemblies — required because Unturned types derive from `UnityEngine.MonoBehaviour`. |
32
47
33
48
See the [redist README](https://github.com/RocketModFix/RocketModFix.Unturned.Redist#using-a-publicized-package) for more on `.Publicized` and `AllowUnsafeBlocks`.
@@ -38,19 +53,20 @@ See the [redist README](https://github.com/RocketModFix/RocketModFix.Unturned.Re
38
53
dotnet build -c Release
39
54
```
40
55
41
-
The plugin DLL lands in `bin/Release/net461/UnturnedRedistExample.dll`. CI builds it on every push — see [`.github/workflows/build.yaml`](.github/workflows/build.yaml).
56
+
Builds both projects (via `UnturnedRedistExample.sln`); the DLLs land in each project's `bin/Release/net461/`. CI builds both on every push — see [`.github/workflows/build.yaml`](.github/workflows/build.yaml).
42
57
43
58
## Verify it loads on a server
44
59
45
60
1. Install [RocketModFix](https://github.com/RocketModFix/RocketModFix#installation) on an Unturned dedicated server (copy the `Rocket.Unturned` folder into `Modules/`) and start it once so it generates `Servers/<ServerID>/Rocket/`.
46
-
2. Copy the built `UnturnedRedistExample.dll` into `Servers/<ServerID>/Rocket/Plugins/` (the DLL goes directly in `Plugins/`, not a subfolder).
47
-
3. Start the server and watch the console for:
61
+
2. Copy either built DLL into `Servers/<ServerID>/Rocket/Plugins/` (DLLs go directly in `Plugins/`, not a subfolder).
62
+
3. Start the server and watch the console:
48
63
49
64
```
50
-
[UnturnedRedistExample] Loaded. Read non-public Provider.isDedicatedUGCInstalled = ... via the .Publicized redist.
[UnturnedRedistExample.Publicized] Loaded. Read NON-public Provider.isDedicatedUGCInstalled = False via the .Publicized redist.
51
67
```
52
68
53
-
That line confirms two things at once: the plugin **loaded**, and the **publicized** member was read successfully **at runtime** (so `AllowUnsafeBlocks` did its job). If publicization were broken you'd instead get a `FieldAccessException`/ "is inaccessible" error.
69
+
The `Publicized`line is the key one: it proves the non-public member was read **at runtime** (so `AllowUnsafeBlocks` did its job). If publicization were broken you'd get a `FieldAccessException`("is inaccessible") instead.
0 commit comments