This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
bin/
|
||||
obj/
|
||||
artifacts/
|
||||
@@ -0,0 +1,102 @@
|
||||
# __PROJECT_NAME__
|
||||
|
||||
这是由 `ShrinkModFramework` 生成器创建的外部 DLL 模组模板。
|
||||
|
||||
## 模板内容
|
||||
|
||||
- `src/__PROJECT_NAME__Mod.cs`
|
||||
- 模组主入口,演示 `ShrinkModFramework + ShrinkEventBus + ShrinkCommand + ShrinkNetwork`
|
||||
- `src/__PROJECT_NAME__Contracts.cs`
|
||||
- 示例事件、RPC 请求与响应
|
||||
- `__PROJECT_NAME__.csproj`
|
||||
- 独立类库工程,默认引用当前 SDK 仓库里的运行时工程
|
||||
- `build.ps1`
|
||||
- 一键构建,可选复制 DLL 到你的模组目录
|
||||
- `dev-env.ps1`
|
||||
- 先设置 `MSBuildEnableWorkloadResolver=false`,适合有些 IDE 打开项目前先跑一遍
|
||||
- `global.json`
|
||||
- 锁定到生成模板时检测到的 `dotnet SDK` 版本
|
||||
|
||||
## 默认标识
|
||||
|
||||
- `ProjectName`: `__PROJECT_NAME__`
|
||||
- `Namespace`: `__ROOT_NAMESPACE__`
|
||||
- `ModId`: `__MOD_ID__`
|
||||
- `DisplayName`: `__DISPLAY_NAME__`
|
||||
|
||||
生成后建议你先改这几处,再开始写正式业务。
|
||||
|
||||
## 构建
|
||||
|
||||
```powershell
|
||||
dotnet build .\__PROJECT_NAME__.csproj -c Release /nr:false
|
||||
```
|
||||
|
||||
或者直接运行:
|
||||
|
||||
```powershell
|
||||
.\build.ps1
|
||||
```
|
||||
|
||||
如果你的 IDE 打开项目时报类似:
|
||||
|
||||
```text
|
||||
Microsoft.NET.SDK.WorkloadAutoImportPropsLocator
|
||||
```
|
||||
|
||||
先在 PowerShell 里执行:
|
||||
|
||||
```powershell
|
||||
.\dev-env.ps1
|
||||
```
|
||||
|
||||
然后在**同一个 shell** 里启动 IDE,或者直接继续 `dotnet build`。
|
||||
|
||||
默认产物输出到:
|
||||
|
||||
```text
|
||||
artifacts\Release\
|
||||
```
|
||||
|
||||
## 投放到游戏
|
||||
|
||||
`ShrinkModFramework` 当前会扫描:
|
||||
|
||||
```text
|
||||
Application.persistentDataPath/Mods
|
||||
```
|
||||
|
||||
所以常见流程是:
|
||||
|
||||
1. 先构建出 `__PROJECT_NAME__.dll`
|
||||
2. 把 DLL 复制到游戏实际使用的 `Mods` 目录
|
||||
3. 启动游戏,让 `ShrinkModLoader` 自动发现
|
||||
|
||||
如果你已经知道目标 `Mods` 目录,也可以直接用:
|
||||
|
||||
```powershell
|
||||
.\build.ps1 -ModsDir "D:\YourGameMods\Mods"
|
||||
```
|
||||
|
||||
## 这个模板示范了什么
|
||||
|
||||
- `[ShrinkMod]` 模组声明
|
||||
- `ShrinkModBase` 生命周期
|
||||
- `[ShrinkEventSubscriber]` / `[ShrinkSubscribe]` 生成式实例接入 Mod Bus
|
||||
- `ShrinkCommandSubscriber` 实例命令自动接入
|
||||
- `ShrinkNetworkSubscriber` 实例网络处理自动接入
|
||||
- `context.RegisterContent(...)` 使用 ModId namespace 注册内容
|
||||
- `context.OverrideContent(...)` 以显式优先级覆盖已有内容
|
||||
- `context.RegisterNetworkHandler(...)` 走模组网络抽象层
|
||||
|
||||
## 注意
|
||||
|
||||
- 示例里用到的 `opcode`、命令路径、`modId` 都只是模板默认值,正式模组请自己调整,避免冲突
|
||||
- 当前模板默认依赖当前仓库根目录下的:
|
||||
- `ShrinkModFramework.Runtime.csproj`
|
||||
- `ShrinkEventBus.Runtime.csproj`
|
||||
- `Assets/Modules/ShrinkEventBus/Tools~/DotNet/ShrinkEventBus.Generator/ShrinkEventBus.Generator.csproj`(作为 Roslyn analyzer)
|
||||
- `ShrinkCommand.Runtime.csproj`
|
||||
- `ShrinkNetwork.Runtime.csproj`
|
||||
- 如果你把模板工程移到别处,需要同步修正 `__PROJECT_NAME__.csproj` 里的 `ProjectReference`
|
||||
- 某些 IDE / MSBuild 环境里,`MSBuildEnableWorkloadResolver=false` 写在项目文件内仍然太晚;这种情况要靠 `dev-env.ps1` 或系统环境变量在**打开项目之前**先设置
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfa94a3d7a41c6b4e81e7675db94e55f
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net471</TargetFramework>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<MSBuildEnableWorkloadResolver>false</MSBuildEnableWorkloadResolver>
|
||||
<RootNamespace>__ROOT_NAMESPACE__</RootNamespace>
|
||||
<AssemblyName>__PROJECT_NAME__</AssemblyName>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<EnableDefaultCompileItems>true</EnableDefaultCompileItems>
|
||||
<OutputPath>artifacts\$(Configuration)\</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="__SDK_ROOT_RELATIVE__\ShrinkModFramework.Runtime.csproj" />
|
||||
<ProjectReference Include="__SDK_ROOT_RELATIVE__\ShrinkEventBus.Runtime.csproj" />
|
||||
<ProjectReference Include="__SDK_ROOT_RELATIVE__\Assets\Modules\ShrinkEventBus\Tools~\DotNet\ShrinkEventBus.Generator\ShrinkEventBus.Generator.csproj"
|
||||
OutputItemType="Analyzer"
|
||||
ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="__SDK_ROOT_RELATIVE__\ShrinkCommand.Runtime.csproj" />
|
||||
<ProjectReference Include="__SDK_ROOT_RELATIVE__\ShrinkNetwork.Runtime.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 770057fe3b5782f4ba28e2e36f087b96
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
param(
|
||||
[string]$Configuration = "Release",
|
||||
[string]$ModsDir = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$projectPath = Join-Path $PSScriptRoot "__PROJECT_NAME__.csproj"
|
||||
dotnet build $projectPath -c $Configuration /nr:false
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
exit $LASTEXITCODE
|
||||
}
|
||||
|
||||
$artifactDir = Join-Path $PSScriptRoot ("artifacts\" + $Configuration)
|
||||
$dllPath = Join-Path $artifactDir "__PROJECT_NAME__.dll"
|
||||
|
||||
Write-Host "Build completed: $dllPath"
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($ModsDir)) {
|
||||
return
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $ModsDir | Out-Null
|
||||
Copy-Item -LiteralPath $dllPath -Destination (Join-Path $ModsDir "__PROJECT_NAME__.dll") -Force
|
||||
|
||||
$pdbPath = Join-Path $artifactDir "__PROJECT_NAME__.pdb"
|
||||
if (Test-Path -LiteralPath $pdbPath) {
|
||||
Copy-Item -LiteralPath $pdbPath -Destination (Join-Path $ModsDir "__PROJECT_NAME__.pdb") -Force
|
||||
}
|
||||
|
||||
Write-Host "Copied artifacts to: $ModsDir"
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 956930660ab00e74692b22857f3159b7
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
$env:MSBuildEnableWorkloadResolver = "false"
|
||||
|
||||
Write-Host "MSBuildEnableWorkloadResolver=false"
|
||||
Write-Host "Current dotnet: $(dotnet --version)"
|
||||
Write-Host ""
|
||||
Write-Host "现在请在这个 PowerShell 里启动你的 IDE,或直接在这个 shell 里运行 dotnet build。"
|
||||
Write-Host "示例:"
|
||||
Write-Host " dotnet build .\\__PROJECT_NAME__.csproj -c Release /nr:false"
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56c53370b8dbbab4ea70d4566bc1fed8
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "__DOTNET_SDK_VERSION__",
|
||||
"rollForward": "latestPatch"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48ebb276437630c4495d82c4c8e4ae2e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8713158fd023ce48abfb7365184ac7c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
#nullable enable
|
||||
|
||||
using ShrinkEventBus;
|
||||
using ShrinkNetwork;
|
||||
|
||||
namespace __ROOT_NAMESPACE__
|
||||
{
|
||||
public sealed class __PROJECT_NAME__Event : IShrinkEvent
|
||||
{
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[ShrinkNetworkMessage(__REQUEST_OPCODE__, "__ROUTE_PREFIX__/ping")]
|
||||
public sealed class __PROJECT_NAME__PingRequest : IShrinkNetworkRequest
|
||||
{
|
||||
public string Message { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
[ShrinkNetworkMessage(__RESPONSE_OPCODE__, "__ROUTE_PREFIX__/ping_response")]
|
||||
public sealed class __PROJECT_NAME__PingResponse : ShrinkRpcResponseBase
|
||||
{
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public int Counter { get; set; }
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4ff81758d9539947ba6f4df94c2db91
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
#nullable enable
|
||||
|
||||
using ShrinkCommand;
|
||||
using ShrinkEventBus;
|
||||
using ShrinkModFramework;
|
||||
using ShrinkNetwork;
|
||||
|
||||
namespace __ROOT_NAMESPACE__
|
||||
{
|
||||
[ShrinkMod("__MOD_ID__", "__DISPLAY_NAME__", "1.0.0")]
|
||||
[ShrinkEventSubscriber(OwnerId = "__MOD_ID__", DefaultBus = "mod:__MOD_ID__")]
|
||||
[ShrinkCommandSubscriber]
|
||||
[ShrinkNetworkSubscriber]
|
||||
public sealed partial class __PROJECT_NAME__Mod : ShrinkModBase
|
||||
{
|
||||
private readonly RuntimeState _state = new();
|
||||
|
||||
public override void OnConstruct(ShrinkModContext context)
|
||||
{
|
||||
context.Log("模组已构造。");
|
||||
}
|
||||
|
||||
public override void OnRegisterContent(ShrinkModContext context)
|
||||
{
|
||||
context.RegisterContent("example.items", "example_item", "__DISPLAY_NAME__ Item");
|
||||
}
|
||||
|
||||
public override void OnInitialize(ShrinkModContext context)
|
||||
{
|
||||
context.RegisterNetworkHandler<int>("sync.counter", (_, value) =>
|
||||
{
|
||||
_state.Counter = value;
|
||||
context.Log("收到模组网络计数:" + value);
|
||||
});
|
||||
}
|
||||
|
||||
[ShrinkSubscribe]
|
||||
private void OnExampleEvent(__PROJECT_NAME__Event evt)
|
||||
{
|
||||
_state.LastEventMessage = evt.Message ?? string.Empty;
|
||||
_state.Counter++;
|
||||
}
|
||||
|
||||
[ShrinkCommand("__COMMAND_ROOT__ ping", Description = "测试模组命令", Permission = "__MOD_ID__.command.ping")]
|
||||
private string Ping()
|
||||
{
|
||||
return "pong:" + _state.Counter;
|
||||
}
|
||||
|
||||
[ShrinkNetworkSubscribe(Permission = "__MOD_ID__.rpc.ping")]
|
||||
private __PROJECT_NAME__PingResponse HandlePing(__PROJECT_NAME__PingRequest request)
|
||||
{
|
||||
return new __PROJECT_NAME__PingResponse
|
||||
{
|
||||
Message = "pong:" + (request.Message ?? string.Empty),
|
||||
Counter = _state.Counter
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class RuntimeState
|
||||
{
|
||||
public int Counter { get; set; }
|
||||
public string LastEventMessage { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2a0ac418f07ef74393b89e9612e3f5f
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user