Skip to content

Steam 与创意工坊 ​

本文定义 Steamworks 工坊行为。接入使用 SDK 1.65,App ID 固定为 4771560;实现和真实联调范围见实现说明(宿主文档:../implementation.md),剩余工作见开发计划(宿主文档:../roadmap.md)。本地安装与运行不依赖 Steam 可用。

生命周期与本地来源 ​

Steam 适配器负责 SDK 初始化、回调泵和退出,与组件恢复独立。Steam 不可用时不得卡住管理界面或强制退出;页面显示在线功能不可用,已有完整本地包继续运行。不能将 Steam 离线模式和客户端未运行视为同一个 SDK 状态。

当前使用 SDK 1.65 与 App ID 4771560,适配器私有线程每50ms驱动一次回调。SDK类型与句柄不进入界面或组件桥接,回调只投递纯数据结果。服务通过有界队列处理结果,查询最多48个在途请求、每个查询最多200页及10000项;不完整、超额或超时结果不用于清理。普通异步请求120秒超时;上传提交后保留文件直到SDK返回或宿主关闭,不虚报取消成功。

安装目录服务保存应用拥有的已校验副本和来源记录,运行不依赖 Steam 下载目录始终存在。首次使用仍需必要运行时,离线可运行不等于全新系统无需安装依赖。重新联网后同步订阅、下载与更新,未拿到可靠结果前保留本地状态。

本地导入遵循 包协议,复制导入而不是实时挂载目录。更新本地包同样校验、暂存、显式重载/下次启动生效。来源区别仅影响分发与清理,不改变执行权限。

浏览与订阅 ​

详情抽屉提供收藏/取消收藏、赞/踩、分享和查看作者作品。收藏与投票属于当前 Steam 账号,不改变订阅、安装或授权;进入抽屉读取真实状态,修改以异步成功结果为准,同一条目同类操作串行,失败保留已确认状态并提供重试。状态读取失败不能显示为未收藏或未投票;账号会话变化清空状态并拒绝迟到结果。收藏读取最多200页、10000项且总时限120秒,未完整读取且未找到条目时保持未知。投票只支持赞或踩及二者切换,不提供撤回投票。分享复制固定 Steam 作品链接;查看作者作品打开该作者在本应用的 Steam 工坊作品列表,作者身份无效时不可用。

工坊页分组件、布局,支持统一名称/条目ID搜索、标准标签多选、排序、分页和卡片/抽屉详情;只查询本应用的AppID。类型标签Widget、Layout与内容标签分开:内容标签不选表示全部,多选匹配任一所选标签,且必须满足内容类型;只接受标准目录的英文身份,不识别未知标签。名称查询通过Steam的独立必需标签组实现上述条件,精确条目ID结果由Services执行同样筛选;不在分页后的结果上伪造完整标签搜索。最近更新排序使用Steam的最后更新时间倒序,最新发布仍按发布时间。详情包括作者 Steam 昵称、说明、预览、来源、版本、所需能力以及订阅/安装状态。SteamID仅用于所有权与账号关联,不显示为作者名称;昵称尚未取得时显示作者占位,获取后同时刷新卡片和抽屉,拒绝过期账号会话的昵称回调。姓名请求只取昵称,适配器最多跟踪256个作者并在五分钟后失效,不请求头像。订阅后自动下载和检查更新,抽屉不提供“下载或检查更新”按钮。呈现和交互见管理界面(宿主文档:ui.md)。

两类内容均使用Community类型,保留Widget、Layout标签,组件附加标签直接取当前源码manifest中识别的tags,发布表单只显示本地化结果,不另行编辑;未知值不上传,附加标签不能改变分类。内部内容类型与开发者元数据的kind仍为widget、layout;Services在提交查询与发布时统一转换为上述Steam标签,后台可见标签使用相同大小写。开发者元数据描述kind、作品UUID、version及组件hostApiMajor/capabilities,仅为未校验的展示摘要,不授予权限;安装以下载目录的实际协议校验为准。预览按需从Steam图片服务读取,响应最多1MiB,规范化为最长边512像素的PNG,缓存最多128份;页面不执行描述HTML或远端脚本。

