Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@ repositories {
}

// Adds the Hytale server as a build dependency, allowing you to reference and
// compile against their code. This requires you to have Hytale installed using
// the official launcher for now.
// compile against their code. This requires you to have Hytale installed.
// Set hytale_server_jar in gradle.properties to override the default location.
dependencies {
implementation(files("$userHome/AppData/Roaming/Hytale/install/release/package/game/latest/Server/HytaleServer.jar"))
def hytaleJar = project.hasProperty('hytale_server_jar')
? project.property('hytale_server_jar')
: "$userHome/AppData/Roaming/Hytale/install/release/package/game/latest/Server/HytaleServer.jar"
implementation(files(hytaleJar))
shade "org.ow2.asm:asm:${project.asm_version}"
shade "org.ow2.asm:asm-analysis:${project.asm_version}"
shade "org.ow2.asm:asm-commons:${project.asm_version}"
Expand Down
5 changes: 4 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ version=0.0.11
description=Provides a Mixin environment for Hytale!
author=Darkhax, Jaredlll08
website=build-9.com
server_version=*
server_version=*

# Hytale installation path (override if not using default launcher location)
hytale_server_jar=D:/Roaming/install/release/package/game/latest/Server/HytaleServer.jar
4 changes: 3 additions & 1 deletion src/main/java/com/build_9/hyxin/HyxinTransformer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
public class HyxinTransformer implements ClassTransformer {

public HyxinTransformer() {

// Captures the system class loader, and the early plugin class loader.
// TODO In dev the early plugin classloader is wrong.
// This is caused by Hyxin being loaded by Gradle/Idea and not through
Expand All @@ -42,6 +41,9 @@ public HyxinTransformer() {

MixinBootstrap.init();

// Load Hyxin's built-in mixin config
Mixins.addConfiguration(Constants.BUILTIN_MIXIN_CONFIG);

// Load Mixin configs from plugin manifests.
for (Map.Entry<File, PluginManifest> entry : plugins.entries().entrySet()) {
if (entry.getValue().hasMixinConfigs()) {
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/build_9/hyxin/LaunchEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ public ClassReader getClassReader(String name) throws IOException, ClassNotFound
return new ClassReader(stream);
}
}
// Debug: Log when class can't be found
if (name.contains("Accessor") || name.contains("Mixin") || name.contains("hyxin")) {
Constants.log("[LaunchEnvironment] FAILED to find class: " + name);
Constants.log(" - runtimeLoader: " + (runtimeLoader != null ? runtimeLoader.getResource(fileName) : "null"));
Constants.log(" - earlyPluginLoader: " + (earlyPluginLoader != null ? earlyPluginLoader.getResource(fileName) : "null"));
Constants.log(" - systemLoader: " + (systemLoader != null ? systemLoader.getResource(fileName) : "null"));
}
throw new ClassNotFoundException("Could not find class '" + fileName + "'.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ private static void onMain(CallbackInfo ci) {
logger.at(Level.INFO).log("Hello from Hyxin! The server has been patched!");
logger.at(Level.INFO).log("Scanning for plugins in '" + new File("./earlyplugins").getAbsolutePath() + "'.");
}
}
}
37 changes: 32 additions & 5 deletions src/main/java/com/build_9/hyxin/mixin/BytecodeProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,37 @@ public ClassNode getClassNode(String name, boolean runTransformers) throws Class

@Override
public ClassNode getClassNode(String name, boolean runTransformers, int readerFlags) throws ClassNotFoundException, IOException {
// TODO Consider how to handle runTransformers
final ClassReader reader = LaunchEnvironment.get().getClassReader(name);
final ClassNode node = new ClassNode();
reader.accept(node, readerFlags);
return node;
// First check if this is a synthetic class
byte[] syntheticBytes = SyntheticClassRegistry.get().getSyntheticClassBytes(name);
if (syntheticBytes != null) {
final ClassReader reader = new ClassReader(syntheticBytes);
final ClassNode node = new ClassNode();
reader.accept(node, readerFlags);
return node;
}

// Otherwise, load from the class loaders
try {
final ClassReader reader = LaunchEnvironment.get().getClassReader(name);
final ClassNode node = new ClassNode();
reader.accept(node, readerFlags);
return node;
} catch (ClassNotFoundException e) {
// Try to generate the class if it's a mixin-generated synthetic
if (MixinService.transformer != null) {
byte[] generatedBytes = MixinService.transformer.generateClass(
org.spongepowered.asm.mixin.MixinEnvironment.getCurrentEnvironment(),
name
);
if (generatedBytes != null) {
SyntheticClassRegistry.get().registerSyntheticClass(name, generatedBytes);
final ClassReader reader = new ClassReader(generatedBytes);
final ClassNode node = new ClassNode();
reader.accept(node, readerFlags);
return node;
}
}
throw e;
}
}
}
22 changes: 20 additions & 2 deletions src/main/java/com/build_9/hyxin/mixin/ClassProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,34 @@ public URL[] getClassPath() {

@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
return LaunchEnvironment.get().findLoaderForClass(name).loadClass(name);
return findClassInternal(name, true);
}

@Override
public Class<?> findClass(String name, boolean initialize) throws ClassNotFoundException {
return Class.forName(name, initialize, LaunchEnvironment.get().findLoaderForClass(name));
return findClassInternal(name, initialize);
}

@Override
public Class<?> findAgentClass(String name, boolean initialize) throws ClassNotFoundException {
return this.findClass(name, initialize);
}

/**
* Internal method to find a class, checking for synthetic classes if the
* class cannot be found through normal class loading.
*/
private Class<?> findClassInternal(String name, boolean initialize) throws ClassNotFoundException {
try {
ClassLoader loader = LaunchEnvironment.get().findLoaderForClass(name);
return Class.forName(name, initialize, loader);
} catch (ClassNotFoundException e) {
// Class not found on disk - check if it's a synthetic class (accessor/invoker)
Class<?> syntheticClass = SyntheticClassRegistry.get().findSyntheticClass(name);
if (syntheticClass != null) {
return syntheticClass;
}
throw e;
}
}
}
Loading