# Development setup

JDK requirements, first build, IDE dev runs and common build/test commands

Source: https://socketsvc.vercel.app/client/development/setup
## Prerequisites

| Requirement | Notes |
| --- | --- |
| Git | To get the source |
| JDK 25 | Gradle daemon and 26.x compilation/tests |
| JDK 21 | Compile/test toolchain for 1.21.11 |
| Python 3.9+ | Only needed for the all-version scripts (`scripts/*.py`); no pip packages required |

Use the project's Gradle Wrapper; a separately installed Gradle is not needed.

[gradle/gradle-daemon-jvm.properties](https://github.com/HippoDev03/SocketSVC/blob/main/gradle/gradle-daemon-jvm.properties) pins the Gradle daemon to Java 25; each module then picks its compile and test JDK through toolchains. The Wrapper version is defined in [gradle-wrapper.properties](https://github.com/HippoDev03/SocketSVC/blob/main/gradle/wrapper/gradle-wrapper.properties).

## First build

<Tabs items={['Windows PowerShell', 'Linux / macOS']}>
<Tab value="Windows PowerShell">

```powershell
git clone https://github.com/HippoDev03/SocketSVC.git
cd SocketSVC
.\gradlew.bat --version
.\gradlew.bat javaToolchains
.\gradlew.bat buildAll
```

</Tab>
<Tab value="Linux / macOS">

```sh
git clone https://github.com/HippoDev03/SocketSVC.git
cd SocketSVC
sh gradlew --version
sh gradlew javaToolchains
sh gradlew buildAll
```

</Tab>
</Tabs>

The first build downloads Gradle, Minecraft, Fabric, NeoForge, Forge and other dependencies, so it needs network access; the first NeoForge/Forge setup takes several minutes per Minecraft version.

<Callout type="warn" title="If a JDK is not found">
Check `javaToolchains` and the IDE's Gradle JVM setting first. Do not lower the project's Java version just to get a local build to pass.
</Callout>

## Build tasks and properties

| Gradle task | Builds |
| --- | --- |
| `buildAll` | Every artifact at once: client, server and proxy |
| `buildAllClients` | All clients |
| `buildAllServers` | All servers (Paper + each loader's server mod) |
| `buildAllProxy` | The Velocity/BungeeCord relay plugin |

These are all Gradle tasks: no Python needed, and they appear in the IDE's Gradle `build` group. They read the supported list straight from the version catalog and build each Minecraft version in sequence, including tests and artifact checks.

A single Gradle invocation targets one Minecraft version (`-PminecraftVersion`, defaulting to the catalog's `minecraft.default`) and configures every loader project available for that version, e.g. `:client:neoforge`. Matrix tasks such as `buildAll` are not narrowed by `-PminecraftVersion`.

| Property | Effect |
| --- | --- |
| `-PminecraftVersion=26.2` | Minecraft version for this Gradle invocation |
| `-Ploaders=fabric` | Configure only the given loader's projects, for faster local builds |
| `-Ploaders=none` | Keep only Paper and proxy |

For the version catalog, default version and artifact locations, see [versions and loaders](/client/development/versions).

## IDE and dev runs

Import the root directory as a Gradle project and set the Gradle JVM to JDK 25. To switch versions, add `-PminecraftVersion=26.2` to the Gradle run configuration, generate sources with the same version property and reload the project.

<Tabs items={['Windows PowerShell', 'Linux / macOS']}>
<Tab value="Windows PowerShell">

```powershell
.\gradlew.bat :client:fabric:generateMainCompatibilitySources '-PminecraftVersion=26.2'
.\gradlew.bat :client:fabric:runClient '-PminecraftVersion=26.2'
.\gradlew.bat :server:neoforge:runServer '-PminecraftVersion=26.2'
```

In Windows PowerShell keep the quotes around the version property so the argument is not split.

</Tab>
<Tab value="Linux / macOS">

```sh
sh gradlew :client:fabric:generateMainCompatibilitySources -PminecraftVersion=26.2
sh gradlew :client:fabric:runClient -PminecraftVersion=26.2
sh gradlew :server:neoforge:runServer -PminecraftVersion=26.2
```

</Tab>
</Tabs>

`:<side>:<loader>:generateMainCompatibilitySources` refreshes the generated sources the IDE uses; dev game runs use `runClient`/`runServer` with the same property.

<Callout type="warn" title="Do not edit generated sources">
Edit `client/common/src/`, `server/common/src/` or a loader project's `src/`, not `<side>/<loader>/build/<version>/generated/compat/`. The latter is the build's version-adapted output and is overwritten on the next generation. After adding a Java file, rerun the generation task first, then reload the IDE.
</Callout>

Build different Minecraft versions one after another in the same checkout; for parallel work across versions use separate checkouts so Loom/ModDevGradle/ForgeGradle working files do not interfere.

## Common builds and tests

`test` accepts `--tests` to narrow the JUnit scope, but partial tests do not replace the full checks required before committing (see [daily workflow](/client/development/contributing#daily-workflow)).

<Tabs items={['Windows PowerShell', 'Linux / macOS']}>
<Tab value="Windows PowerShell">

```powershell
# Build every client, server and proxy at once (including tests and packaging)
.\gradlew.bat buildAll

# Build only all clients / all servers
.\gradlew.bat buildAllClients
.\gradlew.bat buildAllServers

# Specific version and loader: compile, test, package and verify
.\gradlew.bat :client:neoforge:build :server:neoforge:build '-PminecraftVersion=26.2'

# Configure only some loader projects for a faster local build
.\gradlew.bat :client:fabric:build '-PminecraftVersion=26.2' '-Ploaders=fabric'

# The Python script works too; handy for picking a few versions/loaders/sides, or CI
python scripts/build_matrix.py
python scripts/build_matrix.py 1.21.11 26.2 --loaders fabric,forge --side client
python scripts/build_matrix.py 1.21.11 26.2 --loaders forge --side server

# Print the current version matrix without building
python scripts/build_matrix.py --matrix

# Partial JUnit tests (client/common tests run in the Fabric project)
.\gradlew.bat :client:fabric:test '-PminecraftVersion=26.2' --tests 'com.socketsvc.client.VoiceReconnectTest'

# Real Fabric Loader Mixin verification / native audio regression
.\gradlew.bat :client:fabric:mixinTest '-PminecraftVersion=26.2'
.\gradlew.bat :client:fabric:audioRegressionTest '-PminecraftVersion=26.2'

# Paper plugin compile, tests and shaded JAR (no loader projects needed)
.\gradlew.bat :server:paper:build '-Ploaders=none'

# Velocity/BungeeCord relay plugin compile, tests and shaded JAR
.\gradlew.bat buildAllProxy
```

</Tab>
<Tab value="Linux / macOS">

```sh
# Build every client, server and proxy at once (including tests and packaging)
sh gradlew buildAll

# Build only all clients / all servers
sh gradlew buildAllClients
sh gradlew buildAllServers

# Specific version and loader: compile, test, package and verify
sh gradlew :client:neoforge:build :server:neoforge:build -PminecraftVersion=26.2
sh gradlew :client:forge:build -PminecraftVersion=26.2

# Configure only some loader projects for a faster local build
sh gradlew :client:fabric:build -PminecraftVersion=26.2 -Ploaders=fabric

# The Python script works too; handy for picking a few versions/loaders/sides, or CI
python3 scripts/build_matrix.py
python3 scripts/build_matrix.py 26.2
python3 scripts/build_matrix.py 1.21.11 26.2 --loaders fabric,forge --side client

# Print the current version matrix without building
python3 scripts/build_matrix.py --matrix

# Partial JUnit tests (client/common tests run in the Fabric project)
sh gradlew :client:fabric:test -PminecraftVersion=26.2 --tests 'com.socketsvc.client.VoiceReconnectTest'

# Real Fabric Loader Mixin verification / native audio regression
sh gradlew :client:fabric:mixinTest -PminecraftVersion=26.2
sh gradlew :client:fabric:audioRegressionTest -PminecraftVersion=26.2

# Paper plugin compile, tests and shaded JAR (no loader projects needed)
sh gradlew :server:paper:build -Ploaders=none

# Velocity/BungeeCord relay plugin compile, tests and shaded JAR
sh gradlew buildAllProxy
```

</Tab>
</Tabs>

For installing and configuring the relay plugin see [Proxy](/proxy); for what each check actually verifies and where reports go, see [validation and releases](/client/development/ci-release).

## Build troubleshooting

| Symptom | Check first |
| --- | --- |
| Gradle cannot find Java / class version errors | JDK 21/25 installation, daemon criteria, IDE Gradle JVM, `javaToolchains` |
| Unsupported Minecraft version | The version catalog and the full `-PminecraftVersion=...` property; do not bypass it by changing the version check |
| IDE shows old APIs or cannot find a new class | Target version is consistent, regenerate compatibility sources, reload Gradle |
| Waiting on the Loom cache lock | Whether an IDE or another build uses the same checkout; wait for it to finish, do not delete a lock that is in use |
| Icons did not change | Whether client/common resources were synced, the new JAR is in use, and the JAR comes from the right version and loader directory |
| Mixin fails to apply | Look at the `mixinTest` and bytecode test reports first; check version/signature/call path |
| Game connected but no voice | `/ssvc status`, server status, base URL, listener reachability, proxy negotiation, first-time setup and mute state (see also [troubleshooting](/client/troubleshooting)) |
| Audio tests pass but real audio is wrong | Device routing, capture/playback settings, real two-player testing; synthetic tests do not cover every acoustic condition (see [audio validation](/client/development/audio-validation)) |