订阅关联、工坊布局及发布草稿保存在应用数据根的workshop/state.json,采用current-only原子记录,不随管理元数据回退。工坊布局以条目身份保存,完整内容复制到workshop/layouts/<item>/<sha256>.json,保留当前及前一份版本;进入预览时使用独立本机布局ID,不用内容中的layoutId覆盖用户布局库。用户显式另存的布局独立保留。

用户订阅后按以下阶段展示进度:订阅请求成功 → 下载或等待下载 → 完整内容就绪 → 校验 → 安装完成。订阅成功不等于可以启用;布局条目同样需下载并校验,不自动应用。

安装提交复用统一widgetId去重(宿主文档:../architecture.md#身份与数据归属)。若其他来源或其他工坊条目已安装同一组件,保留现有可用安装并报告冲突,不标记新条目安装成功,也不自动删除原安装、转移个人数据或取消订阅。

主动下载必须等待正确的异步结果,核实回调 App ID 和条目 ID,再读取下载目录;拒绝无关应用事件。中断、超时、磁盘不足、内容无效提供可重试状态,不覆盖激活版本。

更新与激活 ​

下载成功的新版复制到暂存目录并校验,完成后进入待激活状态。应用下次启动或用户主动重载时,对同一安装全部显示器实例执行一次版本切换。更新准备期间旧实例可继续运行;切换前保存可恢复配置,之后重建受影响会话。

没有新增权限的新版也不立即热替换正在运行的内容。新增能力保持未授权,不阻止新版运行;管理页列出能力变化。校验、兼容、窗口准备或激活失败恢复上一可用版本,并记录原因。权限撤销和卸载不能随版本回滚恢复。

不承诺工坊 API 提供任意历史版本;回滚只利用应用自己保留的上一可用安装。订阅同步无需保留无限版本缓存。

取消订阅与彻底清理 ​

个人数据继续按 Windows 用户共用,订阅关联按 Steam 用户保存;切换 Steam 账号前退出应用。每次启动只同步当前账号,其他账号的既有订阅关联保留。确认取消订阅先移除当前账号关联,其他账号仍关联同一条目时保留共享安装和数据;最后一个关联移除后执行下面的专属数据清理。账号未知、离线或错误账号快照不能触发清理。本机禁用不等于取消订阅,SDK 枚举显式包含 locally disabled 条目。

用户在应用点击取消订阅直接提交请求,不弹确认。Steam 返回成功,或收到校验通过的取消事件/完整权威订阅快照确认缺失后,自动执行清理;不要从搜索结果、某一页列表、下载失败、服务错误或离线状态判断取消。

订阅快照带本次同步代,和正在进行的订阅/取消请求串行归并;旧快照不得覆盖后发请求的成功结果。用户身份改变或 App ID 不匹配时不能据该列表清理当前用户的安装记录。

清理步骤必须可重复执行:

  1. 写入删除失效标记,拒绝新启动、调用、更新激活与布局应用,关闭全部显示器实例并取消任务。
  2. 撤销授权,删除资源绑定和秘密,关闭所有相关 WebView,等待浏览数据文件释放。
  3. 删除激活版本、上一版本、候选版本、暂存文件、实例配置、KV 存储、Cookie/缓存/profile、预览缓存和组件专属诊断文件。
  4. 清理旧状态代、恢复快照与内部布局中的该组件个人配置及绑定,只保留缺失依赖身份和排布;删除已失效引用不得重新出现。
  5. 所有历史状态代清除该组件数据、提交清理后新状态且文件删除完成后,才移除失效标记及清理任务。锁文件等暂时故障保留最小清理记录,运行期按后台清理规则(宿主文档:../architecture.md#持久化与提交)自动重试,下次启动仍优先处理;期间保持不可运行,不要求用户手动清理或弹提醒。

清理记录只含内部身份和待清理对象,不保留秘密。必须核实解析后的目标都属于该安装在应用数据根下的目录,拒绝跟随链接越界。删除共享状态文件时按记录过滤,不能删除其他组件数据。

不搜索或删除用户原始导入目录、用户实际文件、已打开的程序、用户主动导出的布局文件,也不擅自修改 Steam 管理目录。工坊的远程已发布条目不因本地取消订阅而被删除。这里的“所有数据”指应用管理的该组件专属数据;已发送给网络服务或已发布内容无法靠本机清理撤回。

本地组件详情提供“移除”,执行相同的应用专属数据清理,但不调用 Steam 取消订阅,也不删除导入源目录。

取消请求失败时记录失败状态,保留内容,不虚报已经取消。清理期间重新订阅先完成旧数据清理,再全新安装,授权与配置从空开始。离线下取消订阅操作显示不可用,不将本地卸载伪装为 Steam 取消成功。

取消订阅布局条目时删除应用管理的条目内容及其缓存,不自动删除其依赖组件,也不改变已应用在桌面的当前排布;之后不能再从该条目应用。用户另存的布局是独立对象。

应用内发布 ​

用户从开发页组件抽屉或保存布局的抽屉进入发布。发布是独立显式操作:校验 → 在“预览并发布”弹窗选择“发布/更新” → 填写对应配置,核对类型及清单标签 → 预览内容与分享字段 → 用户提交 → 展示上传结果。组件发布校验当前项目源码,草稿随对应组件或布局显示。

弹窗顶部使用“操作”下拉选择“发布”或“更新”。“发布”显示标题、作品说明、标签、预览图和可见范围;预览图带“预览图”标签,放在标签与可见范围之间。“更新”仅提供必填的“本人条目 ID”和可选的“更新说明”两个输入项,更新说明记录本次变更;标题、作品说明、标签、预览图及可见范围不在更新表单中显示。更新已有条目时保留其标题、作品说明和可见范围,组件文件、预览资源、清单标签及版本元数据随当前上传内容更新。组件的两种操作均展示实际上传文件清单;布局以包含组件列表和同窗的配置分享选择代替。

新发布默认公开,可明确选择其他可见范围;已有草稿保留所选范围。未填写更新条目 ID 时不能提交或保存;保存更新草稿同时保存条目 ID 和更新说明。已关联条目的草稿固定为更新,目标只读;创建结果未知时只能选择更新并找回原条目 ID,避免重复创建。草稿卡片在作品名右侧显示清洁上传副本的版本,上传成功只显示“上传成功”;仍需处理的错误、协议和创建结果未知状态保持明确。

组件发布显示预览图和实际上传文件清单。布局从布局抽屉直接进入同一个发布/更新弹窗,不再先弹出“发布布局内容”;布局弹窗不显示预览图、实际上传文件清单或原始布局JSON,改为列出包含的组件名称与UUID。可分享普通配置在同一弹窗中逐项显示名称和值并供勾选,新草稿默认不选,保存后保留选择;发布和更新使用相同的分享选择。配置候选和值在准备草稿时由服务筛选并冻结,后续只接受候选中的UUID/字段键,不接受界面传入任意配置值。保存只提交草稿,实际上传前由草稿生成并校验布局文件;失败保留可重试草稿。缺少 preview 时使用产品占位图或布局排布示意,不自动截图用户桌面。

创建条目得到 PublishedFileId 后保存发布草稿,更新同一作品时复用身份,不能因重试自动创建多个条目。上传目录为清洁副本,只含作者内容和所选元数据;组件来源记录、运行数据、绑定、日志和秘密不得进入。

检查 SDK 初始化、当前用户、条目所有权、App ID、内容类型和校验结果。确认 Steam 返回成功后才能报告上传成功;需要接受协议、审核或可见性生效时显示真实后续状态,不声称立即公开。失败保留可重试草稿,不自动更换目标或可见范围。

布局发布沿用布局协议的 UUID 依赖,不检查组件来源或要求填写工坊组件引用。布局的“安装组件齐全才应用”不改变 Steam 自己的订阅机制。

当前宿主协议 · SDK 0.1.1 · MIT