Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
154 commits
Select commit Hold shift + click to select a range
f7c3833
refactor(convert): start converting project `Plain Craft Launcher 2` …
SALTWOOD Feb 21, 2026
eb456bb
feat(logger): ILogger 支持 (#2447)
tangge233 Feb 21, 2026
87e0c67
chore(bump): 2.14.3-beta.1 (#2462)
tangge233 Feb 21, 2026
37afbd2
fix(mmc-modpack): PreLaunchCommand Java 参数替换错误 (#2466)
tangge233 Feb 21, 2026
2f5c7e0
ref(csharp): initial commit
SALTWOOD Feb 21, 2026
5eee1bb
Merge branch 'dev' into dev
MoYuan-CN Feb 21, 2026
e69b4ee
chore: remove vb files
MoYuan-CN Feb 21, 2026
5129f05
chore: modify project slnx def
MoYuan-CN Feb 21, 2026
508262b
chore(csproj): remove My references
MoYuan-CN Feb 21, 2026
4e8a2dd
fix(ci): vbproj -> csproj
Pigeon0v0 Feb 22, 2026
9df54a8
fix: ci
Pigeon0v0 Feb 22, 2026
397dcbd
refactor: 修改部分 ModSetup 调用为 Config
Pigeon0v0 Feb 22, 2026
4d6908f
fix(link): 连个寂寞的配置下发的服务器 (#2467)
tangge233 Feb 22, 2026
265c39f
refactor(mc-ping): 重构 McPing 的实现 (#2465)
tangge233 Feb 22, 2026
c1d28ff
fix(components): 补齐几乎所有组件中的 `InitializeComponent();` 防止主窗体无法初始化
Big-Cake-jpg Feb 22, 2026
b9a13e2
fix(setup): invalid implicit conversion caused `ArgumentException`
SALTWOOD Feb 22, 2026
4b6d525
Revert "chore: remove vb files"
SALTWOOD Feb 22, 2026
0270924
fix(select-left): 恢复被截断的 logo
LuLu-ling Feb 22, 2026
f052879
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 22, 2026
7b91af9
fix config loading type cast
ruattd Feb 22, 2026
15eace5
fix(FormMain): Add `BtnTitleClose_Blick`
SALTWOOD Feb 22, 2026
7abfd8e
chore: 阶段性提交
MoYuan-CN Feb 22, 2026
98aa615
chore: push
Pigeon0v0 Feb 22, 2026
8f3ae43
chore: push
Pigeon0v0 Feb 22, 2026
9f8d79f
feat: 来点 InitializeComponent();
LuLu-ling Feb 22, 2026
167e6cb
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 22, 2026
089cedb
chore: push
Big-Cake-jpg Feb 22, 2026
80b641f
fix form main events
ruattd Feb 22, 2026
5fce64c
fix: msgboxmarkdowm
LinQingYuu Feb 22, 2026
1239df0
fix: msgboxselect
LinQingYuu Feb 22, 2026
15bbb22
fix: 修复一些错误的签名
LuLu-ling Feb 22, 2026
b0a2170
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 22, 2026
72ac533
imp(java): 调整 Java 发行版名称 (#2458)
Pigeon0v0 Feb 22, 2026
506a546
fix: Event Funcs in PageTools
MoYuan-CN Feb 22, 2026
ea81383
fix(event): PageDownload Event Emitter
Big-Cake-jpg Feb 22, 2026
b920431
feat: NeoForge 下载适配愚人节版本 (#2463)
wyc-26 Feb 22, 2026
3de8c7c
fix: invalid comma in event func def in xaml
MoYuan-CN Feb 22, 2026
9ba253d
feat(MyListltem): 加回缺失的 tag 属性
LuLu-ling Feb 22, 2026
4556b31
fix: half way of Event Funcs in PageSetup
MoYuan-CN Feb 22, 2026
6be9f10
fix form main events
ruattd Feb 22, 2026
ec18654
Merge remote-tracking branch 'origin/dev' into dev
ruattd Feb 22, 2026
d81078d
fix: stack overflow
LinQingYuu Feb 22, 2026
6845fd1
修掉龙猫的妙妙兼容问题
ruattd Feb 22, 2026
2150e4e
fix: 修复实例设置页面切换
LuLu-ling Feb 22, 2026
c1a012f
fix(FormMain): cannot switch page
SALTWOOD Feb 22, 2026
9db4816
fix: mgstext
LinQingYuu Feb 22, 2026
72cd766
忽略自定义代理空值
ruattd Feb 22, 2026
fb08b85
fix: 修复存档信息页面切换
LuLu-ling Feb 22, 2026
a44b8d2
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 22, 2026
4933ce8
fix(PageDownloadLeft): cannot switch to default download page
SALTWOOD Feb 22, 2026
c23e185
fix: 修复联机页面的签名错误
LuLu-ling Feb 22, 2026
01bbddd
fix: 修复设置页面切换
LuLu-ling Feb 22, 2026
5cac7c4
fix: 修复下载页面切换
LuLu-ling Feb 22, 2026
a6cb073
fix(PageTools): correct method signature to fix navigation to tools page
SALTWOOD Feb 22, 2026
96d6eda
fix(PageTools): incorrect rebase caused error
SALTWOOD Feb 22, 2026
eda4066
fix: 修复百宝箱页面的签名错误
LuLu-ling Feb 22, 2026
e894475
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 22, 2026
ee54575
fix(setup): java manager page
SALTWOOD Feb 22, 2026
2b7e731
style(setup-launch): 把 VB 味的代码写成 C# 味的
Pigeon0v0 Feb 22, 2026
1af8e41
fix: 2nd half of PageSetup
MoYuan-CN Feb 22, 2026
d4c5a69
fix: check should not be set twice
MoYuan-CN Feb 22, 2026
1a936b6
fix: check should not be set twice
MoYuan-CN Feb 22, 2026
f04d823
fix: should not use comma for multi-function
MoYuan-CN Feb 22, 2026
78b444e
fix: partial fix of mismatched func sig in PageSetup
MoYuan-CN Feb 22, 2026
2c4cb9c
all in ? (event)
ruattd Feb 22, 2026
3dba657
fix(font-selector): 修复无法设置字体
LuLu-ling Feb 22, 2026
b33e0a7
fix(set-up-update): 修复几个错误的签名
LuLu-ling Feb 22, 2026
c6b748c
fix: 修复反馈页面无法打开
LuLu-ling Feb 22, 2026
bb1ca3d
fix(msg-markdown): 修复错误的签名
LuLu-ling Feb 22, 2026
ac8d78e
fix(events): add unused event handlers to xaml files
SALTWOOD Feb 22, 2026
7cb68c9
ref: binding in csharp
MoYuan-CN Feb 22, 2026
98a792a
fix(install): 无法安装 Cleanroom (#2474)
wyc-26 Feb 22, 2026
bff2afb
fix(login): `RadioCustomUuid_Checked` -> `RadioUuid_Checked`
SALTWOOD Feb 23, 2026
6c12b41
fix: incorrect signature for `Btn1_Click` and `Btn2_Click`
SALTWOOD Feb 23, 2026
0422279
fix(msg-select): 修复签名错误
LuLu-ling Feb 23, 2026
07f7105
fix(select-right): 修复错误的签名
LuLu-ling Feb 23, 2026
df8fcd6
fix(pages): add missing `InitializeComponent()`
SALTWOOD Feb 23, 2026
3a5b12a
fix(select-left): 补全被截断的 Logo
LuLu-ling Feb 23, 2026
fa11aa7
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
LuLu-ling Feb 23, 2026
2aba3fe
fix(select-right): 修复实例列表显示不正常
LuLu-ling Feb 23, 2026
fc411b5
fix(launch): unable to close CE-version hint with Enter key
SALTWOOD Feb 23, 2026
e522ff3
fix(instance-overall): 修复签名错误
LuLu-ling Feb 23, 2026
c9eb50a
fix: 资源列表显示不正常
LuLu-ling Feb 23, 2026
b6897d2
feat(log): `--console` to allocate a console
SALTWOOD Feb 23, 2026
0030e10
fix(logger): 日志可能在最后阶段写入不全 (#2472)
tangge233 Feb 23, 2026
9cd3f8a
fix(modloader): 修复整合包信息无法加载
LuLu-ling Feb 23, 2026
c192311
fix: 部分弹窗会弹两次
LuLu-ling Feb 23, 2026
7c2dc65
refactor(net): refactor method `TryBeginThread` in ModNet.cs
SALTWOOD Feb 23, 2026
7f2b938
fix(typo): `AllowMuiltThread` -> `AllowMultiThread`
SALTWOOD Feb 23, 2026
f1ccd74
fix(game-link): 修复错误的签名
LuLu-ling Feb 23, 2026
1523738
ref(binding): partial work - binding events in csharp
MoYuan-CN Feb 23, 2026
0a59d7d
Merge branch 'dev' of https://github.com/PCL-Community/PCL-CSharpE in…
MoYuan-CN Feb 23, 2026
ebeddf1
fix(lifecycle): wait for async exiting of services (#2471)
ruattd Feb 23, 2026
3e9e187
refactor(code): run code clean
SALTWOOD Feb 23, 2026
4a2ea66
fix(image): 临时图片保存地址错误 (#2479)
tangge233 Feb 23, 2026
4fb48e7
fix(pages): `PageChange` not working properly caused by dynamic conve…
SALTWOOD Feb 23, 2026
d1686a2
ref(binding): partial work - binding events in csharp
MoYuan-CN Feb 23, 2026
04b2772
fix: add default values to fix compile error in d1686a24
ruattd Feb 23, 2026
9de290b
fix: 修复数据包列表显示不正常
LuLu-ling Feb 23, 2026
ec54929
fix(comp-resource): 添加事件绑定
LuLu-ling Feb 23, 2026
e8375b7
fix(search-box): 添加事件绑定
LuLu-ling Feb 23, 2026
cd94040
fix(ModValidate): 修复 ModValidate 里的一些问题
LuLu-ling Feb 23, 2026
40df1f8
fix: 修复瞅眼服务器不显示
LuLu-ling Feb 23, 2026
6f717c4
feat(comp-favs): 移除批量下载数量限制 (#2480)
tangge233 Feb 23, 2026
1340c0d
Merge remote-tracking branch 'main/dev' into upstream
ruattd Feb 23, 2026
3f2901f
Merge upstream Visual Basic into current CSharp
ruattd Feb 23, 2026
9fc8f59
docs(readme): 更新 README 链接 (#2481)
Pigeon0v0 Feb 23, 2026
d54fb15
chore(logger): 异步释放日志流,确保日志真的完全写入了 (#2484)
tangge233 Feb 23, 2026
6d91e04
improve(config): support force new value (#2486)
ruattd Feb 23, 2026
bfeac4b
fix: 使用批量下载时不遵循设置的文件名格式 (#2473)
wyc-26 Feb 24, 2026
9a87fe8
Merge upstream #2473 & #2480
wyc-26 Feb 24, 2026
c218a97
fix(extra-text-button): 添加事件绑定
LuLu-ling Feb 24, 2026
7248fab
fix(login-auth): 修复验证服务器下拉框自动填充内容错误
LuLu-ling Feb 24, 2026
31d5c79
fix(login): run browser process asynchronously to prevent loop blocking
SALTWOOD Feb 24, 2026
bab4410
fix(net): 忽略下载任务取消时删除文件失败错误 (#2494)
tangge233 Feb 24, 2026
c03431e
refactor(config): migrate `ModBase.Setup` calls to `Config` and `States`
SALTWOOD Feb 24, 2026
f184877
chore(change-log): 调整日志构建器支持的 scope (#2488)
tangge233 Feb 24, 2026
4d9754f
feat(identity): 提供身份认证组件 (#2421)
LinQingYuu Feb 24, 2026
5d4db9e
fix(telemetry): 修复缓存导致的配置未保存问题 (#2485)
tangge233 Feb 24, 2026
ee6b2f5
refactor: use forceNewValue (#2496)
LinQingYuu Feb 24, 2026
62869ba
chore(loader): 使用 Task 代替 Thread (#2487)
tangge233 Feb 24, 2026
0965ff4
chore(bump): 2.14.3 (#2495)
tangge233 Feb 24, 2026
7ce8887
Merge branch 'PCL-Community:dev' into dev
EncVar Feb 25, 2026
ad8f0fe
fix(cs): merge
EncVar Feb 25, 2026
8a47110
ref: 主页市场
LuLu-ling Feb 25, 2026
aca1e16
fix(loader): initialize `CancelToken` field
SALTWOOD Feb 25, 2026
ce0892e
fix: ;
EncVar Feb 25, 2026
595e2ce
imp: add null check to cancel token
ruattd Feb 25, 2026
b4a1243
refactor(convert): replace Constants with string literals
SALTWOOD Feb 25, 2026
477312d
fix: UUid => Uuid
LuLu-ling Feb 25, 2026
af96b34
fix download page bugs
ruattd Feb 25, 2026
1247028
fix: StartGetInputNoType NullReferenceException
LuLu-ling Feb 25, 2026
8f0086e
fix: 内存显示重叠
LuLu-ling Feb 25, 2026
4efedcb
fix: 实例图标分配不正确
Pigeon0v0 Feb 25, 2026
469880f
fix: add initialize component invoke; fix loader type problem
ruattd Feb 25, 2026
d579db9
fix: loadertask
EncVar Feb 25, 2026
d33d7d3
fix: 修复了没🐴的巨硬是个啥比的问题
ruattd Feb 25, 2026
04e6039
fix(select-left): InitializeComponent 顺序
LuLu-ling Feb 25, 2026
71d74cc
fix(mod): Unable to cast object of type 'System.Object[]' to type 'Co…
SALTWOOD Feb 25, 2026
56bda9b
fix: UVMC 特供项缺少了一个空格
Pigeon0v0 Feb 25, 2026
d2fdcd6
fix: toolshelp problem
LuLu-ling Feb 25, 2026
262a1c4
refactor(type): remove some `dynamic` cast
SALTWOOD Feb 25, 2026
7e7ea55
refactor(type): remove even more `dynamic` cast (x2)
SALTWOOD Feb 25, 2026
c51a3cc
fix: InitializeComponent Problem
LuLu-ling Feb 25, 2026
119a65b
fix: fix comp independent downloading
ruattd Feb 25, 2026
c8030c4
fix: add missed events to extra button
ruattd Feb 25, 2026
3858740
refactor(type): remove even more `dynamic` casts (x3)
SALTWOOD Feb 25, 2026
2db0f1d
fix(main): Unable to cast object of type `System.Windows.Controls.Gri…
SALTWOOD Feb 25, 2026
7b96d73
chore(type): cast "Loader" to `LoaderCombo<string>`
SALTWOOD Feb 25, 2026
d3dc801
refactor(type): remove even more `dynamic` casts (x4)
SALTWOOD Feb 26, 2026
f030967
fix: 记住右侧内容页的子页面状态
LuLu-ling Feb 26, 2026
335ff05
refactor(convert): replace all `dynamic` casts
SALTWOOD Feb 26, 2026
978955c
refactor: refactor MyBitmap
whitecat346 Feb 27, 2026
7686a2a
revert: revert wrong style changes
whitecat346 Feb 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/reusable-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:
PCL_LOBBY_DEFAULT_SECRET: ${{ secrets.LOBBY_DEFAULT_SECRET }}
PCL_GITHUB_SHA: ${{ github.sha }}
run: |
dotnet publish "Plain Craft Launcher 2/Plain Craft Launcher 2.vbproj" \
dotnet publish "Plain Craft Launcher 2/Plain Craft Launcher 2.csproj" \
-p:Configuration=${{ inputs.configuration }} -p:Platform=${{ inputs.architecture }} \
-p:DeleteExistingFiles=true -o ./artifact --no-self-contained

Expand Down
8 changes: 4 additions & 4 deletions PCL.Core.Test/PCL.Core.Test.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<OutputType>Library</OutputType>
Expand Down Expand Up @@ -44,9 +44,9 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Microsoft.TestPlatform.AdapterUtilities" Version="18.0.1" />
<PackageReference Include="Microsoft.TestPlatform.ObjectModel" Version="18.0.1" />
<PackageReference Include="MSTest.TestAdapter" Version="4.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="4.0.2" />
<PackageReference Include="System.Text.Json" Version="10.0.2" />
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
<PackageReference Include="System.Text.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PCL.Core\PCL.Core.csproj" />
Expand Down
14 changes: 14 additions & 0 deletions PCL.Core/App/Basics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using PCL.Core.Logging;
using PCL.Core.Utils;
Expand Down Expand Up @@ -155,6 +156,19 @@ public static void OpenPath(string path, string? workingDirectory = null)
};
Process.Start(psi);
}

/// <summary>
/// 以默认程序打开 Uri
/// </summary>
/// <param name="uri">Uri 地址</param>
public static void OpenUri(string uri)
{
var psi = new ProcessStartInfo(uri)
{
UseShellExecute = true,
};
_ = Task.Run(() => Process.Start(psi));
}
#endregion

#region 应用程序操作
Expand Down
42 changes: 25 additions & 17 deletions PCL.Core/App/Configuration/ConfigItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public ConfigItem(string key, TValue defaultValue, ConfigSource source)

private ConfigValueCache<TValue> _valueCache = new();

/// <summary>
/// 指定是否启用缓存。<br/>
/// <b>NOTE</b>: 禁用缓存将造成一些功能(如自动监听内容更改)不按预期工作,请仅在真正需要的时候禁用。
/// </summary>
public bool EnableCache
{
get;
Expand All @@ -72,23 +76,24 @@ public bool EnableCache
/// 处理看起来是新的值,并返回是否真的是新的。<br/>
/// 只有启用缓存时该方法才会生效,未启用缓存将始终直接返回 <see langword="true"/>。
/// </summary>
private bool _ProcessNewCache(TValue newCache, object? argument)
private bool _ProcessNewCache(TValue newCache, object? argument, bool force = false)
{
if (!EnableCache) return true;
var existsOld = _valueCache.TryRead(out var oldCache, argument);
if (existsOld)
if (!force)
{
// 判断一下是否是新值
if (EqualityComparer<TValue>.Default.Equals(oldCache, newCache)) return false;
// 对新缓存值执行准备工作
if (newCache is INotifyPropertyChanged reactive)
reactive.PropertyChanged += (_, _) => OnContentChanged();
else if (newCache is INotifyCollectionChanged reactiveCollection)
reactiveCollection.CollectionChanged += (_, _) => OnContentChanged();
// 判断是否是新值
var existsOld = _valueCache.TryRead(out var oldCache, argument);
if (existsOld && EqualityComparer<TValue>.Default.Equals(oldCache, newCache)) return false;
}
// 对新缓存值执行准备工作
if (newCache is INotifyPropertyChanged reactive)
reactive.PropertyChanged += (_, _) => OnContentChanged();
else if (newCache is INotifyCollectionChanged reactiveCollection)
reactiveCollection.CollectionChanged += (_, _) => OnContentChanged();
// 写入缓存
_valueCache.Write(newCache, argument);
return true;
void OnContentChanged() => SetValue(newCache, argument, true);
void OnContentChanged() => SetValue(newCache, argument, bypassCache: true);
}

/// <summary>
Expand Down Expand Up @@ -127,17 +132,19 @@ public object GetValueNoType(object? argument = null)
/// </summary>
/// <param name="value">用于设置的值</param>
/// <param name="argument">上下文参数</param>
/// <param name="bypassCacheCheck">跳过缓存检查,<b>将造成一些功能不按预期工作,请仅在真正需要的时候指定该参数</b></param>
/// <param name="forceNewValue">强制将传入的值视为新值,不检查缓存,仅在 <see cref="EnableCache"/> 为 <see langword="true"/> 时生效</param>
/// <param name="bypassCache">跳过缓存检查和写入,相当于对本次操作临时将 <see cref="EnableCache"/> 设为 <see langword="false"/></param>
/// <returns>是否成功设置值,若成功则为 <c>true</c></returns>
public bool SetValue(TValue value, object? argument = null, bool bypassCacheCheck = false)
public bool SetValue(TValue value, object? argument = null, bool forceNewValue = false, bool bypassCache = false)
{
var e = _TriggerEvent(ConfigEvent.Set, argument, value, isPreview: true);
if (e != null)
{
if (e.Cancelled) return false;
if (e.NewValueReplacement != null) value = (TValue)e.NewValueReplacement;
}
if (bypassCacheCheck || _ProcessNewCache(value, argument)) _Provider.SetValue(Key, value, argument);
if (bypassCache || _ProcessNewCache(value, argument, forceNewValue))
_Provider.SetValue(Key, value, argument);
_TriggerEvent(ConfigEvent.Set, argument, value, e: e, isPreview: false);
return true;
}
Expand All @@ -157,9 +164,9 @@ public bool SetValueNoType(object value, object? argument = null)
}
}

public bool SetDefaultValue(object? argument = null)
public bool SetDefaultValue(object? argument = null, bool? forceNewValue = null)
{
return SetValue(DefaultValue, argument);
return SetValue(DefaultValue, argument, forceNewValue ?? IsDefault(argument));
}

public bool Reset(object? argument = null)
Expand Down Expand Up @@ -333,8 +340,9 @@ public event ConfigEventHandler Changed
/// 将配置项的值设置为默认值,设置后 <see cref="IsDefault"/> 将返回 <c>false</c>。
/// </summary>
/// <param name="argument">上下文参数</param>
/// <param name="forceNewValue">强制视为新值,不检查缓存,仅在 <see cref="EnableCache"/> 为 <see langword="true"/> 时生效</param>
/// <returns>是否成功设置值,若成功则为 <c>true</c></returns>
public bool SetDefaultValue(object? argument = null);
public bool SetDefaultValue(object? argument = null, bool? forceNewValue = null);

/// <summary>
/// 没有泛型的 <see cref="ConfigItem{T}.GetValue"/>。<br/>
Expand Down
21 changes: 17 additions & 4 deletions PCL.Core/App/IoC/Lifecycle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,17 @@ private static void _RemoveRunningInstance(ILifecycleService service)
removed?.MarkAsStopped();
}

private static readonly ConcurrentBag<Task> _StoppingServiceTasks = [];

private static void _WaitStoppingServiceTasks()
{
Task.WaitAll(_StoppingServiceTasks.ToArray());
}

private static void _StopService(ILifecycleService service, bool async, bool manual = false)
{
var name = _ServiceName(service, manual ? LifecycleState.Manual : CurrentState);
if (async) Task.Run(Stop);
if (async) _StoppingServiceTasks.Add(Task.Run(Stop));
else Stop().Wait();
return;

Expand Down Expand Up @@ -326,7 +333,7 @@ private static void _UpdateLastException(ILifecycleService service, Exception ex

private static void _RunCurrentExecutable(string? arguments)
{
var fileName = Process.GetCurrentProcess().MainModule!.FileName;
var fileName = Environment.ProcessPath!;
if (arguments == null) Process.Start(fileName);
else Process.Start(fileName, arguments);
}
Expand All @@ -335,10 +342,15 @@ private static void _RunCurrentExecutable(string? arguments)
private static string? _requestRestartArguments;
private static ILifecycleService? _requestRestartService;

private static readonly object _ExitLock = new();

private static void _Exit(int statusCode = 0)
{
if (HasShutdownStarted) return;
HasShutdownStarted = true;
lock (_ExitLock)
{
if (HasShutdownStarted) return;
HasShutdownStarted = true;
}
// 结束 Running 计时
if (_countRunningStart is { } start)
{
Expand All @@ -364,6 +376,7 @@ private static void _Exit(int statusCode = 0)
// 执行停止流程
_StopService(service, service.SupportAsync);
}
_WaitStoppingServiceTasks();
if (logService != null)
{
Context.Trace("退出过程已结束,正在停止日志服务");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace PCL.Core.Link;

public class Broadcast(string description, int localPort) : IDisposable
public class BroadcastLocal(string description, int localPort) : IDisposable
{
private Socket? _broadcastSocket;
private CancellationTokenSource? _cts;
Expand Down Expand Up @@ -80,6 +80,7 @@ public void Dispose()
{
Stop();
_cts?.Dispose();
_broadcastSocket.SafeClose();
GC.SuppressFinalize(this);
}
}
5 changes: 3 additions & 2 deletions PCL.Core/Link/Lobby/LobbyController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using static PCL.Core.Link.Lobby.LobbyInfoProvider;
using static PCL.Core.Link.Natayark.NatayarkProfileManager;
using LobbyType = PCL.Core.Link.Scaffolding.Client.Models.LobbyType;
using PCL.Core.Link.McPing;

namespace PCL.Core.Link.Lobby;

Expand Down Expand Up @@ -88,7 +89,7 @@ public sealed class LobbyController

var tcpPortForForward = NetworkHelper.NewTcpPort();
McForward = new TcpForward(IPAddress.Loopback, tcpPortForForward, IPAddress.Loopback, localPort);
McBroadcast = new Broadcast($"§ePCL CE 大厅{desc}", tcpPortForForward);
McBroadcast = new BroadcastLocal($"§ePCL CE 大厅{desc}", tcpPortForForward);
McForward.Start();
McBroadcast.Start();

Expand Down Expand Up @@ -159,7 +160,7 @@ public sealed class LobbyController
/// </summary>
public static async Task<bool> IsHostInstanceAvailableAsync(int port)
{
var ping = new McPing("127.0.0.1", port);
using var ping = McPingServiceFactory.CreateService("127.0.0.1", port);
var info = await ping.PingAsync().ConfigureAwait(false);

if (info != null) return true;
Expand Down
2 changes: 1 addition & 1 deletion PCL.Core/Link/Lobby/LobbyInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class LobbyInfoProvider
public static bool RequiresRealName { get; set; } = true;
public static int ProtocolVersion { get; set; } = 6;

public static Broadcast? McBroadcast { get; internal set; }
public static BroadcastLocal? McBroadcast { get; internal set; }
public static TcpForward? McForward { get; internal set; }

public class LobbyInfo
Expand Down
3 changes: 2 additions & 1 deletion PCL.Core/Link/Lobby/LobbyService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using System.Windows;
using PCL.Core.App.IoC;
using PCL.Core.UI;
using PCL.Core.Link.McPing;

namespace PCL.Core.Link.Lobby;

Expand Down Expand Up @@ -204,7 +205,7 @@ public static async Task DiscoverWorldAsync()
{
if (!recordedPorts.TryAdd(info.Address.Port)) return;

using var pinger = new McPing(new IPEndPoint(IPAddress.Loopback, info.Address.Port));
using var pinger = McPingServiceFactory.CreateService(new IPEndPoint(IPAddress.Loopback, info.Address.Port));
using var cts = new CancellationTokenSource(2000);

try
Expand Down
35 changes: 35 additions & 0 deletions PCL.Core/Link/McPing/IMcPingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using PCL.Core.Link.McPing.Model;
using System;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace PCL.Core.Link.McPing;

/// <summary>
/// Minecraft服务器探测服务接口
/// </summary>
public interface IMcPingService : IDisposable
{
/// <summary>
/// 异步探测Minecraft服务器信息
/// </summary>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>服务器探测结果,如果探测失败则返回null</returns>
Task<McPingResult?> PingAsync(CancellationToken cancellationToken = default);

/// <summary>
/// 获取服务端点信息
/// </summary>
IPEndPoint Endpoint { get; }

/// <summary>
/// 获取主机地址
/// </summary>
string Host { get; }

/// <summary>
/// 获取超时时间(毫秒)
/// </summary>
int Timeout { get; }
}
Loading