IDE: IntelliJ IDEA
Forge Version: 1.14.4 - 28.1.0
I'm able to develop and test the mod without any issue in the IDE with the runClient task. I know that I need to package the external libraries with the mod as told in the forge documentation so I use the Jar-in-Jar approach.
Placing the JAR in the mods folder, loading the world and entering the chat command to start the mod crashes the game and gives me the following error:
The game crashed whilst exception in server tick loop
Error: java.lang.NoClassDefFoundError: com/microsoft/signalr/HubConnectionBuilder
I have placed the JAR (signalr-3.0.0.jar) and Meta (signalr-3.0.0.jar.meta) files in the resources/META-INF/libraries directory.
Here are the Meta file contents:
Maven-Artifact: com.microsoft.signalr:signalr:3.0.0
Here is an excerpt from my build.gradle file where I define dependencies and manifest attributes:
dependencies {
minecraft 'net.minecraftforge:forge:1.14.4-28.1.0'
implementation 'com.microsoft.signalr:signalr:3.0.0'
}
jar {
manifest {
attributes([
"Specification-Title": "mymod",
"Specification-Vendor": "glorious",
"Specification-Version": "1",
"Implementation-Title": project.name,
"Implementation-Version": "${version}",
"Implementation-Vendor" :"glorious",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
"ContainedDeps" : "signalr-3.0.0.jar",
])
}
}
Which creates the following MANIFEST.MF (ends with empty line):
Manifest-Version: 1.0
Implementation-Title: MinecraftMod
Implementation-Version: 1.0
Specification-Vendor: glorious
Specification-Title: mymod
Implementation-Timestamp: 2019-11-05T18:29:41+0000
ContainedDeps: signalr-3.0.0.jar
Specification-Version: 1
Implementation-Vendor: glorious
I'm not sure what I could be missing here, any help is appreciated.
EDIT: Problem solved
I went back to Gradle Shadow and tried a different approach, here are my changes to build.gradle:
buildscript {
...
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.4'
}
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'com.github.johnrengelman.shadow'
...
dependencies {
minecraft 'net.minecraftforge:forge:1.14.4-28.1.0'
shadow 'com.microsoft.signalr:signalr:3.0.0'
}
shadowJar {
project.configurations.shadow.setTransitive(true);
configurations = [project.configurations.shadow]
classifier '' // Replace the default JAR
}
reobf {
shadowJar {} // Reobfuscate the shadowed JAR
}
jar {
manifest {
attributes([
"Specification-Title": "mymod",
"Specification-Vendor": "glorious",
"Specification-Version": "1",
"Implementation-Title": project.name,
"Implementation-Version": "${version}",
"Implementation-Vendor" :"glorious",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
The key here was the line: project.configurations.shadow.setTransitive(true);
Although the setTransitive() method summary says transitive is true by default it didn't seem to work without explicitly specifying.
Thanks to user Choonster for their build.gradle file from this forum post.
Thanks to user KhogaEslam for their comment on this github issue.
I hope this helps anyone having the same issue.