Skip to content

Commit aa2cc7a

Browse files
committed
Update 1.2.33
1 parent eb9dc73 commit aa2cc7a

File tree

12 files changed

+129
-47
lines changed

12 files changed

+129
-47
lines changed

build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ subprojects {
2626
}
2727
maven {
2828
url 'https://repo.spongepowered.org/maven'
29+
content {
30+
includeGroup "org.spongepowered"
31+
}
32+
}
33+
maven {
34+
url 'https://cdn.fox2code.com/maven'
2935
}
3036
maven {
3137
url 'https://jitpack.io/'

common/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ dependencies {
1212
api 'org.ow2.asm:asm-commons:9.6'
1313
api 'org.semver4j:semver4j:5.2.2'
1414
api 'org.spongepowered:mixin:0.8.5'
15-
api 'com.github.LlamaLad7.MixinExtras:mixinextras-common:0.2.1'
15+
api 'io.github.llamalad7:mixinextras-common:0.3.2'
16+
api 'com.github.bawnorton.mixinsquared:mixinsquared-common:0.1.1'
1617
api 'org.luaj:luaj-jse:3.0.1'
1718

1819
// Mixin dependencies
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.fox2code.foxloader.launcher;
2+
3+
import java.net.URL;
4+
5+
/**
6+
* Used to generate new classes, only called when the class loader fails to load any class
7+
*/
8+
@FunctionalInterface
9+
public interface ClassGenerator {
10+
byte[] generate(String className);
11+
12+
default URL source(String className) { return null; }
13+
}

common/src/main/java/com/fox2code/foxloader/launcher/ClassTransformer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@
22

33
import org.objectweb.asm.Opcodes;
44

5+
/**
6+
* Used to transform classes, if a same instance also implement {@link ClassGenerator},
7+
* {@link #transform(byte[], String)} won't be called for classes the instance generate.
8+
*/
9+
@FunctionalInterface
510
public interface ClassTransformer {
11+
// Note: Opcodes is not accessible from this class
12+
// It's oki to do so there cause the value is inlined at compile time
613
int ASM_BUILD = Opcodes.ASM9;
714

815
byte[] transform(byte[] bytes,String className);

common/src/main/java/com/fox2code/foxloader/launcher/DependencyHelper.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ GSON_DEPENDENCY, new Dependency("com.google.guava:guava:21.0", MAVEN_CENTRAL, "c
3434
new Dependency("org.apache.commons:commons-lang3:3.3.2", MAVEN_CENTRAL, "org.apache.commons.lang3.tuple.Pair"),
3535
new Dependency("org.luaj:luaj-jse:3.0.1", MAVEN_CENTRAL, "org.luaj.vm2.Globals"),
3636
new Dependency("org.spongepowered:mixin:0.8.5", SPONGE_POWERED, "org.spongepowered.asm.mixin.Mixins"),
37-
new Dependency("com.github.LlamaLad7.MixinExtras:mixinextras-common:0.2.1",
38-
JITPACK, "com.llamalad7.mixinextras.MixinExtrasBootstrap",
39-
// Need fallback URL cause JitPack links can ded at any time
40-
"https://github.com/LlamaLad7/MixinExtras/releases/download/0.2.1/mixinextras-common-0.2.1.jar"),
37+
new Dependency("io.github.llamalad7:mixinextras-common:0.3.2",
38+
MAVEN_CENTRAL, "com.llamalad7.mixinextras.MixinExtrasBootstrap"),
39+
new Dependency("com.github.bawnorton.mixinsquared:mixinsquared-common:0.1.1",
40+
JITPACK, "com.bawnorton.mixinsquared.MixinSquaredBootstrap",
41+
"https://github.com/Bawnorton/MixinSquared/releases/download/0.1.1/mixinsquared-common-0.1.1.jar"),
4142
};
4243

4344
public static final Dependency sparkDependency =
@@ -242,13 +243,6 @@ static boolean supported() {
242243
}
243244

244245
static void addToClassPath(final File library) {
245-
if (inst == null) {
246-
System.err.println("Unable to retrieve Instrumentation API to add Paper jar to classpath. If you're " +
247-
"running paperclip without -jar then you also need to include the -javaagent:<paperclip_jar> JVM " +
248-
"command line option.");
249-
System.exit(1);
250-
return;
251-
}
252246
try {
253247
inst.appendToSystemClassLoaderSearch(new JarFile(library));
254248
} catch (final IOException e) {
@@ -314,7 +308,7 @@ private static String fixUpPath(String path) {
314308
}
315309

316310
public static boolean hasClass(String cls) {
317-
return FoxLauncher.getFoxClassLoader().isClassInClassPath(cls);
311+
return FoxLauncher.getFoxClassLoader().hasClass(cls);
318312
}
319313

320314
private static String resolvePostURL(String string) {

common/src/main/java/com/fox2code/foxloader/launcher/FoxClassLoader.java

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public final class FoxClassLoader extends URLClassLoader {
1919
private static final URL[] NO_URLs = new URL[0];
2020
private final LinkedList<String> exclusions;
2121
private final LinkedList<ClassTransformer> classTransformers;
22+
private final LinkedList<ClassGenerator> classGenerators;
2223
private final HashMap<String, byte[]> injectedClasses;
2324
private URLClassLoader gameExclusiveSource;
2425
private boolean allowLoadingGame;
@@ -33,7 +34,9 @@ public final class FoxClassLoader extends URLClassLoader {
3334
super(new URL[0], FoxClassLoader.class.getClassLoader());
3435
this.exclusions = new LinkedList<>();
3536
this.classTransformers = new LinkedList<>();
37+
this.classGenerators = new LinkedList<>();
3638
this.injectedClasses = new HashMap<>();
39+
this.classGenerators.add(this.injectedClasses::remove);
3740
// Allow to set a Minecraft URL before loader is initialized.
3841
if (earlyMinecraftURL != null) {
3942
this.setMinecraftURL(earlyMinecraftURL);
@@ -109,9 +112,16 @@ private Class<?> findClassImpl(String name, URL resource) throws ClassNotFoundEx
109112
name.replace('.', '/').concat(".class"));
110113
}
111114
URLConnection urlConnection;
115+
ClassGenerator generator = null;
112116
if (resource == null) {
113117
urlConnection = null;
114-
bytes = injectedClasses.remove(name);
118+
for (ClassGenerator classGenerator : this.classGenerators) {
119+
bytes = classGenerator.generate(name);
120+
if (bytes != null) {
121+
generator = classGenerator;
122+
break;
123+
}
124+
}
115125
if (bytes == null) {
116126
throw new ClassNotFoundException(name);
117127
}
@@ -132,6 +142,7 @@ private Class<?> findClassImpl(String name, URL resource) throws ClassNotFoundEx
132142
String tmpName = name.replace('/','.');
133143
if (wrappedExtensions != null && !isTransformExclude(tmpName)) {
134144
for (ClassTransformer classTransformer : classTransformers) {
145+
if (classTransformer == generator) continue;
135146
try {
136147
bytes = classTransformer.transform(bytes, tmpName);
137148
} catch (Throwable e) {
@@ -165,6 +176,8 @@ private Class<?> findClassImpl(String name, URL resource) throws ClassNotFoundEx
165176
URL url = null;
166177
if (urlConnection instanceof JarURLConnection) {
167178
url = ((JarURLConnection) urlConnection).getJarFileURL();
179+
} else if (generator != null) {
180+
url = generator.source(name);
168181
}
169182
if (name.equals(CLASS_TO_DUMP)) {
170183
Files.write(new File(FoxLauncher.gameDir, "class_dump.class").toPath(), bytes);
@@ -251,38 +264,52 @@ public boolean isClassInClassPath(String className) {
251264
}
252265
}
253266

267+
public boolean hasClass(String className) {
268+
return this.isClassLoaded(className) ||
269+
this.isClassInClassPath(className) ||
270+
this.injectedClasses.containsKey(className);
271+
}
272+
254273
public void addClassTransformers(ClassTransformer classTransformer) {
255274
String pkg = classTransformer.getClass().getPackage().getName();
256275
if (!isTransformExclude(pkg)) {
257-
exclusions.add(pkg);
276+
this.exclusions.add(pkg);
258277
}
259-
classTransformers.add(classTransformer);
278+
this.classTransformers.add(classTransformer);
279+
}
280+
281+
public void addClassGenerator(ClassGenerator classGenerator) {
282+
this.classGenerators.add(Objects.requireNonNull(classGenerator));
260283
}
261284

262285
public void injectRuntimeClass(String className, byte[] classData) {
263286
if (isClassLoaded(className))
264287
throw new IllegalStateException("Cannot redefine already loaded classes");
265-
injectedClasses.put(className, classData);
288+
this.injectedClasses.put(className, classData);
266289
}
267290

268291
public int getClassTransformersCount() {
269-
return classTransformers.size();
292+
return this.classTransformers.size();
293+
}
294+
295+
public int getClassGeneratorsCount() {
296+
return this.classGenerators.size();
270297
}
271298

272299
public void addTransformerExclusion(String exclusion) {
273-
exclusions.add(exclusion);
300+
this.exclusions.add(exclusion);
274301
}
275302

276303
public void addURL(URL url) {
277304
super.addURL(url);
278305
}
279306

280307
public void addCoreModURL(URL url) {
281-
if (allowLoadingGame)
308+
if (this.allowLoadingGame)
282309
throw new IllegalStateException("Minecraft jar already loaded!");
283-
if (coreMods == null)
284-
coreMods = new ArrayList<>(16);
285-
coreMods.add(url);
310+
if (this.coreMods == null)
311+
this.coreMods = new ArrayList<>(16);
312+
this.coreMods.add(url);
286313
}
287314

288315
public void setMinecraftURL(URL url) {
@@ -371,6 +398,7 @@ public void installWrappedExtensions(WrappedExtensions wrappedExtensions) {
371398
public static boolean isSpecialClassName(String cls) {
372399
// Check mixins to fix them in development environment.
373400
return cls.startsWith("com.llamalad7.mixinextras.") ||
401+
cls.startsWith("com.bawnorton.mixinsquared.") ||
374402
cls.startsWith("org.spongepowered.") ||
375403
cls.startsWith("org.objectweb.asm.");
376404
}

common/src/main/java/com/fox2code/foxloader/launcher/FoxLauncher.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ static void initForClientFromArgs(String[] args) {
9999
foxClassLoader.addTransformerExclusion("org.spongepowered.asm.");
100100
foxClassLoader.addTransformerExclusion("org.spongepowered.tools.");
101101
foxClassLoader.addTransformerExclusion("com.llamalad7.mixinextras.");
102+
foxClassLoader.addTransformerExclusion("com.bawnorton.mixinsquared.");
102103
foxClassLoader.addTransformerExclusion("com.fox2code.foxloader.loader.");
103104
installLoggerHelper(true); // Install special logger before libraries loading
104105
DependencyHelper.loadDependencies(true);
@@ -145,6 +146,7 @@ static void initForServerFromArgs(String[] args) {
145146
foxClassLoader.addTransformerExclusion("org.spongepowered.asm.");
146147
foxClassLoader.addTransformerExclusion("org.spongepowered.tools.");
147148
foxClassLoader.addTransformerExclusion("com.llamalad7.mixinextras.");
149+
foxClassLoader.addTransformerExclusion("com.bawnorton.mixinsquared.");
148150
foxClassLoader.addTransformerExclusion("com.fox2code.foxloader.loader.");
149151
installLoggerHelper(false); // Install special logger before libraries loading
150152
DependencyHelper.loadDependencies(false);

common/src/main/java/com/fox2code/foxloader/loader/ModLoaderMixin.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.fox2code.foxloader.loader;
22

3+
import com.bawnorton.mixinsquared.MixinSquaredBootstrap;
4+
import com.fox2code.foxloader.launcher.ClassGenerator;
5+
import com.fox2code.foxloader.launcher.ClassTransformer;
36
import com.fox2code.foxloader.launcher.FoxLauncher;
47
import com.fox2code.foxloader.loader.mixin.MixinBootstrapService;
58
import com.fox2code.foxloader.loader.mixin.MixinService;
@@ -37,9 +40,11 @@ static void initializeMixin(boolean client) {
3740
MixinBootstrap.getPlatform().inject();
3841
IMixinTransformer mixinTransformer = // Inject mixin transformer into class loader.
3942
(IMixinTransformer) MixinEnvironment.getCurrentEnvironment().getActiveTransformer();
40-
FoxLauncher.getFoxClassLoader().addClassTransformers((bytes, className) ->
41-
mixinTransformer.transformClassBytes(className, className, bytes));
43+
FoxLoaderMixinWrapper foxLoaderMixinWrapper = new FoxLoaderMixinWrapper(mixinTransformer);
44+
FoxLauncher.getFoxClassLoader().addClassTransformers(foxLoaderMixinWrapper);
45+
FoxLauncher.getFoxClassLoader().addClassGenerator(foxLoaderMixinWrapper);
4246
MixinExtrasBootstrap.init();
47+
MixinSquaredBootstrap.init();
4348
}
4449

4550
static boolean addMixinConfigurationSafe(String modId, String mixin) {
@@ -63,4 +68,22 @@ static boolean addMixinConfigurationSafe(String modId, String mixin, boolean exp
6368
}
6469
return false;
6570
}
71+
72+
private static final class FoxLoaderMixinWrapper implements ClassGenerator, ClassTransformer {
73+
private final IMixinTransformer mixinTransformer;
74+
75+
private FoxLoaderMixinWrapper(IMixinTransformer mixinTransformer) {
76+
this.mixinTransformer = mixinTransformer;
77+
}
78+
79+
@Override
80+
public byte[] generate(String className) {
81+
return this.mixinTransformer.transformClassBytes(className, className, null);
82+
}
83+
84+
@Override
85+
public byte[] transform(byte[] bytes, String className) {
86+
return this.mixinTransformer.transformClassBytes(className, className, bytes);
87+
}
88+
}
6689
}

common/src/main/java/com/fox2code/foxloader/loader/PreLoader.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ static void initializePrePatch(boolean client) {
203203
File sourceJar = new File(FoxLauncher.getFoxClassLoader()
204204
.getMinecraftSource().toURI().getPath());
205205
ModLoader.foxLoader.logger.info("Source jar file: " + sourceJar.getAbsolutePath());
206-
patchJar(sourceJar, jar, false);
206+
patchJar(sourceJar, jar, false, false);
207207
jarSize = String.format("%08X", jar.length());
208208
Files.write(hash.toPath(), (currentHash + jarSize).getBytes(StandardCharsets.UTF_8));
209209
ModLoader.foxLoader.logger.info("Jar patched successfully, using that!");
@@ -249,18 +249,18 @@ public static void patchReIndevForDev(File in, File out, boolean client) throws
249249
throw new IllegalStateException("Not in development environment!");
250250
loadPrePatches(client, false);
251251
registerPrePatch(new DevelopmentModeTransformer());
252-
patchJar(in, out, false);
252+
patchJar(in, out, false, true);
253253
}
254254

255255
public static void patchDevReIndevForSource(File in, File out) throws IOException {
256256
if (FoxLauncher.getFoxClassLoader() != null)
257257
throw new IllegalStateException("Not in development environment!");
258258
preTransformers.clear();
259259
registerPrePatch(new DevelopmentSourceTransformer());
260-
patchJar(in, out, true);
260+
patchJar(in, out, true, true);
261261
}
262262

263-
private static void patchJar(File in, File out, boolean ignoreFrames) throws IOException {
263+
private static void patchJar(File in, File out, boolean ignoreFrames, boolean dev) throws IOException {
264264
LinkedHashMap<String, byte[]> hashMap = new LinkedHashMap<>();
265265
hashMap.put(metaInfPath, metaInf); // Set META-INF first
266266
final byte[] empty = new byte[0];
@@ -271,17 +271,18 @@ private static void patchJar(File in, File out, boolean ignoreFrames) throws IOE
271271
ArrayList<File> sources = new ArrayList<>(coreMods);
272272
sources.add(in);
273273
for (File source : sources) {
274+
boolean forceComplete = dev && source == in;
274275
try (ZipInputStream zipInputStream = new ZipInputStream(
275276
new BufferedInputStream(Files.newInputStream(source.toPath())))) {
276277
while (null != (entry = zipInputStream.getNextEntry())) {
277-
if (FoxClassLoader.isGamePath(entry.getName()) &&
278+
if ((FoxClassLoader.isGamePath(entry.getName()) || forceComplete) &&
278279
!entry.isDirectory() && !hashMap.containsKey(entry.getName())) {
279280
baos.reset();
280281
while ((nRead = zipInputStream.read(buffer, 0, buffer.length)) != -1) {
281282
baos.write(buffer, 0, nRead);
282283
}
283-
byte[] bytes = baos.toByteArray();
284-
if (bytes.length == 0) bytes = empty;
284+
byte[] bytes = baos.size() == 0 ?
285+
empty : baos.toByteArray();
285286
hashMap.put(entry.getName(), bytes);
286287
}
287288
}

common/src/main/java/com/fox2code/foxloader/loader/transformer/RegistryTransformer.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ public class RegistryTransformer implements PreClassTransformer {
1111
private static final String GAME_REGISTRY = "com/fox2code/foxloader/registry/GameRegistry";
1212
private static final String BLOCK = "net/minecraft/src/game/block/Block";
1313
private static final String ITEM = "net/minecraft/src/game/item/Item";
14+
private static final String BITSET = "java/util/BitSet";
1415

1516
private int oldBlockcap = -1;
1617

@@ -33,8 +34,10 @@ private void patchBlock(ClassNode classNode) {
3334
if (insnNode.getOpcode() == SIPUSH) {
3435
IntInsnNode intInsnNode = (IntInsnNode) insnNode;
3536
int opcode;
37+
AbstractInsnNode next;
3638
if (intInsnNode.operand == oldBlockcap && ((opcode =
37-
intInsnNode.getNext().getOpcode()) == ANEWARRAY || opcode == NEWARRAY)) {
39+
(next = intInsnNode.getNext()).getOpcode()) == ANEWARRAY || opcode == NEWARRAY ||
40+
(opcode == INVOKESPECIAL && ((MethodInsnNode) next).owner.equals(BITSET)))) {
3841
intInsnNode.operand = MAXIMUM_BLOCK_ID;
3942
}
4043
}
@@ -50,18 +53,16 @@ private void patchItemMap(ClassNode classNode) {
5053
for (MethodNode methodNode : classNode.methods) {
5154
InsnList insnList = methodNode.instructions;
5255
for (AbstractInsnNode insnNode : insnList) {
53-
if (insnNode.getOpcode() == NEWARRAY) {
54-
IntInsnNode newArray = (IntInsnNode) insnNode;
55-
if (newArray.operand == T_INT) {
56-
insnNode = insnNode.getPrevious();
57-
if (insnNode instanceof IntInsnNode &&
58-
((IntInsnNode) insnNode).operand == oldBlockcap) {
59-
insnList.insert(newArray,
60-
new MethodInsnNode(INVOKESTATIC, GAME_REGISTRY,
61-
"getTemporaryBlockIntArray", "()[I"));
62-
insnList.remove(insnNode);
63-
insnList.remove(newArray);
64-
}
56+
if ((insnNode.getOpcode() == NEWARRAY && ((IntInsnNode) insnNode).operand == T_INT) ||
57+
(insnNode.getOpcode() == INVOKESPECIAL && ((MethodInsnNode) insnNode).owner.equals(BITSET))) {
58+
AbstractInsnNode previous = insnNode.getPrevious();
59+
if (previous instanceof IntInsnNode &&
60+
((IntInsnNode) previous).operand == oldBlockcap) {
61+
insnList.insert(insnNode,
62+
new MethodInsnNode(INVOKESTATIC, GAME_REGISTRY,
63+
"getTemporaryBlockIntArray", "()[I"));
64+
insnList.remove(previous);
65+
insnList.remove(insnNode);
6566
}
6667
}
6768
}

0 commit comments

Comments
 (0)