feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
CI / Go Backend (push) Canceled after 0s

初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
This commit is contained in:
xyou
2026-08-08 14:07:56 +08:00
parent 9500c4c80a
commit f70b061d1a
1972 changed files with 159760 additions and 6 deletions
@@ -0,0 +1,29 @@
using System.Threading.Tasks;
namespace PCL.Core.IO.Download;
/// <summary>
/// 下载连接,负责与服务器进行通信。
/// </summary>
public interface IDlConnection
{
/// <summary>
/// 开始连接,发起与服务器的通信。
/// </summary>
/// <param name="beginOffset">起始偏移,为 <c>0</c> 表示不使用分块</param>
/// <returns>连接信息</returns>
public Task<NDlConnectionInfo> StartAsync(long beginOffset);
/// <summary>
/// 停止连接,同时停止服务器通信并释放资源。
/// </summary>
/// <returns></returns>
public Task StopAsync();
/// <summary>
/// 读取指定长度的数据,若无法继续读取则返回空数组。
/// </summary>
/// <param name="length">读取长度</param>
/// <returns>字节数组形式的数据</returns>
public Task<byte[]> ReadAsync(int length);
}
@@ -0,0 +1,10 @@
namespace PCL.Core.IO.Download;
/// <summary>
/// 资源 ID 映射。
/// </summary>
/// <typeparam name="TMappingValue">映射目标类型</typeparam>
public interface IDlResourceMapping<out TMappingValue>
{
public TMappingValue? Parse(string resId);
}
@@ -0,0 +1,31 @@
using System.IO;
using System.Threading.Tasks;
namespace PCL.Core.IO.Download;
/// <summary>
/// 下载写入器。
/// </summary>
public interface IDlWriter
{
/// <summary>
/// 是否支持并行写入,即是否支持多次调用 <see cref="CreateStreamAsync"/>。
/// </summary>
public bool IsSupportParallel { get; }
/// <summary>
/// 创建写入流。
/// </summary>
/// <returns>写入流</returns>
public Task<Stream> CreateStreamAsync();
/// <summary>
/// 停止写入并释放资源。
/// </summary>
public Task StopAsync();
/// <summary>
/// 完成写入,用于执行某些并行操作的收尾工作 (例如合并文件)。
/// </summary>
public Task FinishAsync();
}
@@ -0,0 +1,15 @@
namespace PCL.Core.IO.Download;
/// <summary>
/// 下载连接信息。
/// </summary>
/// <param name="Length">内容长度,单位为字节</param>
/// <param name="BeginOffset">起始偏移</param>
/// <param name="EndOffset">结束偏移</param>
/// <param name="IsSupportSegment">是否支持分块</param>
public record NDlConnectionInfo(
long Length,
long BeginOffset,
long EndOffset,
bool IsSupportSegment
);
@@ -0,0 +1,65 @@
namespace PCL.Core.IO.Download;
/// <summary>
/// 无泛型的下载器构建工厂。
/// </summary>
public abstract class NDlFactory
{
/// <summary>
/// 新建连接。
/// </summary>
/// <param name="resId">资源 ID</param>
/// <returns>下载连接</returns>
public abstract IDlConnection? CreateConnection(string resId);
/// <summary>
/// 新建写入器。
/// </summary>
/// <param name="resId">资源 ID</param>
/// <returns>下载写入器</returns>
public abstract IDlWriter? CreateWriter(string resId);
}
/// <summary>
/// 下载器构建工厂。
/// </summary>
/// <typeparam name="TSourceArgument">下载源参数类型</typeparam>
/// <typeparam name="TTargetArgument">写入目标参数类型</typeparam>
public abstract class NDlFactory<TSourceArgument, TTargetArgument> : NDlFactory
{
/// <summary>
/// 下载源映射。
/// </summary>
protected abstract IDlResourceMapping<TSourceArgument> SourceMapping { get; }
/// <summary>
/// 写入目标映射。
/// </summary>
protected abstract IDlResourceMapping<TTargetArgument> TargetMapping { get; }
/// <summary>
/// 新建连接。
/// </summary>
/// <param name="source">下载源参数</param>
/// <returns>下载连接</returns>
protected abstract IDlConnection CreateConnection(TSourceArgument source);
public override IDlConnection? CreateConnection(string resId)
{
var source = SourceMapping.Parse(resId);
return (source is null) ? null : CreateConnection(source);
}
/// <summary>
/// 新建写入器。
/// </summary>
/// <param name="target">写入目标</param>
/// <returns>下载写入器</returns>
protected abstract IDlWriter CreateWriter(TTargetArgument target);
public override IDlWriter? CreateWriter(string resId)
{
var target = TargetMapping.Parse(resId);
return (target is null) ? null : CreateWriter(target);
}
}
@@ -0,0 +1,13 @@
namespace PCL.Core.IO.Download;
/// <summary>
/// 下载源质量报告
/// </summary>
/// <param name="MaxSegmentCount">支持最大分块数量</param>
/// <param name="RetryCount">重试计数</param>
/// <param name="AverageSpeed">总体平均速度</param>
public record NDlSourceReport(
int MaxSegmentCount = 1,
int RetryCount = 0,
long AverageSpeed = -1
);