Class MinecraftPatchedProvider
- Direct Known Subclasses:
MinecraftLegacyPatchedProvider
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static interface允许抛出任意受检异常的生产回调(AtomicFiles.IOConsumer只允许IOException).static enum -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected booleanprotected final org.gradle.api.logging.Loggerprotected final MinecraftProviderprotected final org.gradle.api.Projectprotected final MinecraftPatchedProvider.Type -
Constructor Summary
ConstructorsConstructorDescriptionMinecraftPatchedProvider(org.gradle.api.Project project, MinecraftProvider minecraftProvider, MinecraftPatchedProvider.Type type) -
Method Summary
Modifier and TypeMethodDescriptionprotected voidaccessTransform(Path input, Path target) 对给定 jar 执行 Forge 的 access transform.protected voidvoidapplyLoomPatchVersion(Path target) protected boolean锁内二次确认:判定现有产物能否复用,并返回本次是否需要整链重建.protected voidcopyMissingClasses(Path source, Path target) protected voidcopyReplacing(FileSystem sourceFs, FileSystem targetFs, Path sourcePath, Path targetPath) createMcpExecutor(Path cache) static MinecraftPatchedProviderget(org.gradle.api.Project project) protected Path[]Returns 本配置下必须可复用的共享产物列表,供needsWork()判定.Returns 打补丁后的中间 Minecraft jar;产物不可复用时先按件补齐.booleanisDirty()Checks whether the provider's state is dirty (regenerating jars).protected booleanisPatchedJarUpToDate(Path jar) protected static booleanisReusableJar(Path jar) Returns 该共享产物是否可作为输入复用.protected voidprotected void确保getMinecraftPatchedIntermediateJar()指向的产物已存在.voidprovide()protected static voidpublishAtomically(Path target, MinecraftPatchedProvider.ThrowingProducer producer) 原子发布:在「临时文件 + 原子落位」保护下执行可能抛出任意受检异常的生产动作.voidremapJar(ServiceFactory serviceFactory) protected voidwalkFileSystems(Path source, Path target, Predicate<Path> filter, FsPathConsumer action) protected voidwithPatchedLock(Callable<Void> action) 在跨进程锁保护下执行 patched jar 生产.
-
Field Details
-
project
protected final org.gradle.api.Project project -
logger
protected final org.gradle.api.logging.Logger logger -
minecraftProvider
-
type
-
dirty
protected boolean dirty
-
-
Constructor Details
-
MinecraftPatchedProvider
public MinecraftPatchedProvider(org.gradle.api.Project project, MinecraftProvider minecraftProvider, MinecraftPatchedProvider.Type type)
-
-
Method Details
-
get
-
getGlobalCaches
Returns 本配置下必须可复用的共享产物列表,供needsWork()判定..列表只包含当前 jar 配置确实会生成的产物:server-only 不提供 client jar,
client-extra.jar既不生成也不进 classpath、不注册进 FORGE_EXTRA(见providesClientJar()), 把它计入判定会让needsWork()恒为真、每次构建都白取一次跨进程锁。- Returns:
- 本配置下必须可复用的共享产物列表,供
needsWork()判定
-
isReusableJar
Returns 该共享产物是否可作为输入复用..口径与理由见
JarReusability.isReusable(Path):能作为 zip 打开且至少含一个条目。 实现只有那一份,其它共享缓存链(mapped minecraft jar、mcp.zip、SrgProvider 产物等)用的是同一判定; 本方法保留,是因为 legacy 子类仍以isReusableJar的名字调用它。- Returns:
- 该共享产物是否可作为输入复用
-
checkCache
锁内二次确认:判定现有产物能否复用,并返回本次是否需要整链重建.本方法刻意不再删除共享产物。这些 jar 位于跨 daemon 共享的 forge 缓存目录: 删除会让锁外只做存在性判定的读方拿到缺失文件,也会让其它工作树误判「需要重建」而互相触发重建。 取而代之的策略是:
- 可复用的产物原样保留,缺失或损坏的产物由后续步骤按件补齐(
needsWork()同样基于可复用性判定); - 需要整链重建时由返回值表达,各步骤以「临时文件 + 原子落位」重新生成, 读方见到的要么是旧文件、要么是完整的新文件。
- Returns:
- 是否需要整链重建
- Throws:
IOException
- 可复用的产物原样保留,缺失或损坏的产物由后续步骤按件补齐(
-
provide
- Throws:
Exception
-
getOrProduceMinecraftPatchedIntermediateJar
Returns 打补丁后的中间 Minecraft jar;产物不可复用时先按件补齐..该 jar 位于跨 daemon 共享的 forge 缓存目录:其它工作树的构建(尤其是仍在删除整组产物的 旧版本 loom)可能让它在被读取前一刻消失,直接读取会以
NoSuchFileException打断整个构建。判定与补齐都基于「可复用」(存在、能作为 zip/jar 打开且至少含一个条目,见
isReusableJar(Path))而非「存在」:共享缓存里可能出现 22 字节空 zip 或截断文件, 只判存在性会把这类半成品原样交给调用方——它能以只读 jar 文件系统打开但读不出任何 class, 下游(FieldMappingsMigrator / MethodInheritanceMappingsMigrator)会把「读不出内容」当成 「没有内容」,从而把空结果写进映射缓存,形成静默错误映射。补齐走
produceIntermediateJarIfMissing():产物齐备时它是无锁快路径,不可复用时在forge-patched跨进程锁内只重建缺失件,并以原子方式落位。- Returns:
- 打补丁后的中间 Minecraft jar;产物不可复用时先按件补齐
-
produceIntermediateJarIfMissing
确保getMinecraftPatchedIntermediateJar()指向的产物已存在.默认实现调用
provide();legacy 链的产物在remapJar(ServiceFactory)阶段生成(provide()只做判定),由子类覆盖补齐。- Throws:
Exception
-
remapJar
- Throws:
Exception
-
withPatchedLock
在跨进程锁保护下执行 patched jar 生产.产物位于跨 daemon 共享的 forge 缓存目录(不按项目隔离),且
client-extra.jar在 各 Type 实例间共享同一路径;同一 MC+Forge 版本的多个并发构建会互相读写/删除同一批文件, 必须整段生产串行化。锁内判定均为幂等二次确认,等锁期间其它进程完成生产后直接复用。 -
publishAtomically
protected static void publishAtomically(Path target, MinecraftPatchedProvider.ThrowingProducer producer) throws IOException 原子发布:在「临时文件 + 原子落位」保护下执行可能抛出任意受检异常的生产动作.补丁步骤会调用外部工具(binpatcher / installer tools 等),其受检异常不限于
IOException, 无法直接作为AtomicFiles.IOConsumer;这里统一折叠为UncheckedIOException后向上抛, 以保证共享缓存里永远不会出现半截产物。- Parameters:
target- 最终落位路径(位于跨 daemon 共享的缓存目录)producer- 内容生产者,接收本次独占的临时文件路径- Throws:
IOException
-
isPatchedJarUpToDate
- Throws:
IOException
-
accessTransformForge
- Throws:
IOException
-
accessTransform
对给定 jar 执行 Forge 的 access transform.现代 Forge 走
accessTransformForge()(中间产物路径);legacy Forge 的补丁 流程在 FG2 自己的工作目录下产出 jar(client/server/merged-patched.jar),必须显式指定 输入输出,否则会写错产物,令后续的 walkFileSystems / applyLoomPatchVersion 拿到陈旧文件。- Throws:
IOException
-
patchJars
- Throws:
Exception
-
walkFileSystems
protected void walkFileSystems(Path source, Path target, Predicate<Path> filter, FsPathConsumer action) throws IOException - Throws:
IOException
-
copyMissingClasses
- Throws:
IOException
-
copyReplacing
protected void copyReplacing(FileSystem sourceFs, FileSystem targetFs, Path sourcePath, Path targetPath) throws IOException - Throws:
IOException
-
applyLoomPatchVersion
- Throws:
IOException
-
createMcpExecutor
-
getMinecraftIntermediateJar
-
getMinecraftPatchedIntermediateJar
-
getMinecraftPatchedJar
-
isDirty
public boolean isDirty()Checks whether the provider's state is dirty (regenerating jars).
-