Merge upstream Changes #2

Open
KainTim wants to merge 9 commits from realBritakee/main into main
7 changed files with 197 additions and 210 deletions

View File

@@ -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 ]
@@ -11,62 +15,62 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Java 25 - name: Setup Java 25
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
java-version: '25' java-version: '25'
distribution: 'temurin' distribution: 'temurin'
- name: Cache Gradle Dependencies - name: Cache Gradle Dependencies
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: ~/.gradle path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Grant Execute Permission for Gradlew - name: Grant Execute Permission for Gradlew
run: chmod +x gradlew run: chmod +x gradlew
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew shadowJar run: ./gradlew shadowJar
- name: Run Tests - name: Run Tests
run: ./gradlew test run: ./gradlew test
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: plugin-jar name: plugin-jar
path: build/libs/*.jar path: build/libs/*.jar
release: release:
needs: build needs: build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Setup Java 25 - name: Setup Java 25
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
java-version: '25' java-version: '25'
distribution: 'temurin' distribution: 'temurin'
- name: Grant Execute Permission for Gradlew - name: Grant Execute Permission for Gradlew
run: chmod +x gradlew run: chmod +x gradlew
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew shadowJar run: ./gradlew shadowJar
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
with: with:
files: build/libs/*.jar files: build/libs/*.jar
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4
.gitignore vendored
View File

@@ -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

View File

@@ -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/`

View File

@@ -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,54 +90,105 @@ tasks.named('processResources') {
dependsOn 'updatePluginManifest' dependsOn 'updatePluginManifest'
} }
def createServerRunArguments(String srcDir) { tasks.named('shadowJar') {
def programParameters = '--allow-op --disable-sentry --assets="' + "${hytaleHome}/install/$patchline/package/game/latest/Assets.zip" + '"' archiveClassifier.set('')
def modPaths = [] mergeServiceFiles()
if (includes_pack.toBoolean()) {
modPaths << srcDir
}
if (load_user_mods.toBoolean()) {
modPaths << "${hytaleHome}/UserData/Mods"
}
if (!modPaths.isEmpty()) {
programParameters += ' --mods="' + modPaths.join(',') + '"'
}
return programParameters
} }
// Creates a run configuration in IDEA that will run the Hytale server with // Ensure the shaded jar is produced during a normal build.
// your plugin and the default assets. tasks.named('build') {
idea.project.settings.runConfigurations { dependsOn 'shadowJar'
'HytaleServer'(org.jetbrains.gradle.ext.Application) {
mainClass = 'com.hypixel.hytale.Main'
moduleName = project.idea.module.name + '.main'
programParameters = createServerRunArguments(sourceSets.main.java.srcDirs.first().parentFile.absolutePath)
workingDirectory = serverRunDir.absolutePath
}
} }
// Creates a launch.json file for VSCode with the same configuration if (hasHytaleHome) {
tasks.register('generateVSCodeLaunch') { // Create the working directory to run the server if it does not already exist.
def vscodeDir = file("$projectDir/.vscode") def serverRunDir = file("$projectDir/run")
def launchFile = file("$vscodeDir/launch.json") if (!serverRunDir.exists()) {
doLast { serverRunDir.mkdirs()
if (!vscodeDir.exists()) { }
vscodeDir.mkdirs()
def createServerRunArguments = { String srcDir ->
def programParameters = '--allow-op --disable-sentry --assets="' + "${hytaleHome}/install/$patchline/package/game/latest/Assets.zip" + '"'
def modPaths = []
if (includes_pack.toBoolean()) {
modPaths << srcDir
} }
def programParams = createServerRunArguments("\${workspaceFolder}") if (load_user_mods.toBoolean()) {
def launchConfig = [ modPaths << "${hytaleHome}/UserData/Mods"
version: "0.2.0", }
configurations: [ if (!modPaths.isEmpty()) {
[ programParameters += ' --mods="' + modPaths.join(',') + '"'
type: "java", }
name: "HytaleServer", return programParameters
request: "launch", }
mainClass: "com.hypixel.hytale.Main",
args: programParams, def serverJar = file("$hytaleHome/install/$patchline/package/game/latest/Server/HytaleServer.jar")
cwd: "\${workspaceFolder}/run" def assetsZip = file("$hytaleHome/install/$patchline/package/game/latest/Assets.zip")
] 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) {
mainClass = 'com.hypixel.hytale.Main'
moduleName = project.idea.module.name + '.main'
programParameters = createServerRunArguments(sourceSets.main.java.srcDirs.first().parentFile.absolutePath)
workingDirectory = serverRunDir.absolutePath
}
}
// Creates a launch.json file for VSCode with the same configuration
tasks.register('generateVSCodeLaunch') {
def vscodeDir = file("$projectDir/.vscode")
def launchFile = file("$vscodeDir/launch.json")
doLast {
if (!vscodeDir.exists()) {
vscodeDir.mkdirs()
}
def programParams = createServerRunArguments("\${workspaceFolder}")
def launchConfig = [
version: "0.2.0",
configurations: [
[
type: "java",
name: "HytaleServer",
request: "launch",
mainClass: "com.hypixel.hytale.Main",
args: programParams,
cwd: "\${workspaceFolder}/run"
]
]
] ]
] 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.")
}
} }
} }

View File

@@ -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))
}
}

View File

@@ -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
@@ -29,4 +34,4 @@ load_user_mods=false
# manually. You may also want to use a custom path if you are building in # manually. You may also want to use a custom path if you are building in
# a non-standard environment like a build server. The home path should # a non-standard environment like a build server. The home path should
# the folder that contains the install and UserData folder. # the folder that contains the install and UserData folder.
# hytale_home=./test-file # hytale_home=./test-file

View File

@@ -9,7 +9,7 @@
} }
], ],
"Website": "example.org", "Website": "example.org",
"ServerVersion": "*", "ServerVersion": "2026.02.17-255364b8e",
"Dependencies": { "Dependencies": {
}, },