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
110 changes: 57 additions & 53 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
name: Build Plugin

permissions:
contents: write

on:
push:
branches: [ main, develop ]
tags: [ 'v*' ]
pull_request:
branches: [ main ]

Expand All @@ -11,62 +15,62 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
- name: Cache Gradle Dependencies
uses: actions/cache@v4
with:
path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant Execute Permission for Gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew shadowJar
- name: Run Tests
run: ./gradlew test
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: plugin-jar
path: build/libs/*.jar
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'

- name: Cache Gradle Dependencies
uses: actions/cache@v4
with:
path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant Execute Permission for Gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew shadowJar

- name: Run Tests
run: ./gradlew test

- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: plugin-jar
path: build/libs/*.jar

release:
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')

steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'
- name: Grant Execute Permission for Gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew shadowJar
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: build/libs/*.jar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Java 25
uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'temurin'

- name: Grant Execute Permission for Gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew shadowJar

- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: build/libs/*.jar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
145 changes: 90 additions & 55 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
plugins {
id 'java'
id 'org.jetbrains.gradle.plugin.idea-ext' version '1.3'
id 'com.gradleup.shadow' version '9.3.1'
}

import org.gradle.internal.os.OperatingSystem
Expand All @@ -26,11 +27,10 @@ ext {
}
}

if (!project.hasProperty('hytaleHome')) {
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.');
}
else if (!file(project.findProperty('hytaleHome')).exists()) {
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')}")
def hytaleHomePath = project.findProperty('hytaleHome')
def hasHytaleHome = hytaleHomePath && file(hytaleHomePath).exists()
if (!hasHytaleHome) {
logger.lifecycle("Hytale install not detected; run configs that launch the server will be skipped. Set -Phytale_home=/path/to/Hytale to enable them.")
}

java {
Expand All @@ -45,16 +45,27 @@ javadoc {
}

// 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 without bundling it. When a local install is
// present, we still use its jar for launching the server in IDE run configs.
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.
def serverRunDir = file("$projectDir/run")
if (!serverRunDir.exists()) {
serverRunDir.mkdirs()
repositories {
mavenCentral()
maven {
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
Expand All @@ -78,54 +89,78 @@ tasks.named('processResources') {
dependsOn 'updatePluginManifest'
}

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
}
if (load_user_mods.toBoolean()) {
modPaths << "${hytaleHome}/UserData/Mods"
}
if (!modPaths.isEmpty()) {
programParameters += ' --mods="' + modPaths.join(',') + '"'
}
return programParameters
tasks.named('shadowJar') {
archiveClassifier.set('')
mergeServiceFiles()
}

// 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
}
// Ensure the shaded jar is produced during a normal build.
tasks.named('build') {
dependsOn 'shadowJar'
}

// 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()
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 modPaths = []
if (includes_pack.toBoolean()) {
modPaths << srcDir
}
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"
]
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
// 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.")
}
}
}
7 changes: 6 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ includes_pack=true
# official launcher.
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
# 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
Expand All @@ -29,4 +34,4 @@ load_user_mods=false
# 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
# the folder that contains the install and UserData folder.
# hytale_home=./test-file
# hytale_home=./test-file