Merge upstream Changes #2
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -1,8 +1,12 @@
|
|||||||
name: Build Plugin
|
name: Build Plugin
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main, develop ]
|
branches: [ main, develop ]
|
||||||
|
tags: [ 'v*' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main ]
|
branches: [ main ]
|
||||||
|
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -38,7 +38,9 @@ bin/
|
|||||||
/.nb-gradle/
|
/.nb-gradle/
|
||||||
|
|
||||||
# VS Code
|
# VS Code
|
||||||
.vscode/
|
.vscode/*
|
||||||
|
!.vscode/java-formatter.xml
|
||||||
|
!.vscode/settings.json
|
||||||
|
|
||||||
# Mac OS
|
# Mac OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -6,7 +6,7 @@ A minimal, ready-to-use template for creating Hytale plugins with modern build t
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
✅ **Modern Build System** - Gradle with Kotlin DSL
|
✅ **Modern Build System** - Gradle with Groovy DSL
|
||||||
✅ **Automated Testing** - Custom Gradle plugin for one-command server testing
|
✅ **Automated Testing** - Custom Gradle plugin for one-command server testing
|
||||||
✅ **Java 25** - Latest Java features
|
✅ **Java 25** - Latest Java features
|
||||||
✅ **ShadowJar** - Automatic dependency bundling
|
✅ **ShadowJar** - Automatic dependency bundling
|
||||||
@@ -51,9 +51,9 @@ Your plugin JAR will be in: `build/libs/TemplatePlugin-1.0.0.jar`
|
|||||||
|
|
||||||
When ready to customize, edit these files:
|
When ready to customize, edit these files:
|
||||||
|
|
||||||
**`settings.gradle.kts`:**
|
**`settings.gradle`:**
|
||||||
|
|
||||||
```kotlin
|
```groovy
|
||||||
rootProject.name = "your-plugin-name"
|
rootProject.name = "your-plugin-name"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -139,9 +139,9 @@ TemplatePlugin/
|
|||||||
│ └── resources/
|
│ └── resources/
|
||||||
│ └── manifest.json # Plugin metadata
|
│ └── manifest.json # Plugin metadata
|
||||||
├── .gitignore # Git ignore rules
|
├── .gitignore # Git ignore rules
|
||||||
├── build.gradle.kts # Build configuration
|
├── build.gradle # Build configuration
|
||||||
├── gradle.properties # Project properties
|
├── gradle.properties # Project properties
|
||||||
├── settings.gradle.kts # Project settings
|
├── settings.gradle # Project settings
|
||||||
├── LICENSE # MIT License
|
├── LICENSE # MIT License
|
||||||
└── README.md # This file
|
└── README.md # This file
|
||||||
```
|
```
|
||||||
@@ -200,9 +200,9 @@ rm -rf run/
|
|||||||
|
|
||||||
### Adding Dependencies
|
### Adding Dependencies
|
||||||
|
|
||||||
Edit `build.gradle.kts`:
|
Edit `build.gradle`:
|
||||||
|
|
||||||
```kotlin
|
```groovy
|
||||||
dependencies {
|
dependencies {
|
||||||
// Hytale API (provided by server)
|
// Hytale API (provided by server)
|
||||||
compileOnly(files("./HytaleServer.jar"))
|
compileOnly(files("./HytaleServer.jar"))
|
||||||
@@ -221,9 +221,9 @@ dependencies {
|
|||||||
|
|
||||||
**Usage:**
|
**Usage:**
|
||||||
|
|
||||||
Edit `build.gradle.kts`:
|
Edit `build.gradle`:
|
||||||
|
|
||||||
```kotlin
|
```groovy
|
||||||
runHytale {
|
runHytale {
|
||||||
jarUrl = "url to hytale server jar"
|
jarUrl = "url to hytale server jar"
|
||||||
}
|
}
|
||||||
@@ -322,7 +322,7 @@ GitHub Actions will automatically build and create a release with your plugin JA
|
|||||||
|
|
||||||
### Server Won't Start
|
### Server Won't Start
|
||||||
|
|
||||||
1. Check that `jarUrl` in `build.gradle.kts` is correct
|
1. Check that `jarUrl` in `build.gradle` is correct
|
||||||
2. Verify Java 25 is installed: `java -version`
|
2. Verify Java 25 is installed: `java -version`
|
||||||
3. Check logs in `run/logs/`
|
3. Check logs in `run/logs/`
|
||||||
|
|
||||||
|
|||||||
107
build.gradle
107
build.gradle
@@ -1,6 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.3'
|
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.3'
|
||||||
|
id 'com.gradleup.shadow' version '9.3.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
import org.gradle.internal.os.OperatingSystem
|
import org.gradle.internal.os.OperatingSystem
|
||||||
@@ -8,8 +9,9 @@ import org.gradle.internal.os.OperatingSystem
|
|||||||
ext {
|
ext {
|
||||||
if (project.hasProperty('hytale_home')) {
|
if (project.hasProperty('hytale_home')) {
|
||||||
hytaleHome = project.findProperty('hytale_home')
|
hytaleHome = project.findProperty('hytale_home')
|
||||||
}
|
} else if (System.getenv('HYTALE_HOME')) {
|
||||||
else {
|
hytaleHome = System.getenv('HYTALE_HOME')
|
||||||
|
} else {
|
||||||
def os = OperatingSystem.current()
|
def os = OperatingSystem.current()
|
||||||
if (os.isWindows()) {
|
if (os.isWindows()) {
|
||||||
hytaleHome = "${System.getProperty("user.home")}/AppData/Roaming/Hytale"
|
hytaleHome = "${System.getProperty("user.home")}/AppData/Roaming/Hytale"
|
||||||
@@ -26,11 +28,10 @@ ext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!project.hasProperty('hytaleHome')) {
|
def hytaleHomePath = ext.has('hytaleHome') ? hytaleHome : null
|
||||||
throw new GradleException('Your Hytale install could not be detected automatically. If you are on an unsupported platform or using a custom install location, please define the install location using the hytale_home property.');
|
def hasHytaleHome = (hytaleHomePath != null) && file(hytaleHomePath).exists()
|
||||||
}
|
if (!hasHytaleHome) {
|
||||||
else if (!file(project.findProperty('hytaleHome')).exists()) {
|
logger.lifecycle("Hytale install not detected; run configs that launch the server will be skipped. Set -Phytale_home=/path/to/Hytale to enable them.")
|
||||||
throw new GradleException("Failed to find Hytale at the expected location. Please make sure you have installed the game. The expected location can be changed using the hytale_home property. Currently looking in ${project.findProperty('hytaleHome')}")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -45,16 +46,27 @@ javadoc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds the Hytale server as a build dependency, allowing you to reference and
|
// 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
|
// compile against their code without bundling it. When a local install is
|
||||||
// the official launcher for now.
|
// present, we still use its jar for launching the server in IDE run configs.
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(files("$hytaleHome/install/$patchline/package/game/latest/Server/HytaleServer.jar"))
|
compileOnly("com.hypixel.hytale:Server:$hytale_build")
|
||||||
|
if (hasHytaleHome) {
|
||||||
|
runtimeOnly(files("$hytaleHome/install/$patchline/package/game/latest/Server/HytaleServer.jar"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Your dependencies here
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the working directory to run the server if it does not already exist.
|
repositories {
|
||||||
def serverRunDir = file("$projectDir/run")
|
mavenCentral()
|
||||||
if (!serverRunDir.exists()) {
|
maven {
|
||||||
serverRunDir.mkdirs()
|
name = "hytale-release"
|
||||||
|
url = uri("https://maven.hytale.com/release")
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
name = "hytale-pre-release"
|
||||||
|
url = uri("https://maven.hytale.com/pre-release")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates the manifest.json file with the latest properties defined in the
|
// Updates the manifest.json file with the latest properties defined in the
|
||||||
@@ -78,7 +90,24 @@ tasks.named('processResources') {
|
|||||||
dependsOn 'updatePluginManifest'
|
dependsOn 'updatePluginManifest'
|
||||||
}
|
}
|
||||||
|
|
||||||
def createServerRunArguments(String srcDir) {
|
tasks.named('shadowJar') {
|
||||||
|
archiveClassifier.set('')
|
||||||
|
mergeServiceFiles()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the shaded jar is produced during a normal build.
|
||||||
|
tasks.named('build') {
|
||||||
|
dependsOn 'shadowJar'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasHytaleHome) {
|
||||||
|
// Create the working directory to run the server if it does not already exist.
|
||||||
|
def serverRunDir = file("$projectDir/run")
|
||||||
|
if (!serverRunDir.exists()) {
|
||||||
|
serverRunDir.mkdirs()
|
||||||
|
}
|
||||||
|
|
||||||
|
def createServerRunArguments = { String srcDir ->
|
||||||
def programParameters = '--allow-op --disable-sentry --assets="' + "${hytaleHome}/install/$patchline/package/game/latest/Assets.zip" + '"'
|
def programParameters = '--allow-op --disable-sentry --assets="' + "${hytaleHome}/install/$patchline/package/game/latest/Assets.zip" + '"'
|
||||||
def modPaths = []
|
def modPaths = []
|
||||||
if (includes_pack.toBoolean()) {
|
if (includes_pack.toBoolean()) {
|
||||||
@@ -91,21 +120,48 @@ def createServerRunArguments(String srcDir) {
|
|||||||
programParameters += ' --mods="' + modPaths.join(',') + '"'
|
programParameters += ' --mods="' + modPaths.join(',') + '"'
|
||||||
}
|
}
|
||||||
return programParameters
|
return programParameters
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a run configuration in IDEA that will run the Hytale server with
|
def serverJar = file("$hytaleHome/install/$patchline/package/game/latest/Server/HytaleServer.jar")
|
||||||
// your plugin and the default assets.
|
def assetsZip = file("$hytaleHome/install/$patchline/package/game/latest/Assets.zip")
|
||||||
idea.project.settings.runConfigurations {
|
def shadowJarTask = tasks.named('shadowJar')
|
||||||
|
|
||||||
|
tasks.register('runServerJar', JavaExec) {
|
||||||
|
dependsOn shadowJarTask
|
||||||
|
mainClass = 'com.hypixel.hytale.Main'
|
||||||
|
classpath = files(serverJar)
|
||||||
|
workingDir = serverRunDir.absolutePath
|
||||||
|
doFirst {
|
||||||
|
def modPaths = [shadowJarTask.get().archiveFile.get().asFile.absolutePath]
|
||||||
|
if (load_user_mods.toBoolean()) {
|
||||||
|
modPaths << "${hytaleHome}/UserData/Mods"
|
||||||
|
}
|
||||||
|
setArgs([
|
||||||
|
'--allow-op',
|
||||||
|
'--disable-sentry',
|
||||||
|
"--assets=${assetsZip}",
|
||||||
|
"--mods=${modPaths.join(',')}"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register('runServer') {
|
||||||
|
dependsOn 'runServerJar'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a run configuration in IDEA that will run the Hytale server with
|
||||||
|
// your plugin and the default assets.
|
||||||
|
idea.project.settings.runConfigurations {
|
||||||
'HytaleServer'(org.jetbrains.gradle.ext.Application) {
|
'HytaleServer'(org.jetbrains.gradle.ext.Application) {
|
||||||
mainClass = 'com.hypixel.hytale.Main'
|
mainClass = 'com.hypixel.hytale.Main'
|
||||||
moduleName = project.idea.module.name + '.main'
|
moduleName = project.idea.module.name + '.main'
|
||||||
programParameters = createServerRunArguments(sourceSets.main.java.srcDirs.first().parentFile.absolutePath)
|
programParameters = createServerRunArguments(sourceSets.main.java.srcDirs.first().parentFile.absolutePath)
|
||||||
workingDirectory = serverRunDir.absolutePath
|
workingDirectory = serverRunDir.absolutePath
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a launch.json file for VSCode with the same configuration
|
// Creates a launch.json file for VSCode with the same configuration
|
||||||
tasks.register('generateVSCodeLaunch') {
|
tasks.register('generateVSCodeLaunch') {
|
||||||
def vscodeDir = file("$projectDir/.vscode")
|
def vscodeDir = file("$projectDir/.vscode")
|
||||||
def launchFile = file("$vscodeDir/launch.json")
|
def launchFile = file("$vscodeDir/launch.json")
|
||||||
doLast {
|
doLast {
|
||||||
@@ -128,4 +184,11 @@ tasks.register('generateVSCodeLaunch') {
|
|||||||
]
|
]
|
||||||
launchFile.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(launchConfig))
|
launchFile.text = groovy.json.JsonOutput.prettyPrint(groovy.json.JsonOutput.toJson(launchConfig))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tasks.register('generateVSCodeLaunch') {
|
||||||
|
doLast {
|
||||||
|
logger.lifecycle("Skipped VSCode launch configuration because hytale_home is not set or the install path is missing.")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("java-library")
|
|
||||||
id("com.gradleup.shadow") version "9.3.1"
|
|
||||||
id("run-hytale")
|
|
||||||
}
|
|
||||||
|
|
||||||
group = findProperty("pluginGroup") as String? ?: "com.example"
|
|
||||||
version = findProperty("pluginVersion") as String? ?: "1.0.0"
|
|
||||||
description = findProperty("pluginDescription") as String? ?: "A Hytale plugin template"
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenLocal()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
// Hytale Server API (provided by server at runtime)
|
|
||||||
compileOnly(files("./libs/HytaleServer.jar"))
|
|
||||||
|
|
||||||
// Common dependencies (will be bundled in JAR)
|
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
|
||||||
implementation("org.jetbrains:annotations:24.1.0")
|
|
||||||
|
|
||||||
// Test dependencies
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure server testing
|
|
||||||
runHytale {
|
|
||||||
jarUrl = "./libs/HytaleServer.jar"
|
|
||||||
assetsPath = "./libs/Assets.zip"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
// Configure Java compilation
|
|
||||||
compileJava {
|
|
||||||
options.encoding = Charsets.UTF_8.name()
|
|
||||||
options.release = 25
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure resource processing
|
|
||||||
processResources {
|
|
||||||
filteringCharset = Charsets.UTF_8.name()
|
|
||||||
|
|
||||||
// Replace placeholders in manifest.json
|
|
||||||
val props = mapOf(
|
|
||||||
"group" to project.group,
|
|
||||||
"version" to project.version,
|
|
||||||
"description" to project.description
|
|
||||||
)
|
|
||||||
inputs.properties(props)
|
|
||||||
|
|
||||||
filesMatching("manifest.json") {
|
|
||||||
expand(props)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure ShadowJar (bundle dependencies)
|
|
||||||
shadowJar {
|
|
||||||
archiveBaseName.set(rootProject.name)
|
|
||||||
archiveClassifier.set("")
|
|
||||||
|
|
||||||
// Relocate dependencies to avoid conflicts
|
|
||||||
relocate("com.google.gson", "com.yourplugin.libs.gson")
|
|
||||||
|
|
||||||
// Minimize JAR size (removes unused classes)
|
|
||||||
minimize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure tests
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make build depend on shadowJar
|
|
||||||
build {
|
|
||||||
dependsOn(shadowJar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure Java toolchain
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion.set(JavaLanguageVersion.of(25))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,11 @@ includes_pack=true
|
|||||||
# official launcher.
|
# official launcher.
|
||||||
patchline=release
|
patchline=release
|
||||||
|
|
||||||
|
# The exact Hytale build to compile against. Use the build string from the
|
||||||
|
# launcher (format YYYY.MM.DD-<hash>) so Gradle pulls the matching server jar
|
||||||
|
# for your selected patchline.
|
||||||
|
hytale_build=2026.01.27-734d39026
|
||||||
|
|
||||||
# Determines if the development server should also load mods from the user's
|
# Determines if the development server should also load mods from the user's
|
||||||
# standard mods folder. This lets you test mods by installing them where a
|
# standard mods folder. This lets you test mods by installing them where a
|
||||||
# normal player would, instead of adding them as dependencies or adding them
|
# normal player would, instead of adding them as dependencies or adding them
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Website": "example.org",
|
"Website": "example.org",
|
||||||
"ServerVersion": "*",
|
"ServerVersion": "2026.02.17-255364b8e",
|
||||||
"Dependencies": {
|
"Dependencies": {
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user