ASMDataTableV2
基本信息
| 属性 | 值 |
|---|---|
| 类 | com.mitchej123.jarjar.fml.common.discovery.ASMDataTableV2 |
| 父类 | cpw.mods.fml.common.discovery.ASMDataTable |
| Annotation desc 常量 | API_ANNOTATION = "cpw.mods.fml.common.API" |
| 修改点 | @API 数据按 apiVersion 倒序、getAnnotationsFor 缓存按 jar 分组 |
ASMDataTableV2 扩展 FML 原版 ASMDataTable,引入两项关键优化:
- API 排序:原版按发现顺序返回
@API数据;V2 按apiVersion倒序排序,让最新版本的 API 拥有者优先被依赖方识别 - 按 jar 分组:
getAnnotationsFor(ModContainer)的 O(n) 扫描改为按 jar 缓存的SetMultimap
@API 排序
@Override
public Set<ASMData> getAll(String annotation) {
final Set<ASMData> all = super.getAll(annotation);
if (!API_ANNOTATION.equals(annotation) || all == null || all.size() < 2) return all;
final List<ASMData> sorted = new ArrayList<>(all);
sorted.sort(Comparator.comparing(ASMDataTableV2::apiVersionOf).reversed());
return new LinkedHashSet<>(sorted);
}
private static DefaultArtifactVersion apiVersionOf(ASMData data) {
String v = null;
if (data != null && data.getAnnotationInfo() != null) {
final Object raw = data.getAnnotationInfo().get("apiVersion");
if (raw instanceof String) v = (String) raw;
}
if (v == null || v.isEmpty()) v = "0.0.0";
return new DefaultArtifactVersion(v);
}
只对 @API 注解做排序(其它注解保留原顺序以保持兼容性),返回 LinkedHashSet 维持迭代次序。
getAnnotationsFor 缓存
@Override
public SetMultimap<String, ASMData> getAnnotationsFor(ModContainer container) {
if (containerAnnotationData == null) {
final Map<File, ImmutableSetMultimap.Builder<String, ASMData>> builders = new HashMap<>();
for (Map.Entry<String, ASMData> e : globalAnnotationData.entries()) {
final ASMData data = e.getValue();
final ModCandidate cand = data.getCandidate();
if (cand == null) continue;
final File src = cand.getModContainer();
if (src == null) continue;
builders.computeIfAbsent(src, k -> ImmutableSetMultimap.builder()).put(e.getKey(), data);
}
final Map<File, ImmutableSetMultimap<String, ASMData>> bySource = new HashMap<>(builders.size());
for (Map.Entry<File, ImmutableSetMultimap.Builder<String, ASMData>> e : builders.entrySet()) {
bySource.put(e.getKey(), e.getValue().build());
}
final ImmutableMap.Builder<ModContainer, SetMultimap<String, ASMData>> out = ImmutableMap.builder();
for (ModContainer cont : containers) {
final File src = cont.getSource();
final ImmutableSetMultimap<String, ASMData> mm = src == null ? null : bySource.get(src);
out.put(cont, mm == null ? ImmutableSetMultimap.of() : mm);
}
containerAnnotationData = out.build();
}
return containerAnnotationData.get(container);
}
按 ModContainer.getSource() 分组 global annotation data,每个 ModContainer 只看见来自同一 jar 的注解。懒加载:第一次调用时构造 cache。
替代 globalAnnotationData
V2 构造函数替换 globalAnnotationData 类型为 LinkedHashMultimap:
public ASMDataTableV2() {
super();
this.globalAnnotationData = LinkedHashMultimap.create();
}
LinkedHashMultimap 保证插入顺序稳定,对 @API 排序前的初始集合尤为重要。
与原版差异
| 操作 | 原版 | V2 |
|---|---|---|
getAll("@API") |
保留发现顺序 | 按 apiVersion 倒序 |
getAll(其它) |
不变 | 不变 |
getAnnotationsFor(container) |
遍历整个 globalAnnotationData 过滤 | 按 jar 文件缓存 |
相关条目
- V2ConstructionReplacerTransformer - 替换
new ASMDataTable()为 V2 - API 所有权排序 - 上层排序逻辑
- ModCandidateV2 数据模型 -
getDeclaredApiPackages来源