Skip to content

Commit 38bb6a4

Browse files
authored
Develop beta 25 (#509)
2 parents edb2692 + f4715a2 commit 38bb6a4

File tree

9 files changed

+151
-54
lines changed

9 files changed

+151
-54
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,12 @@ repositories {
7272
}
7373
}
7474
dependencies {
75-
implementation fg.deobf("dev.su5ed.sinytra:Connector:<version>")
75+
// Add Connector to the launch classpath
76+
minecraftLibrary fg.deobf("dev.su5ed.sinytra:Connector:<version>")
77+
// Add FFAPI dependency (if required)
78+
runtimeOnly fg.deobf("dev.su5ed.sinytra.fabric-api:fabric-api:<version>")
79+
// Install desired Fabric mods
80+
implementation "some.fabric:mod:<version>"
7681
}
7782
```
7883

build.gradle.kts

+6-2
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,14 @@ val fullJar: Jar by tasks.creating(Jar::class) {
145145
into("adapter_data")
146146
include("*.json")
147147
}
148-
from(modJar)
148+
// Despite not being part of jarjar metadata, the mod jar must be located in this directory
149+
// in order to be deobfuscated by FG in userdev environments
150+
into("META-INF/jarjar/") {
151+
from(modJar)
152+
}
149153
manifest {
150154
from(tasks.jar.get().manifest)
151-
attributes("Embedded-Dependencies-Mod" to modJar.archiveFile.get().asFile.name)
155+
attributes("Embedded-Dependencies-Mod" to "META-INF/jarjar/" + modJar.archiveFile.get().asFile.name)
152156
}
153157
}
154158

gradle.properties

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ org.gradle.jvmargs=-Xmx3G
44
org.gradle.daemon=true
55

66
# Versions
7-
versionConnector=1.0.0-beta.24
8-
versionAdapter=1.8.9-1.20.1-20231106.225239
9-
versionAdapterDefinition=1.8.10
7+
versionConnector=1.0.0-beta.25
8+
versionAdapter=1.8.12-1.20.1-20231112.230129
9+
versionAdapterDefinition=1.8.16
1010

1111
versionMc=1.20.1
1212
versionForge=47.1.3
1313
versionForgeAutoRenamingTool=1.0.8
14-
versionFabricLoader=2.5.1+0.14.21+1.20.1
14+
versionFabricLoader=2.5.2+0.14.21+1.20.1
1515
versionAccessWidener=2.1.0
16-
versionFabricApi=0.90.4+1.9.30+1.20.1
16+
versionFabricApi=0.90.7+1.9.32+1.20.1
1717
versionMixin=0.12.5+mixin.0.8.5
1818
versionMixinTransmog=0.4.1+1.20.1
1919

src/main/java/dev/su5ed/sinytra/connector/transformer/MixinPatchTransformer.java

+30-36
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.google.common.collect.ImmutableList;
44
import com.google.common.collect.Lists;
5-
import com.google.gson.Gson;
65
import com.google.gson.GsonBuilder;
76
import com.google.gson.JsonArray;
87
import com.google.gson.JsonElement;
@@ -77,6 +76,18 @@ public class MixinPatchTransformer implements Transformer {
7776
.targetInjectionPoint("Lnet/fabricmc/loader/impl/game/minecraft/Hooks;startServer(Ljava/io/File;Ljava/lang/Object;)V")
7877
.modifyInjectionPoint("Lnet/minecraftforge/server/loading/ServerModLoader;load()V")
7978
.build(),
79+
Patch.builder()
80+
.targetClass("net/minecraft/world/level/NaturalSpawner")
81+
.targetMethod("m_220443_")
82+
.targetInjectionPoint("Lnet/minecraft/world/level/levelgen/structure/structures/NetherFortressStructure;f_228517_:Lnet/minecraft/util/random/WeightedRandomList;")
83+
.modifyInjectionPoint("INVOKE", "Lnet/minecraft/world/level/StructureManager;m_220521_()Lnet/minecraft/core/RegistryAccess;")
84+
.build(),
85+
Patch.builder()
86+
.targetClass("net/minecraft/world/item/Item")
87+
.targetMethod("m_7203_")
88+
.targetInjectionPoint("Lnet/minecraft/world/item/Item;m_41473_()Lnet/minecraft/world/food/FoodProperties;")
89+
.modifyInjectionPoint("Lnet/minecraft/world/item/ItemStack;getFoodProperties(Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/food/FoodProperties;")
90+
.build(),
8091
Patch.builder()
8192
.targetClass("net/minecraft/world/entity/Entity")
8293
.targetMethod("m_204031_(Lnet/minecraft/tags/TagKey;D)Z")
@@ -113,13 +124,6 @@ public class MixinPatchTransformer implements Transformer {
113124
.extractMixin("net/minecraftforge/common/extensions/IForgeLivingEntity")
114125
.modifyTarget("sinkInFluid(Lnet/minecraftforge/fluids/FluidType;)V")
115126
.build(),
116-
Patch.builder()
117-
.targetClass("net/minecraft/client/renderer/entity/layers/ElytraLayer")
118-
.targetMethod("m_6494_(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/world/entity/LivingEntity;FFFFFF)V")
119-
.targetInjectionPoint("Lnet/minecraft/world/item/ItemStack;m_150930_(Lnet/minecraft/world/item/Item;)Z")
120-
.targetMixinType(Patch.MODIFY_EXPR_VAL)
121-
.modifyInjectionPoint("Lnet/minecraft/client/renderer/entity/layers/ElytraLayer;shouldRender(Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Z")
122-
.build(),
123127
Patch.builder()
124128
.targetClass("net/minecraft/world/item/BoneMealItem")
125129
.targetMethod("m_40627_")
@@ -187,11 +191,19 @@ public class MixinPatchTransformer implements Transformer {
187191
.targetInjectionPoint("Lnet/minecraft/world/level/block/FireBlock;m_221150_(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;ILnet/minecraft/util/RandomSource;I)V")
188192
.modifyInjectionPoint("Lnet/minecraft/world/level/block/FireBlock;tryCatchFire(Lnet/minecraft/world/level/Level;Lnet/minecraft/core/BlockPos;ILnet/minecraft/util/RandomSource;ILnet/minecraft/core/Direction;)V")
189193
.build(),
194+
Patch.builder()
195+
.targetClass("net/minecraft/client/gui/Gui")
196+
.targetMethod("m_280173_(Lnet/minecraft/client/gui/GuiGraphics;)V")
197+
.targetInjectionPoint("Lnet/minecraft/client/gui/Gui;m_168688_(Lnet/minecraft/client/gui/GuiGraphics;Lnet/minecraft/world/entity/player/Player;IIIIFIIIZ)V")
198+
.extractMixin("net/minecraftforge/client/gui/overlay/ForgeGui")
199+
.modifyTarget("renderHealth(IILnet/minecraft/client/gui/GuiGraphics;)V")
200+
.modifyParams(b -> b.insert(0, Type.INT_TYPE).insert(1, Type.INT_TYPE).targetType(ModifyMethodParams.TargetType.METHOD))
201+
.build(),
190202
Patch.builder()
191203
.targetClass("net/minecraft/client/gui/Gui")
192204
.targetMethod("m_280173_(Lnet/minecraft/client/gui/GuiGraphics;)V")
193205
.extractMixin("net/minecraftforge/client/gui/overlay/ForgeGui")
194-
.modifyTarget("Lnet/minecraftforge/client/gui/overlay/ForgeGui;renderArmor(Lnet/minecraft/client/gui/GuiGraphics;II)V")
206+
.modifyTarget("renderArmor(Lnet/minecraft/client/gui/GuiGraphics;II)V")
195207
.modifyParams(b -> b.insert(1, Type.INT_TYPE).insert(2, Type.INT_TYPE).targetType(ModifyMethodParams.TargetType.METHOD))
196208
.build(),
197209
Patch.builder()
@@ -440,7 +452,7 @@ public MixinPatchTransformer(LVTOffsets lvtOffsets, Set<String> mixinPackages, P
440452
.build();
441453
}
442454

443-
public void finalize(Path zipRoot, Collection<String> configs, SrgRemappingReferenceMapper.SimpleRefmap refmap) throws IOException {
455+
public void finalize(Path zipRoot, Collection<String> configs, Map<String, SrgRemappingReferenceMapper.SimpleRefmap> refmapFiles, Set<String> dirtyRefmaps) throws IOException {
444456
Map<String, MixinClassGenerator.GeneratedClass> generatedMixinClasses = this.environment.getClassGenerator().getGeneratedMixinClasses();
445457
if (!generatedMixinClasses.isEmpty()) {
446458
for (String config : configs) {
@@ -463,8 +475,14 @@ public void finalize(Path zipRoot, Collection<String> configs, SrgRemappingRefer
463475

464476
// Update refmap
465477
if (json.has("refmap")) {
466-
for (MixinClassGenerator.GeneratedClass generatedClass : mixins.values()) {
467-
moveRefmapMappings(generatedClass.originalName(), generatedClass.generatedName(), json.get("refmap").getAsString(), zipRoot, refmap);
478+
String refmapName = json.get("refmap").getAsString();
479+
if (dirtyRefmaps.contains(refmapName)) {
480+
SrgRemappingReferenceMapper.SimpleRefmap refmap = refmapFiles.get(refmapName);
481+
Path path = zipRoot.resolve(refmapName);
482+
if (Files.exists(path)) {
483+
String refmapString = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(refmap);
484+
Files.writeString(path, refmapString, StandardCharsets.UTF_8);
485+
}
468486
}
469487
}
470488
}
@@ -503,30 +521,6 @@ public void finalize(Path zipRoot, Collection<String> configs, SrgRemappingRefer
503521
}
504522
}
505523

506-
private void moveRefmapMappings(String oldClass, String newClass, String refmap, Path root, SrgRemappingReferenceMapper.SimpleRefmap oldRefmap) throws IOException {
507-
Map<String, String> mappingsEntry = oldRefmap.mappings.get(oldClass);
508-
if (mappingsEntry == null) {
509-
return;
510-
}
511-
Map<String, String> dataMappingsEntry = oldRefmap.data.get("searge").get(oldClass);
512-
if (dataMappingsEntry == null) {
513-
return;
514-
}
515-
Path path = root.resolve(refmap);
516-
if (Files.notExists(path)) {
517-
return;
518-
}
519-
try (Reader reader = Files.newBufferedReader(path)) {
520-
SrgRemappingReferenceMapper.SimpleRefmap configRefmap = new Gson().fromJson(reader, SrgRemappingReferenceMapper.SimpleRefmap.class);
521-
522-
configRefmap.mappings.put(newClass, mappingsEntry);
523-
configRefmap.data.get("searge").put(newClass, dataMappingsEntry);
524-
525-
String output = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create().toJson(configRefmap);
526-
Files.writeString(path, output, StandardCharsets.UTF_8);
527-
}
528-
}
529-
530524
private Map<String, MixinClassGenerator.GeneratedClass> getMixinsInPackage(String mixinPackage, Map<String, MixinClassGenerator.GeneratedClass> generatedMixinClasses) {
531525
Map<String, MixinClassGenerator.GeneratedClass> classes = new HashMap<>();
532526
for (Map.Entry<String, MixinClassGenerator.GeneratedClass> entry : generatedMixinClasses.entrySet()) {

src/main/java/dev/su5ed/sinytra/connector/transformer/OptimizedRenamingTransformer.java

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.su5ed.sinytra.connector.transformer;
22

3+
import dev.su5ed.sinytra.adapter.patch.util.MethodQualifier;
34
import net.minecraftforge.fart.api.ClassProvider;
45
import net.minecraftforge.fart.api.Transformer;
56
import net.minecraftforge.fart.internal.ClassProviderImpl;
@@ -28,7 +29,6 @@
2829

2930
public final class OptimizedRenamingTransformer extends RenamingTransformer {
3031
private static final String CLASS_DESC_PATTERN = "^L[a-zA-Z0-9/$_]+;$";
31-
private static final String METHOD_DESC_PATTERN = "^(?<desc>\\((?:\\[*[ZCBSIFJD]|\\[*L[a-zA-Z0-9/_$]+;)*\\)(?:[VZCBSIFJD]|\\[?L[a-zA-Z0-9/_;$]+))$";
3232

3333
public static Transformer create(ClassProvider classProvider, Consumer<String> log, IMappingFile mappingFile, Map<String, String> flatMappings) {
3434
RenamingClassProvider reverseProvider = new RenamingClassProvider(classProvider, mappingFile, mappingFile.reverse(), log);
@@ -196,14 +196,18 @@ public Object mapValue(Object value) {
196196
return 'L' + mapped + ';';
197197
}
198198
}
199-
else if (str.matches(METHOD_DESC_PATTERN)) {
200-
return mapMethodDesc(str);
199+
200+
MethodQualifier qualifier = MethodQualifier.create(str).orElse(null);
201+
if (qualifier != null && qualifier.desc() != null) {
202+
String owner = qualifier.owner() != null ? mapDesc(qualifier.owner()) : "";
203+
String name = qualifier.name() != null ? this.flatMappings.getOrDefault(qualifier.name(), qualifier.name()) : "";
204+
String desc = qualifier.desc() != null ? mapMethodDesc(qualifier.desc()) : "";
205+
return owner + name + desc;
201206
}
202-
else {
203-
String mapped = this.flatMappings.get(str);
204-
if (mapped != null) {
205-
return mapped;
206-
}
207+
208+
String mapped = this.flatMappings.get(str);
209+
if (mapped != null) {
210+
return mapped;
207211
}
208212
}
209213
return super.mapValue(value);

src/main/java/dev/su5ed/sinytra/connector/transformer/jar/JarTransformInstance.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import dev.su5ed.sinytra.connector.transformer.OptimizedRenamingTransformer;
2222
import dev.su5ed.sinytra.connector.transformer.RefmapRemapper;
2323
import dev.su5ed.sinytra.connector.transformer.SrgRemappingReferenceMapper;
24+
import dev.su5ed.sinytra.connector.transformer.patch.ConnectorRefmapHolder;
2425
import net.fabricmc.loader.impl.FabricLoaderImpl;
2526
import net.fabricmc.loader.impl.MappingResolverImpl;
2627
import net.minecraftforge.coremod.api.ASMAPI;
@@ -118,7 +119,8 @@ public void transformJar(File input, Path output, FabricModFileMetadata metadata
118119
AccessorRedirectTransformer accessorRedirectTransformer = new AccessorRedirectTransformer(srgToIntermediary);
119120

120121
List<Patch> extraPatches = Stream.concat(this.adapterPatches.stream(), AccessorRedirectTransformer.PATCHES.stream()).toList();
121-
PatchEnvironment environment = new PatchEnvironment(refmap.merged().mappings, this.cleanClassLookup, this.bfu.unwrap());
122+
ConnectorRefmapHolder refmapHolder = new ConnectorRefmapHolder(refmap.merged(), refmap.files());
123+
PatchEnvironment environment = new PatchEnvironment(refmapHolder, this.cleanClassLookup, this.bfu.unwrap());
122124
MixinPatchTransformer patchTransformer = new MixinPatchTransformer(this.lvtOffsetsData, metadata.mixinPackages(), environment, extraPatches);
123125
RefmapRemapper refmapRemapper = new RefmapRemapper(metadata.visibleMixinConfigs(), refmap.files());
124126
Renamer.Builder builder = Renamer.builder()
@@ -140,7 +142,7 @@ public void transformJar(File input, Path output, FabricModFileMetadata metadata
140142
renamer.run(input, output.toFile());
141143

142144
try (FileSystem zipFile = FileSystems.newFileSystem(output)) {
143-
patchTransformer.finalize(zipFile.getPath("/"), metadata.mixinConfigs(), refmap.merged());
145+
patchTransformer.finalize(zipFile.getPath("/"), metadata.mixinConfigs(), refmap.files(), refmapHolder.getDirtyRefmaps());
144146
}
145147
} catch (Throwable t) {
146148
LOGGER.error("Encountered error while transforming jar file " + input.getAbsolutePath(), t);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package dev.su5ed.sinytra.connector.transformer.patch;
2+
3+
import dev.su5ed.sinytra.adapter.patch.RefmapHolder;
4+
import dev.su5ed.sinytra.connector.transformer.SrgRemappingReferenceMapper;
5+
6+
import java.util.HashSet;
7+
import java.util.Map;
8+
import java.util.Optional;
9+
import java.util.Set;
10+
11+
public class ConnectorRefmapHolder implements RefmapHolder {
12+
private final SrgRemappingReferenceMapper.SimpleRefmap merged;
13+
private final Map<String, SrgRemappingReferenceMapper.SimpleRefmap> refmapFiles;
14+
private final Set<String> dirtyRefmaps = new HashSet<>();
15+
16+
public ConnectorRefmapHolder(SrgRemappingReferenceMapper.SimpleRefmap merged, Map<String, SrgRemappingReferenceMapper.SimpleRefmap> refmapFiles) {
17+
this.merged = merged;
18+
this.refmapFiles = refmapFiles;
19+
}
20+
21+
public Set<String> getDirtyRefmaps() {
22+
return this.dirtyRefmaps;
23+
}
24+
25+
@Override
26+
public String remap(String cls, String reference) {
27+
String cleanReference = reference.replaceAll(" ", "");
28+
return Optional.ofNullable(this.merged.mappings.get(cls))
29+
.map(map -> map.get(cleanReference))
30+
.orElse(reference);
31+
}
32+
33+
@Override
34+
public void copyEntries(String from, String to) {
35+
copyMapEntries(this.merged, from, to);
36+
this.refmapFiles.forEach((name, refmap) -> {
37+
if (copyMapEntries(refmap, from, to)) {
38+
this.dirtyRefmaps.add(name);
39+
}
40+
});
41+
}
42+
43+
private boolean copyMapEntries(SrgRemappingReferenceMapper.SimpleRefmap refmap, String from, String to) {
44+
boolean dirty = false;
45+
Map<String, String> mappingsRefs = refmap.mappings.get(from);
46+
if (mappingsRefs != null) {
47+
refmap.mappings.put(to, mappingsRefs);
48+
dirty = true;
49+
}
50+
for (Map.Entry<String, Map<String, Map<String, String>>> entry : refmap.data.entrySet()) {
51+
Map<String, Map<String, String>> map = entry.getValue();
52+
Map<String, String> dataRefs = map.get(from);
53+
if (dataRefs != null) {
54+
map.put(to, dataRefs);
55+
dirty = true;
56+
}
57+
}
58+
return dirty;
59+
}
60+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package dev.su5ed.sinytra.connector.mod.mixin;
2+
3+
import net.minecraft.server.level.ServerPlayer;
4+
import net.minecraft.server.players.PlayerList;
5+
import org.spongepowered.asm.mixin.Final;
6+
import org.spongepowered.asm.mixin.Mixin;
7+
import org.spongepowered.asm.mixin.Shadow;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
15+
@Mixin(PlayerList.class)
16+
public class PlayerListMixin {
17+
@Shadow
18+
@Final
19+
private List<ServerPlayer> players;
20+
21+
@Inject(method = "getPlayers", at = @At("HEAD"), cancellable = true)
22+
private void onGetPlayers(CallbackInfoReturnable<List<ServerPlayer>> cir) {
23+
// Ensure returned view is up-to-date
24+
// Mods may replace the value of players, invalidating the view initially created by Forge
25+
cir.setReturnValue(Collections.unmodifiableList(players));
26+
}
27+
}

src/mod/resources/connectormod.mixins.json

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"ForgeHooksMixin",
1111
"LivingEntityMixin",
1212
"PoiTypesMixin",
13+
"PlayerListMixin",
1314
"item.IForgeItemMixin",
1415
"lang.PathPackResourcesAnonMixin",
1516
"lang.PathPackResourcesMixin",

0 commit comments

Comments
 (0)