Class MinecraftPatchedProvider
- Direct Known Subclasses:
MinecraftLegacyPatchedProvider
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final record一次最终产物生产所需的全部输入与平台开关.static interface允许抛出任意受检异常的生产回调(AtomicFiles.IOConsumer只允许IOException).static enum -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected static final Stringprotected 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 voidstatic voidapplyLoomPatchVersion(Path target) protected boolean锁内二次确认:判定现有产物能否复用,并返回本次是否需要整链重建.protected voidcopyMissingClasses(Path source, Path target) static voidcopyMissingClassesStatic(Path source, Path target) 与copyMissingClasses(Path, Path)同一处实现;静态供执行期任务复用.static voidcopyReplacing(FileSystem sourceFs, FileSystem targetFs, Path sourcePath, Path targetPath) org.gradle.api.provider.Provider<AccessTransformerService.Options> createAccessTransformerOptions(TempFiles tempFiles) Returns AT 工具的声明式选项(工具 classpath、主类与待应用的 AT 文件).Returns binpatcher 工具的声明式选项.createMcpExecutor(Path cache) Returns NeoForge installer-tools 的声明式选项(工具 classpath、主类与参数模板).org.gradle.api.provider.Provider<McpExecutor.Options> createPrePatchJarMcpOptions(TempFiles tempFiles) Returns 「跑 rename 步」的 MCP 执行器声明(配置期只接线、不执行).org.gradle.api.provider.Provider<McpExecutor.Options> createPrePatchJarMcpOptions(Path mcpCache) Returns 「跑 rename 步」的 MCP 执行器声明,工作目录由调用方给出.org.gradle.api.provider.Provider<McpExecutor.Options> createUnobfuscatedPrePatchJarMcpOptions(Path mcpCache) Returns disableObfuscation / unobfuscated 形态的 pre-patch jar 声明(排 MCP 的 merge / preProcessJar 步).static MinecraftPatchedProviderget(org.gradle.api.Project project) protected Path[]Returns 本配置下必须可复用的共享产物列表,供needsWork()判定.protected net.fabricmc.mappingio.tree.MemoryMappingTreegetMappingTree(ServiceFactory serviceFactory) Returns 本工程的映射树.@Nullable PathReturns 已重映射到 named 的 Forge jar.Returns 打补丁后的中间 Minecraft jar;产物不可复用时先按件补齐.@Nullable StringReturns pre-patch jar 的产出任务路径;未投影(配置期生产)时为null.booleanisDirty()Checks whether the provider's state is dirty (regenerating jars).protected booleanisPatchedJarUpToDate(Path jar) protected static booleanisReusableJar(Path jar) Returns 该共享产物是否可作为输入复用.protected void对给定 jar 执行 Forge 的 binary patch.static voidproduceFinalJarsForTask(MinecraftPatchedProvider.ProductionOptions options, Path patchedJarOutput, @Nullable Path clientExtraOutput, Path lockRoot, String lockKey, boolean refreshDeps, Consumer<String> lifecycle) 执行期任务的生产入口:按需把最终 patched jar 与 client-extra 原子落位到任务声明的输出路径.static voidproduceFinalJarsInto(MinecraftPatchedProvider.ProductionOptions options, Path patchedJarOutput, @Nullable Path clientExtraOutput, Consumer<String> lifecycle) 把最终 patched jar(与 client-extra)生产到**指定路径**,不触碰共享缓存路径、不取跨进程锁.protected void确保getMinecraftPatchedIntermediateJar()指向的产物已存在.static voidproducePatchedIntermediateForTask(Path prePatchJar, Path output, Path patches, ForgeExternalToolService.Options binpatcherTool, boolean fixParameterAnnotations, Consumer<String> lifecycle, Consumer<String> info) 打补丁后的中间产物的生产实现(配置期路径与执行期任务共用).productionOptions(ServiceFactory serviceFactory) Returns 本 provider 当前状态对应的生产输入与平台开关.voidprovide()protected @Nullable StringReturns 不能把三级 patched 产物的生产投影成执行期任务的原因;可以投影时为null.static voidpublishAtomically(Path target, MinecraftPatchedProvider.ThrowingProducer producer) 原子发布:在「临时文件 + 原子落位」保护下执行可能抛出任意受检异常的生产动作.voidremapJar(ServiceFactory serviceFactory) protected @Nullable StringReturns 不能把最终 patched jar 的生产投影成执行期任务的原因;可以投影时为null.static voidrunAccessTransformer(org.gradle.api.provider.Provider<AccessTransformerService.Options> options, Path input, Path target, ServiceFactory serviceFactory) 执行期求值:只认选项、本次调用的输入输出与服务工厂,不读项目模型.static voidrunBinpatcher(ForgeExternalToolService.Options tool, Path clean, Path output, Path patches, ServiceFactory serviceFactory) 执行 binpatcher:把参数模板里的{clean}/{output}/{patch}按本次调用的 路径展开后交给工具服务.static voidrunMcpExecutor(org.gradle.api.provider.Provider<McpExecutor.Options> options, Path output, ServiceFactory serviceFactory) 执行期求值:只认选项、本次落位路径与服务工厂,不读项目模型.static voidrunProduction(MinecraftPatchedProvider.ProductionOptions options, @Nullable Path patchedJarOutput, @Nullable Path clientExtraOutput, Consumer<String> lifecycle) 把最终 patched jar(与 client-extra)生产到给定路径.static voidwalkFileSystems(Path source, Path target, Predicate<Path> filter, FsPathConsumer action) protected static void在跨进程锁保护下执行 patched jar 生产.protected voidwithPatchedLock(Callable<Void> action) 在跨进程锁保护下执行 patched jar 生产.
-
Field Details
-
CURRENT_LOOM_PATCH_VERSION
- See Also:
-
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
-
provideProjectionBlocker
Returns 不能把三级 patched 产物的生产投影成执行期任务的原因;可以投影时为null..与
MinecraftProvider.projectionBlocker()同一风格:每一条都是一个「本形态的生产链不在本阶段 定义之内」或「配置期有确定的读者会按路径读这些 jar」的形态,命中即整段退回配置期路径 (那条路径与改造前逐字一致),并留下 lifecycle 留痕。- legacy Forge(1.8-1.16):
MinecraftLegacyPatchedProvider.provide()覆写了本方法, 走的是 FG2 工作目录下的一组产物,形态与 modern 不同。 - disableObfuscation / unobfuscated Forge:pre-patch jar 走
createUnobfuscatedPrePatchJar(userdev 合并分支),且remapJar也在配置期生产 最终 jar 并读 at-patched jar——两处都不在本次迁移的形态之内。 - mappings 迁移留在配置期:
ForgeMigratedMappingConfiguration.manipulateMappings在配置期生产迁移产物时,要按路径读 intermediate jar (见getOrProduceMinecraftPatchedIntermediateJar())。投影后那件产物只在执行期落位, 配置期读者会拿到不存在的文件——因此该情形整批回退。迁移本身同样任务化之后,剩下的阻碍 只有「配置期有别的读者要真读迁移产物」,判据统一放在ForgeMigratedMappingConfiguration.mappingsMigrationProjectionBlocker(net.fabricmc.loom.LoomGradleExtension)。
- Returns:
- 不能把三级 patched 产物的生产投影成执行期任务的原因;可以投影时为
null
- legacy Forge(1.8-1.16):
-
getPrePatchJarProducerTaskPath
Returns pre-patch jar 的产出任务路径;未投影(配置期生产)时为null..供「按裸路径声明该产物为输入」的消费方(
genForgePatchedSources)建任务依赖: 它注册得比provide()更早,故只能把这次查询做成惰性 provider。- Returns:
- pre-patch jar 的产出任务路径;未投影(配置期生产)时为
null
-
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()只做判定),由子类覆盖补齐。任务路径下不能走
provide():那条路径只做接线、不写产物。本方法只被**配置期读者**调用 (getOrProduceMinecraftPatchedIntermediateJar的调用方:mappings 迁移的配置期回退路径), 而那个读者与provideProjectionBlocker()用的是同一个判据——走到这里时任务路径本不该生效。 真走到这里(产物在判定之后被其它工作树删掉或写坏)时,provide()只做接线, 随后getOrProduceMinecraftPatchedIntermediateJar的可复用性复检会以明确异常报出, 而不是把不存在的路径交给迁移器去读。- Throws:
Exception
-
remapJarProjectionBlocker
Returns 不能把最终 patched jar 的生产投影成执行期任务的原因;可以投影时为null..与
MinecraftProvider.projectionBlocker()同一风格:每一条都是一个「本形态的生产链不在本阶段 定义之内」的形态,命中即整段退回配置期路径(那条路径与改造前逐字一致),并留下 lifecycle 留痕。- legacy Forge(1.8-1.16):它的产物是一组 FG2 工作目录下的 jar
(
client/server/merged-patched.jar、forge.jar),且remapJar是与父类 不同的整链实现(见MinecraftLegacyPatchedProvider.remapJar),形态与 modern 不同。
- Returns:
- 不能把最终 patched jar 的生产投影成执行期任务的原因;可以投影时为
null
- legacy Forge(1.8-1.16):它的产物是一组 FG2 工作目录下的 jar
(
-
remapJar
- Throws:
Exception
-
productionOptions
Returns 本 provider 当前状态对应的生产输入与平台开关..任务接线侧同样用它:任务声明的每一个输入都取自这里,因此两侧的输入逐项同源。 唯一例外是映射树——任务在执行期从它自己的
@Nested映射配置取(见GenerateForgePatchedJarTask), 与这里的getMappingTree(ServiceFactory)用的是同一个映射选项。- Returns:
- 本 provider 当前状态对应的生产输入与平台开关
-
runProduction
public static void runProduction(MinecraftPatchedProvider.ProductionOptions options, @Nullable Path patchedJarOutput, @Nullable Path clientExtraOutput, Consumer<String> lifecycle) throws Exception 把最终 patched jar(与 client-extra)生产到给定路径.配置期路径(
remapJar(ServiceFactory))与执行期任务 (GenerateForgePatchedJarTask)共用这一处实现,因此两条路径的产物逐字节一致—— 同一次重映射、同一批输入,不存在「两套实现各自近似」的分叉。本方法不做任何「是否需要生产」的判定,也不落位:判定由调用方负责(配置期看
dirty, 任务侧看needsFinalJarWork),落位一律由AtomicFiles的原子发布完成。静态:任务对象要能被配置缓存序列化,因此生产不能经由 provider 实例(见
MinecraftPatchedProvider.ProductionOptions)。- Parameters:
options- 生产输入与平台开关patchedJarOutput- 最终 patched jar 的落位路径;为null表示本次不产出它clientExtraOutput- client-extra 的落位路径;为null表示本次不产出它lifecycle- lifecycle 日志出口(配置期是项目 logger,执行期是任务 logger)- Throws:
Exception
-
produceFinalJarsInto
public static void produceFinalJarsInto(MinecraftPatchedProvider.ProductionOptions options, Path patchedJarOutput, @Nullable Path clientExtraOutput, Consumer<String> lifecycle) throws Exception 把最终 patched jar(与 client-extra)生产到**指定路径**,不触碰共享缓存路径、不取跨进程锁.供电线验证使用:它让「配置期实现」可以被独立调用一次作为对照,对照产物落在独立文件上, 因此被测产物的路径上只有被测任务一个写入者——不会出现「配置期先写一份、任务再覆盖」这类别名, 否则「两者一致」可以由「读到了同一份文件」伪造出来。
- Parameters:
options- 生产输入(通常取自productionOptions(ServiceFactory))patchedJarOutput- 最终 patched jar 的落位路径clientExtraOutput- client-extra 的落位路径;为null表示不产出它lifecycle- lifecycle 日志出口- Throws:
Exception
-
produceFinalJarsForTask
public static void produceFinalJarsForTask(MinecraftPatchedProvider.ProductionOptions options, Path patchedJarOutput, @Nullable Path clientExtraOutput, Path lockRoot, String lockKey, boolean refreshDeps, Consumer<String> lifecycle) throws Exception 执行期任务的生产入口:按需把最终 patched jar 与 client-extra 原子落位到任务声明的输出路径.「是否需要生产」的判据与配置期路径同源(见
needsFinalJarWork), 齐备时不写任何文件:于是任务路径与配置期路径在同一份共享缓存上「写了哪些文件」完全一致。 执行时机与跨进程并发保护分别由任务图与这里取的文件锁承担。- Parameters:
options- 生产输入与平台开关(任务从自己声明的输入构造)patchedJarOutput- 最终 patched jar 的落位路径(与配置期同一条路径)clientExtraOutput- client-extra 的落位路径;本配置不产出它时为nulllockRoot- 跨进程锁所在目录(与配置期withPatchedLock同一个目录)lockKey- 跨进程锁的 key(与配置期同一个 key)refreshDeps- 是否显式要求刷新(对应--refresh-dependencies)lifecycle- lifecycle 日志出口- Throws:
Exception
-
withPatchedLock
在跨进程锁保护下执行 patched jar 生产.产物位于跨 daemon 共享的 forge 缓存目录(不按项目隔离),且
client-extra.jar在 各 Type 实例间共享同一路径;同一 MC+Forge 版本的多个并发构建会互相读写/删除同一批文件, 必须整段生产串行化。锁内判定均为幂等二次确认,等锁期间其它进程完成生产后直接复用。 -
withLock
在跨进程锁保护下执行 patched jar 生产.产物位于跨 daemon 共享的 forge 缓存目录(不按项目隔离),且
client-extra.jar在 各 Type 实例间共享同一路径;同一 MC+Forge 版本的多个并发构建会互相读写/删除同一批文件, 必须整段生产串行化。锁内判定均为幂等二次确认,等锁期间其它进程完成生产后直接复用。静态:执行期任务同样要取这把锁,而任务不持有 provider。
-
publishAtomically
public static void publishAtomically(Path target, MinecraftPatchedProvider.ThrowingProducer producer) throws IOException 原子发布:在「临时文件 + 原子落位」保护下执行可能抛出任意受检异常的生产动作.补丁步骤会调用外部工具(binpatcher / installer tools 等),其受检异常不限于
IOException, 无法直接作为AtomicFiles.IOConsumer;这里统一折叠为UncheckedIOException后向上抛, 以保证共享缓存里永远不会出现半截产物。- Parameters:
target- 最终落位路径(位于跨 daemon 共享的缓存目录)producer- 内容生产者,接收本次独占的临时文件路径- Throws:
IOException
-
createPrePatchJarMcpOptions
public org.gradle.api.provider.Provider<McpExecutor.Options> createPrePatchJarMcpOptions(TempFiles tempFiles) throws IOException Returns 「跑 rename 步」的 MCP 执行器声明(配置期只接线、不执行)..与改造前那段内联代码的唯一区别是「不再顺带执行」:
McpExecutorBuilder.build()返回的是惰性 provider,步进逻辑选项、工具 jar 的坐标解析、以及ConstantLogic里downloadClient的 输出路径读取都推迟到它被取值时。因此本方法既能在配置期路径里调用,也能把返回值挂成任务的@Nested输入,由任务在执行期发起同一次调用。tempFiles必须活到那次调用结束:MCP 执行链的步进缓存落在它管理的临时目录里。- Returns:
- 「跑 rename 步」的 MCP 执行器声明(配置期只接线、不执行)
- Throws:
IOException
-
createPrePatchJarMcpOptions
public org.gradle.api.provider.Provider<McpExecutor.Options> createPrePatchJarMcpOptions(Path mcpCache) throws IOException Returns 「跑 rename 步」的 MCP 执行器声明,工作目录由调用方给出..与
createPrePatchJarMcpOptions(TempFiles)等价,区别只在于工作目录的来源:配置期路径用TempFiles(本次调用结束即删),执行期任务用它自己的目录(见GenerateForgePrePatchJarTask)。 两条路径的步进集合、初始配置与工具声明都取自同一处,因此不会分叉。- Parameters:
mcpCache- MCP 执行链的工作目录(由调用方负责创建与清理)- Returns:
- 「跑 rename 步」的 MCP 执行器声明,工作目录由调用方给出
- Throws:
IOException
-
createUnobfuscatedPrePatchJarMcpOptions
public org.gradle.api.provider.Provider<McpExecutor.Options> createUnobfuscatedPrePatchJarMcpOptions(Path mcpCache) throws IOException Returns disableObfuscation / unobfuscated 形态的 pre-patch jar 声明(排 MCP 的 merge / preProcessJar 步)..与
createPrePatchJarMcpOptions(Path)形状完全一致:只排队哪一步不同。 步进名字的选择与配置期createUnobfuscatedPrePatchJar逐字一致 (isNeoForge() ? "preProcessJar" : "merge"),故两条路径的 MCP 步进集合相同。- Parameters:
mcpCache- MCP 执行链的工作目录(由调用方负责创建与清理)- Returns:
- disableObfuscation / unobfuscated 形态的 pre-patch jar 声明(排 MCP 的 merge / preProcessJar 步)
- Throws:
IOException
-
runMcpExecutor
public static void runMcpExecutor(org.gradle.api.provider.Provider<McpExecutor.Options> options, Path output, ServiceFactory serviceFactory) throws IOException 执行期求值:只认选项、本次落位路径与服务工厂,不读项目模型.把 pre-patch jar 的生产搬进任务之后,执行期这一侧就是本方法;它与配置期路径 共用
McpExecutor.execute()这一处实现,因此两条路径的 MCP 步进集合、命令行与产物不会分叉。- Parameters:
options- 配置期接好的 MCP 执行器选项output- MCP 最后一步产物的落位路径(调用方负责原子落位)- Throws:
IOException
-
createNeoForgeInstallerTools
Returns NeoForge installer-tools 的声明式选项(工具 classpath、主类与参数模板)..参数模板里的取值分两类:
- 配置期就确定的纯值——
--task、输入 jar 与--neoform-data——就地定死在模板里, 于是这条链搬进任务后不需要在执行期回读项目模型; - 只有调用时才知道的路径——
{mappings}(本次下载的 client 映射)与{output}(本次调用的目标 jar)——留作占位符。
参数顺序与改造前那串
settings.args(...)逐条一致。与
createBinpatcherTool()同理,供任务侧把同一条调用搬进执行期:把返回值挂成任务的@Nested输入即可。- Returns:
- NeoForge installer-tools 的声明式选项(工具 classpath、主类与参数模板)
- 配置期就确定的纯值——
-
getMappingTree
protected net.fabricmc.mappingio.tree.MemoryMappingTree getMappingTree(ServiceFactory serviceFactory) Returns 本工程的映射树..对子类开放:legacy Forge(1.8-1.16)的 forge.jar 修补需要按 srg→named 重映射, 与这里产出
minecraftPatchedAtJar用的是同一棵映射树。- Returns:
- 本工程的映射树
-
getNamedForgeJar
Returns 已重映射到 named 的 Forge jar. 仅 legacy Forge 具备该产物.legacy 的 Forge universal jar 按 srg 名发布,
patchForge会把它重映射成 named, 落位在 Forge 缓存工作目录的forge.jar。该产物是ForgeMemberNameFixer建立「srg 名 → named 名」映射的 对照来源之一;现代 Forge 的 universal jar 本身就在 named 空间,没有这份产物。这里按路径定位而非依赖实例类型:
MergedForgeMinecraftProvider.getPatchedProvider()在部分时序下返回的是本基类而非MinecraftLegacyPatchedProvider(实测 1.12.2 即如此), 若只靠子类覆写会拿到 null。产物不存在时返回null,调用方据此跳过。- Returns:
- 已重映射到 named 的 Forge jar
-
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
-
createAccessTransformerOptions
public org.gradle.api.provider.Provider<AccessTransformerService.Options> createAccessTransformerOptions(TempFiles tempFiles) Returns AT 工具的声明式选项(工具 classpath、主类与待应用的 AT 文件)..配置期只接线、不求值:
AccessTransformerService.createOptionsForLoaderAts(org.gradle.api.Project, dev.architectury.loom.util.TempFiles)返回的是惰性 provider——依赖解析(DependencyDownloader只建 detached configuration)与「把 AT 文件从 userdev jar 里抽出来」都推迟到runAccessTransformer(org.gradle.api.provider.Provider<dev.architectury.loom.accesstransformer.AccessTransformerService.Options>, java.nio.file.Path, java.nio.file.Path, net.fabricmc.loom.util.service.ServiceFactory)真正取值的那一刻。因此本方法既能在 配置期路径里调用,也能把返回值挂成任务的@Nested输入,由任务在执行期发起同一次调用。tempFiles必须活到那次调用结束:AT 文件抽取到它管理的临时目录里。- Returns:
- AT 工具的声明式选项(工具 classpath、主类与待应用的 AT 文件)
-
runAccessTransformer
public static void runAccessTransformer(org.gradle.api.provider.Provider<AccessTransformerService.Options> options, Path input, Path target, ServiceFactory serviceFactory) throws IOException 执行期求值:只认选项、本次调用的输入输出与服务工厂,不读项目模型.与
createAccessTransformerOptions(dev.architectury.loom.util.TempFiles)配对,让配置期路径与「把provide()链搬进任务」 之后的路径共用同一份实现:AT 的实际参数仍只由AccessTransformerService.execute(java.nio.file.Path, java.nio.file.Path)构造一处, 因此两条路径跑出来的命令行不会分叉。- Parameters:
options- 配置期接好的 AT 选项input- 待执行 AT 的 jartarget- AT 结果落位路径(本方法负责原子落位:先写私有副本,再 move 到 target)- Throws:
IOException
-
producePatchedIntermediateForTask
public static void producePatchedIntermediateForTask(Path prePatchJar, Path output, Path patches, ForgeExternalToolService.Options binpatcherTool, boolean fixParameterAnnotations, Consumer<String> lifecycle, Consumer<String> info) throws Exception 打补丁后的中间产物的生产实现(配置期路径与执行期任务共用).顺序与改造前逐字一致:binpatcher 打补丁 → 补出 pre-patch jar 里存在而补丁结果里缺失的类 → 删除 vignette 参数名 → (非 official 的 Forge 系)修补参数注解。
静态:任务对象要能被配置缓存序列化,因此生产不能经由 provider 实例(见
MinecraftPatchedProvider.ProductionOptions)。output是调用方给的落位路径(配置期与任务路径都是「本次独占的临时文件」), 本方法不做原子落位——落位由调用方负责。- Parameters:
prePatchJar- pre-patch jar,即 binpatcher 的{clean}与补出缺失类的来源output- 本次落位路径patches- 补丁 jar,即 binpatcher 的{patch}binpatcherTool- binpatcher 的声明式选项fixParameterAnnotations- 是否修补参数注解lifecycle- lifecycle 日志出口(配置期是项目 logger,执行期是任务 logger)info- info 日志出口(同上)- Throws:
Exception
-
patchJars
对给定 jar 执行 Forge 的 binary patch.工具的 classpath、主类与参数模板都由
ForgeExternalToolService.Options声明: classpath 是惰性的(配置期只接线,取值推迟到真正执行时),发起调用也只依赖ServiceFactory。 因此本方法既能在配置期路径里调用,也能在把它连同调用点搬进任务之后于执行期调用—— 那条路径上不再有任何需要Project的同步求值。- Throws:
Exception
-
createBinpatcherTool
Returns binpatcher 工具的声明式选项..配置期调用:只做接线。依赖坐标与参数模板都是从 userdev 配置读来的纯值,工具 classpath 是一个 惰性的
FileCollection(DependencyDownloader只建 detached configuration, 不解析),主类由工具 jar 清单派生也是惰性的。因此这里既不解析依赖、也不发起进程。任务侧要用同一份声明时,把返回值挂成任务的
@Nested输入即可。- Returns:
- binpatcher 工具的声明式选项
-
runBinpatcher
public static void runBinpatcher(ForgeExternalToolService.Options tool, Path clean, Path output, Path patches, ServiceFactory serviceFactory) 执行 binpatcher:把参数模板里的{clean}/{output}/{patch}按本次调用的 路径展开后交给工具服务.静态:任务侧(执行期)不持有 provider,也要能用同一份实现发起这次调用,故只认选项与服务工厂。
- Parameters:
tool- binpatcher 的声明式选项(见createBinpatcherTool())clean- 待打补丁的 Minecraft jaroutput- 本次调用的目标 jarpatches- 补丁 jarserviceFactory- 服务工厂
-
walkFileSystems
public static void walkFileSystems(Path source, Path target, Predicate<Path> filter, FsPathConsumer action) throws IOException - Throws:
IOException
-
copyMissingClasses
- Throws:
IOException
-
copyMissingClassesStatic
与copyMissingClasses(Path, Path)同一处实现;静态供执行期任务复用.- Throws:
IOException
-
copyReplacing
public static void copyReplacing(FileSystem sourceFs, FileSystem targetFs, Path sourcePath, Path targetPath) throws IOException - Throws:
IOException
-
applyLoomPatchVersion
- Throws:
IOException
-
createMcpExecutor
-
getMinecraftIntermediateJar
-
getMinecraftPatchedIntermediateJar
-
getMinecraftPatchedIntermediateAtJar
-
getMinecraftPatchedJar
-
isDirty
public boolean isDirty()Checks whether the provider's state is dirty (regenerating jars).
-