Class AbstractMappedMinecraftProvider<M extends MinecraftProvider>
- All Implemented Interfaces:
MappedMinecraftProvider,MappedMinecraftProvider.ProviderImpl
- Direct Known Subclasses:
IntermediaryMinecraftProvider,MojangMappedMinecraftProvider,NamedMinecraftProvider,SrgMinecraftProvider
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumstatic interfacestatic final recordstatic final recordstatic enumconfigureRemapper覆写在投影视角下的形态.static final recordNested classes/interfaces inherited from interface net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider
MappedMinecraftProvider.Merged, MappedMinecraftProvider.ProviderImpl, MappedMinecraftProvider.SingleJar, MappedMinecraftProvider.Split -
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionAbstractMappedMinecraftProvider(org.gradle.api.Project project, M minecraftProvider) -
Method Summary
Modifier and TypeMethodDescriptionprotected StringcacheKey()protected voidconfigureRemapper(AbstractMappedMinecraftProvider.RemappedJars remappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder tinyRemapperBuilder) static voidconfigureSplitRemapper(AbstractMappedMinecraftProvider.RemappedJars remappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder tinyRemapperBuilder) protected voidcreateBackupJars(List<MinecraftJar> minecraftJars) protected void关闭本 provider 的任务生产(见taskProduction).static PathgetBackupJarPath(MinecraftJar minecraftJar) protected StringgetJar(MinecraftJar.Type type) protected StringgetName(MinecraftJar.Type type) List<? extends AbstractMappedMinecraftProvider.OutputJar> org.gradle.api.Projectprotected @Nullable RemapMinecraftTaskRegistry.ProducerReturns 本 provider 为指定 jar 类型登记到的生产位置;未登记(不可投影或未启用任务生产)时为null.abstract MappingsNamespaceprotected StringbooleanReturns 产物是否已就绪(无需重建).供给本 provider 的产物:**生产已改由任务承担**,本方法不再在配置期写任何产物.registerRemapTask(AbstractMappedMinecraftProvider.RemappedJars remappedJars, ConfigContext configContext) 把一个AbstractMappedMinecraftProvider.RemappedJars投影成 L3 重映射任务,返回的任务引用可承载消费侧的文件依赖.protected voidremapJar(AbstractMappedMinecraftProvider.RemappedJars remappedJars, ConfigContext configContext) protected booleanprotected booleanMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface net.fabricmc.loom.configuration.providers.minecraft.mapped.MappedMinecraftProvider
getMinecraftJarPaths, getMinecraftJars
-
Field Details
-
minecraftProvider
-
extension
-
-
Constructor Details
-
AbstractMappedMinecraftProvider
-
-
Method Details
-
getTargetNamespace
-
getRemappedJars
- Returns:
- A list of jars that should be remapped
-
getOutputJars
- Returns:
- A list of output jars that this provider generates
-
getDependencyTypes
-
provide
public List<MinecraftJar> provide(AbstractMappedMinecraftProvider.ProvideContext context) throws Exception 供给本 provider 的产物:**生产已改由任务承担**,本方法不再在配置期写任何产物.本次改造把「判断是否重建 → 取跨进程锁 → 重映射 → 落位」整段交给
RemapMinecraftTask:产物有效性交给 Gradle 的 up-to-date 判定与构建缓存,并发保护交给 任务图,残骸恢复交给构建缓存。本方法只做三件事——逐 jar 注册任务(失败则整批回退,见下)、 把任务产出登记进getMinecraftJarsTaskOutputs、以及把带任务依赖的文件集合注入消费配置。不可投影时整批回退到配置期生产,且必留痕
verifyProjectable(RemappedJars)判为「无法安全投影」的形态(例如disableObfuscation的直通形态)不进入任务路径,改由produceInConfiguration(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.ProvideContext, java.util.List<net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.RemappedJars>, java.util.List<net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar>)走改造前的配置期路径。回退是**按 provider 整批**而不是按 jar 的:半批投影会留下 「一部分产物由任务生产、一部分由配置期生产」的混合状态,同一份缓存里出现两种就绪判据。 回退必定打日志(含被拒的具体原因),不是静默吞掉——静默吞掉会得到「以为切了任务、其实还在配置期写」。- Throws:
Exception
-
disableTaskProduction
protected void disableTaskProduction()关闭本 provider 的任务生产(见taskProduction).只在创建 legacy merged 的委托 provider 时调用,且必须早于
provide。 -
getRemapTask
Returns 本 provider 为指定 jar 类型登记到的生产位置;未登记(不可投影或未启用任务生产)时为null..子 provider 用它建立「本任务以该产物为输入」的任务依赖,而不是只按路径声明输入。
- Returns:
- 本 provider 为指定 jar 类型登记到的生产位置;未登记(不可投影或未启用任务生产)时为
null
-
cacheKey
-
getBackupJarPath
-
requiresBackupJars
protected boolean requiresBackupJars() -
createBackupJars
- Throws:
IOException
-
getJar
- Specified by:
getJarin interfaceMappedMinecraftProvider.ProviderImpl
-
getMavenScope
-
getMavenHelper
-
getName
-
getVersion
-
getDependencyNotation
-
isUpToDate
Returns 产物是否已就绪(无需重建)..供外部(如
minecraft-provision事务锁的无锁快路径)在锁外做只读判定; 实现即shouldRefreshOutputs(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.ProvideContext)的取反,判定产物存在且内容可复用(见下)。- Returns:
- 产物是否已就绪(无需重建)
-
shouldRefreshOutputs
-
remapJar
protected void remapJar(AbstractMappedMinecraftProvider.RemappedJars remappedJars, ConfigContext configContext) throws IOException - Throws:
IOException
-
configureRemapper
protected void configureRemapper(AbstractMappedMinecraftProvider.RemappedJars remappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder tinyRemapperBuilder) -
configureSplitRemapper
public static void configureSplitRemapper(AbstractMappedMinecraftProvider.RemappedJars remappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder tinyRemapperBuilder) -
remapperHookKind
Returns 本 provider 对configureRemapper(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.RemappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder)的覆写在投影视角下的形态..这是一个显式声明,不是探测:钩子是实例方法,它的效果(往
TinyRemapper.Builder上挂什么) 无法被序列化成任务输入,而反射只能确认「覆写了」、不能确认「覆写成什么」。因此默认值刻意保守:AbstractMappedMinecraftProvider.RemapperHookKind.UNKNOWN,即「不可假定」。不认识的覆写一律拒绝投影,而不是把它当作空实现—— 后者会得到「任务成功、产物却比配置期少了钩子改动」的静默损坏。三种形态各自意味着什么
AbstractMappedMinecraftProvider.RemapperHookKind.NO_OP:钩子什么也不挂,任务侧injectClientSidedVisitor = false就是精确复现。适用两种情形:「压根没有覆写」(基类的空实现,由overridesRemapperHook()判定,不需要声明),以及「覆写已被证明是空操作」。后者是对覆写体的一处断言,反射校验不了它, 只能靠证据支撑——把「为什么恒不挂」的证据写在声明处的注释里。AbstractMappedMinecraftProvider.RemapperHookKind.SPLIT_CLIENT_VISITOR_ONLY:钩子的效果恰好是configureSplitRemapper(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.RemappedJars, net.fabricmc.tinyremapper.TinyRemapper.Builder)——非 merged 且含客户端的 jar 挂SidedClassVisitor.CLIENT, 其余 jar 什么也不挂。任务侧已经按 jar 承载了这个效果(RemapMinecraftTask.getInjectClientSidedVisitor()), 所以声明之后本 provider 的每个 jar 都能被投影:需要 visitor 的那个 jar 由任务挂上, 不需要的那个两边都不挂。声明是对「覆写体干了什么」的断言,代码本身无法校验它,因此只有 「覆写体就是一行configureSplitRemapper(remappedJars, tinyRemapperBuilder)」这类 可以逐字核对的情形才该如此声明;覆写体的判据与configureSplitRemapper不同时 (例如按别的条件决定是否挂 visitor),即使「看起来是同一件事」也必须保持UNKNOWN:任务侧的注入条件复刻的是configureSplitRemapper的判据, 判据不同就会在某个 jar 上分叉。AbstractMappedMinecraftProvider.RemapperHookKind.UNKNOWN:无法判定,拒绝投影。第三方覆写只要不声明就落在这里。
-
registerRemapTask
public RemapMinecraftTaskRegistry.Producer registerRemapTask(AbstractMappedMinecraftProvider.RemappedJars remappedJars, ConfigContext configContext) 把一个AbstractMappedMinecraftProvider.RemappedJars投影成 L3 重映射任务,返回的任务引用可承载消费侧的文件依赖.本方法是
provide(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.ProvideContext)里「remapInputs + createBackupJars」那段的替代路径的**注册侧**: 产物有效性、并发保护、损坏恢复分别改由 Gradle 的 up-to-date 判定、任务图与构建缓存承担, 取代shouldRefreshOutputs+ 跨进程锁 +JarReusability这套手写协议。本方法只做「配置期已知量 → 任务输入」的映射,不写任何产物文件。它现在是
provide(net.fabricmc.loom.configuration.providers.minecraft.mapped.AbstractMappedMinecraftProvider.ProvideContext)的生产路径:provide对每个 jar 调用它,并把返回的任务登记进setMinecraftJarsTaskOutputs与消费配置。与 jar processor 链同批接线——后者是ProcessedNamedMinecraftProvider的输入(Named 的产出),只切一环会断链。输入映射
inputJar/outputJar/remapClasspath←AbstractMappedMinecraftProvider.RemappedJars的同名字段,fromNamespace←sourceNamespacetoNamespace←getTargetNamespace()(取toString(), 与remapJar交给 L4 的字符串一致)fixRecords/validateTargetNamespace/innerClassNames/objectHolder*← 与remapJar逐项同判据mappingsServiceOptions←MappingConfiguration.getMappingsServiceOptions(project, MappingOption.forPlatform(extension)), 与配置期getMappingsService取的是同一份映射来源(换来源会产出不等价的 jar)
为什么 annotations / signatureFixes 只能在配置期算
AnnotationsData.getRemappedAnnotations与SignatureFixerApplyVisitor.getRemappedSignatures都要一个ServiceFactory,而configContext携带的那个是配置期 作用域(由调用方 try-with-resources 持有,配置结束后关闭),执行期已不可用。要让任务自己算, 必须把这两个 service 的 Options 也收进任务输入——那是协议扩展,本次不做,因此这里如实提前计算。 代价也如实记下:原路径只在「需要重建」时才算这两个量,投影后变成注册即计算(无注解数据 / 无签名修复时是 O(1) 早退,只有映射带 extras 时才有真实开销)。产物落位:三个具体文件,目录一律不声明
产物取自remappedJars.outputJarPath(),即getJar(net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar.Type)给出的 maven 仓库位置 (getMavenScope()决定落在全局仓库还是项目级仓库,布局由LocalMavenHelper决定)。 该构件目录里属于本任务的产物有三个,本方法逐个声明为@OutputFile、由任务写出:- jar —— 重映射产物本身;
<name>-<version>.pom—— 内容与落位都由LocalMavenHelper.savePom()决定 (任务按坐标调用它,不另写一份模板)。缺它会让按坐标解析该构件的依赖直接失败;<jar>.backup—— jar 的逐字节副本,由任务用AtomicFiles原子复制得到, 位置与getBackupJarPath(net.fabricmc.loom.configuration.providers.minecraft.MinecraftJar)一致(消费者 genSources 按后者找它)。requiresBackupJars()为假的 provider 不声明该输出。
@OutputDirectory:仓库根与版本目录里还有别的 provider、 别的 MC 版本的产物,把它们纳入本任务的快照与清理范围会让并发构建互相破坏。共享路径:同一条路径只有一个生产者
AbstractMappedMinecraftProvider.MavenScope.GLOBAL下产物路径跨项目、跨工作树共享(全局仓库位于 Gradle 用户目录,同一台机器上的 所有工作树共用),同一构建内两个配置相同的子项目会算出同一条路径。这件事交给RemapMinecraftTaskRegistry:同一路径的第一次登记创建任务,后续登记只取回生产者的任务路径, 因此不存在两个任务声明同一个@OutputFile——实测 Gradle 9.5 对这种重叠既不报错也不排序, 两个任务都会写、后完成的覆盖先完成的,而一旦有消费方按该路径取产物,隐式依赖校验会直接让构建失败。 输入指纹不同的登记会被拒绝而不是共享:共享一份输入不同的产物,等于把别的配置的 jar 静默交给本项目。 指纹必须覆盖注解与签名修复(它们是产物内容的一部分),所以去重判定发生在这些量算完之后—— 代价与非共享路径相同(见上面「注册即计算」的说明),共享的那一方会白算一次,但换来的是判定精确。本方法覆盖不到的 provider 形态
这两种形态在verifyProjectable(RemappedJars)之后、更早的地方就拒绝被投影,属于本次未解决项:LegacyMergedImpl(MC 1.3 之前的合并 jar):getRemappedJars()直接抛UnsupportedOperationException,它的生产过程是「分别重映射 client/server 再合并 jar」, 并不是一次重映射,本任务无从承载;需要为「合并」单列一个任务。ProcessedNamedMinecraftProvider:落位是AbstractMappedMinecraftProvider.MavenScope.LOCAL(同名目录由 jar processor 哈希区分),且它的getRemappedJars()与getJar()都抛异常——它的产物由 jar processor 链产生,不经本任务;因此 LOCAL 范围下的跨子项目共享不在本方法职责内。
- Parameters:
remappedJars- 待重映射的一对输入/输出 jarconfigContext- 配置上下文;只用其 service factory(配置期作用域)- Returns:
- 该产物的生产位置;同一构建内同一产物路径只对应一个生产者
- Throws:
IllegalStateException- 产物路径与 maven 助手的构件路径不一致,或同一路径被以不同输入登记时
-
getProject
public org.gradle.api.Project getProject() -
getMinecraftProvider
-