Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
75084e3
update .gitignore
jessefaler May 25, 2026
8f78705
initial commit
Yeetoxic May 13, 2026
a04bfe0
Implemented the server snapshot approach.
Yeetoxic May 13, 2026
67bf5a4
fix(protocube/parser): quote ReplaceValue strings during JSON marshaling
jessefaler May 24, 2026
ad35fe2
Refactor server configuration handling and runtime state management
jessefaler May 25, 2026
e88a235
remove force from kill and stop commands and unregister the server in…
jessefaler May 25, 2026
0f85573
Added daemon install lifecycle visibility
Yeetoxic May 26, 2026
ed4930e
Revert daemon docker compose file
jessefaler May 27, 2026
e90edde
Move install logs out of install info
Yeetoxic May 27, 2026
299202b
Add daemon-owned warmup lifecycle
Yeetoxic May 28, 2026
6cc426f
Add warmup lifecycle test coverage
Yeetoxic May 29, 2026
6f9cb31
Add daemon-owned reinstall and software warmup cleanup
Yeetoxic May 29, 2026
37d1084
Fix Paper smoke install and daemon mount propagation
Yeetoxic May 29, 2026
5340b90
fix: return daemon install logs through lifecycle APIs
Yeetoxic May 29, 2026
0d79542
chore(deps): bump ch.qos.logback:logback-classic in /S4J (#100)
dependabot[bot] May 31, 2026
4d7c84d
chore(deps): bump ch.qos.logback:logback-classic from 1.5.32 to 1.5.3…
dependabot[bot] May 31, 2026
087fdc6
chore(deps): bump com.github.retrooper:packetevents-velocity (#106)
dependabot[bot] May 31, 2026
73e32e4
chore(deps): bump com.fasterxml.jackson.core:jackson-databind (#107)
dependabot[bot] May 31, 2026
e004737
chore(deps): bump ch.qos.logback:logback-classic in /S4J (#108)
dependabot[bot] Jun 7, 2026
3bbb2b3
chore(deps): bump com.github.retrooper:packetevents-velocity in /vsls…
dependabot[bot] Jun 7, 2026
d4b4986
chore(deps): bump com.github.retrooper:packetevents-velocity (#110)
dependabot[bot] Jun 7, 2026
329c4de
chore(deps): bump com.fasterxml.jackson.core:jackson-databind (#111)
dependabot[bot] Jun 7, 2026
746fc40
chore(deps): bump ch.qos.logback:logback-classic from 1.5.33 to 1.5.3…
dependabot[bot] Jun 7, 2026
beb57d9
append server logs last so that appear at the bottom of the log output
jessefaler Jun 8, 2026
6b0e3c9
add pagination to server logs
jessefaler Jun 8, 2026
abbfcb4
chore(deps): bump github.com/mattn/go-colorable in /protocube (#101)
dependabot[bot] Jun 10, 2026
1fa356c
chore(deps): bump github.com/mattn/go-colorable in /daemon (#104)
dependabot[bot] Jun 10, 2026
fff1ae8
Detach node clients from servers when nodes disconnect in Protocube
jessefaler Jun 14, 2026
7cfb679
Remove duplicate SyncWithEnvironment call during server start
jessefaler Jun 14, 2026
d2fb24e
chore(deps): bump golang.org/x/sync from 0.20.0 to 0.21.0 in /daemon …
dependabot[bot] Jun 14, 2026
aeb185c
chore(deps): bump gopkg.in/ini.v1 from 1.67.2 to 1.67.3 in /daemon (#…
dependabot[bot] Jun 14, 2026
31ca2d0
chore(deps): bump golang.org/x/sys from 0.45.0 to 0.46.0 in /daemon (…
dependabot[bot] Jun 14, 2026
b9c4a80
Integrate vSLS with Daemon Install Lifecycle and Warmup Status
jessefaler Jun 20, 2026
7a9b629
Merge branch '74-improve-server-installer' into dev
jessefaler Jun 20, 2026
1b50d69
chore(deps-dev): bump org.sonatype.central:central-publishing-maven-p…
dependabot[bot] Jun 21, 2026
98ffd79
chore(deps-dev): bump org.sonatype.central:central-publishing-maven-p…
dependabot[bot] Jun 21, 2026
465eb64
chore(deps): bump ch.qos.logback:logback-classic in /S4J (#120)
dependabot[bot] Jun 28, 2026
257b943
chore(deps): bump com.github.retrooper:packetevents-velocity (#123)
dependabot[bot] Jun 28, 2026
f8d84a7
chore(deps): bump com.github.retrooper:packetevents-velocity in /vsls…
dependabot[bot] Jun 28, 2026
703ef9e
chore(deps): bump github.com/klauspost/compress in /daemon (#126)
dependabot[bot] Jul 5, 2026
be82750
update paper installation script to use papers v3 api
jessefaler Jul 7, 2026
b56fbbb
chore: bump versions
jessefaler Jul 7, 2026
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
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependency-reduced-pom.xml
# Compiled binaries
slimepacks/slimepacks.so
*.so
daemon/daemon
daemon/daemon*
daemon/sls
protocube/protocube
protocube/protocube*

Empty file modified S4J/ATTRIBUTION
100755 → 100644
Empty file.
4 changes: 2 additions & 2 deletions S4J/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.10.0</version>
<version>0.11.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>ossrh</publishingServerId>
Expand Down Expand Up @@ -133,7 +133,7 @@
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.32</version>
<version>1.5.37</version>
</dependency>
</dependencies>

Expand Down
100 changes: 100 additions & 0 deletions S4J/src/main/java/com/protoxon/S4J/InstallInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.protoxon.S4J;

import org.json.JSONObject;

import java.time.Instant;

/**
* Represents the current installation state for a server instance.
*/
public class InstallInfo {
private final InstallPhase phase;
private final String containerId;
private final String containerName;
private final String status;
private final Long exitCode;
private final Instant startedAt;
private final Instant finishedAt;
private final String failureReason;

public InstallInfo(
InstallPhase phase,
String containerId,
String containerName,
String status,
Long exitCode,
Instant startedAt,
Instant finishedAt,
String failureReason) {
this.phase = phase;
this.containerId = containerId;
this.containerName = containerName;
this.status = status;
this.exitCode = exitCode;
this.startedAt = startedAt;
this.finishedAt = finishedAt;
this.failureReason = failureReason;
}

public static InstallInfo fromJSON(JSONObject json) {
InstallPhase phase = InstallPhase.fromString(json.optString("phase", "unknown"));
String containerId = json.optString("container_id", null);
String containerName = json.optString("container_name", null);
String status = json.optString("status", null);
Long exitCode = json.has("exit_code") && !json.isNull("exit_code")
? json.getLong("exit_code")
: null;
Instant startedAt = parseInstant(json.optString("started_at", null));
Instant finishedAt = parseInstant(json.optString("finished_at", null));
String failureReason = json.optString("failure_reason", null);

return new InstallInfo(
phase,
containerId,
containerName,
status,
exitCode,
startedAt,
finishedAt,
failureReason);
}

private static Instant parseInstant(String value) {
if (value == null || value.isBlank()) {
return null;
}
return Instant.parse(value);
}

public InstallPhase getPhase() {
return phase;
}

public String getContainerId() {
return containerId;
}

public String getContainerName() {
return containerName;
}

public String getStatus() {
return status;
}

public Long getExitCode() {
return exitCode;
}

public Instant getStartedAt() {
return startedAt;
}

public Instant getFinishedAt() {
return finishedAt;
}

public String getFailureReason() {
return failureReason;
}
}
47 changes: 47 additions & 0 deletions S4J/src/main/java/com/protoxon/S4J/InstallPhase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.protoxon.S4J;

/**
* Represents the current phase of a server installation.
*/
public enum InstallPhase {
UNKNOWN("unknown"),
IDLE("idle"),
INSTALLING("installing"),
WARMING("warming"),
POST_WARMUP("post_warmup"),
INSTALL_FAILED("install_failed"),
WARMUP_FAILED("warmup_failed"),
POST_WARMUP_FAILED("post_warmup_failed"),
COMPLETED("completed");

private final String phase;

InstallPhase(String phase) {
this.phase = phase;
}

public String getPhase() {
return phase;
}

/**
* Parses a string phase value to the corresponding enum.
* Case-insensitive matching is performed.
*
* @param phase the phase string (e.g., "installing", "completed")
* @return the corresponding InstallPhase enum, or UNKNOWN if no match is found
*/
public static InstallPhase fromString(String phase) {
if (phase == null || phase.isBlank()) {
return UNKNOWN;
}

String normalized = phase.trim().toLowerCase();
for (InstallPhase installPhase : values()) {
if (installPhase.getPhase().equals(normalized)) {
return installPhase;
}
}
return UNKNOWN;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.protoxon.S4J.client.entites;


import com.protoxon.S4J.InstallInfo;
import com.protoxon.S4J.PowerAction;
import com.protoxon.S4J.SLSAction;
import com.protoxon.S4J.ServerStats;
import com.protoxon.S4J.ServerStatus;
import com.protoxon.S4J.requests.PaginationAction;

import java.util.List;

Expand Down Expand Up @@ -138,20 +140,57 @@ default SLSAction<Void> unpause() {
SLSAction<Void> sendCommands(List<String> commands);

/**
* Retrieves the server logs
* @param size The number of log lines to retrieve (defaults to 100, max 100, min 1)
* @return SLSAction that returns a list of log lines
* Retrieves server logs with pagination. Page 1 contains the most recent lines.
*
* @return PaginationAction that returns a page of log lines
*/
SLSAction<List<String>> getLogs(int size);
PaginationAction<String> getLogs();

/**
* Retrieves the server logs with default size of 100
* @return SLSAction that returns a list of log lines
* Retrieves server logs with a custom page size. Page 1 contains the most recent lines.
*
* @param perPage The number of log lines per page (defaults to 50, max 100, min 1)
* @return PaginationAction that returns a page of log lines
*/
default SLSAction<List<String>> getLogs() {
return getLogs(100);
default PaginationAction<String> getLogs(int perPage) {
int size = perPage <= 0 ? 50 : Math.min(perPage, 100);
return getLogs().limit(size);
}

/**
* Retrieves the current installation state for this server.
*
* @return SLSAction that resolves to the install info
*/
SLSAction<InstallInfo> getInstallInfo();

/**
* Retrieves install logs from all install phases (install, warmup, post-warmup) with pagination.
* Page 1 contains the most recent lines.
*
* @return PaginationAction that returns a page of install log lines
*/
PaginationAction<String> getInstallLogs();

/**
* Retrieves install logs with a custom page size. Page 1 contains the most recent lines.
*
* @param perPage The number of log lines per page (defaults to 50, max 100, min 1)
* @return PaginationAction that returns a page of install log lines
*/
default PaginationAction<String> getInstallLogs(int perPage) {
int size = perPage <= 0 ? 50 : Math.min(perPage, 100);
return getInstallLogs().limit(size);
}

/**
* Reinstalls the server software using its configured installation script.
* Every server using the same installed artifact must be stopped first.
*
* @return SLSAction that completes when the reinstall request is accepted
*/
SLSAction<Void> reinstall();

/**
* Resets the server by deleting the overlay filesystem and restarting if it was running.
* This will stop the server if it's running, wait for it to fully stop, reset the overlay,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package com.protoxon.S4J.client.entites.impl;

import com.protoxon.S4J.InstallInfo;
import com.protoxon.S4J.PowerAction;
import com.protoxon.S4J.SLSAction;
import com.protoxon.S4J.ServerStats;
import com.protoxon.S4J.ServerStatus;
import com.protoxon.S4J.client.entites.Allocation;
import com.protoxon.S4J.client.entites.ClientServer;
import com.protoxon.S4J.client.entities.impl.SLSClientImpl;
import com.protoxon.S4J.requests.PaginationAction;
import com.protoxon.S4J.requests.Route;
import com.protoxon.S4J.requests.SLSActionImpl;
import com.protoxon.S4J.requests.action.operator.impl.StringPaginationResponseImpl;
import org.json.JSONArray;
import org.json.JSONObject;

Expand Down Expand Up @@ -130,34 +133,23 @@ public SLSAction<Void> sendCommands(List<String> commands) {
}

@Override
public SLSAction<List<String>> getLogs(int size) {
// Validate and clamp size parameter (1-100, default 100)
if (size <= 0) {
size = 100;
} else if (size > 100) {
size = 100;
}

Route.CompiledRoute route = Route.Server.LOGS.compile(getId())
.withQueryParams("size", String.valueOf(size));
public PaginationAction<String> getLogs() {
return StringPaginationResponseImpl.onPagination(
impl.getS4J(), Route.Server.LOGS.compile(getId()));
}

@Override
public SLSAction<InstallInfo> getInstallInfo() {
return SLSActionImpl.onRequestExecute(
impl.getS4J(),
route,
(response, request) -> {
JSONObject responseObj = response.getObject();
JSONArray dataArray = responseObj.optJSONArray("data");

if (dataArray == null) {
return new ArrayList<>();
}

List<String> logs = new ArrayList<>();
for (int i = 0; i < dataArray.length(); i++) {
logs.add(dataArray.getString(i));
}
return logs;
});
Route.Server.INSTALL.compile(getId()),
(response, request) -> InstallInfo.fromJSON(response.getObject()));
}

@Override
public PaginationAction<String> getInstallLogs() {
return StringPaginationResponseImpl.onPagination(
impl.getS4J(), Route.Server.INSTALL_LOGS.compile(getId()));
}

@Override
Expand All @@ -175,6 +167,12 @@ public SLSAction<Void> delete(boolean force) {
impl.getS4J(), route);
}

@Override
public SLSAction<Void> reinstall() {
return SLSActionImpl.onRequestExecute(
impl.getS4J(), Route.Server.REINSTALL.compile(getId()));
}

@Override
public SLSAction<Void> reset() {
return SLSActionImpl.onRequestExecute(
Expand Down
Loading
Loading