-
Notifications
You must be signed in to change notification settings - Fork 1.4k
POC only: Bifrost #5319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
POC only: Bifrost #5319
Changes from 4 commits
b4047c8
e7b2d45
ece87bf
ad8f5de
4a12046
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| // Nakama subsystem - optional Bifrost integration | ||
| // Bridges Gestalt chat events to/from a Nakama chat channel | ||
|
|
||
| plugins { | ||
| java | ||
| `java-library` | ||
| id("terasology-common") | ||
| } | ||
|
|
||
| apply(from = "$rootDir/config/gradle/common.gradle") | ||
|
|
||
| configure<SourceSetContainer> { | ||
| main { java.destinationDirectory.set(layout.buildDirectory.dir("classes")) } | ||
| test { java.destinationDirectory.set(layout.buildDirectory.dir("testClasses")) } | ||
| } | ||
|
|
||
| repositories { | ||
| maven { | ||
| name = "JitPack" | ||
| url = uri("https://jitpack.io") | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation(project(":engine")) | ||
|
|
||
| annotationProcessor(libs.gestalt.injectjava) | ||
|
|
||
| api("com.github.heroiclabs.nakama-java:nakama-java:2.5.3") | ||
| } | ||
|
|
||
| tasks.named<Test>("test") { | ||
| // Exclude integration tests by default — they need a running Nakama server | ||
| useJUnitPlatform { | ||
| if (!project.hasProperty("includeTags")) { | ||
| excludeTags("integration") | ||
| } else { | ||
| includeTags(project.property("includeTags") as String) | ||
| } | ||
| } | ||
| // Pass nakama.test.* system properties through to the test JVM | ||
| System.getProperties().entries | ||
| .filter { (it.key as String).startsWith("nakama.test.") } | ||
| .forEach { systemProperty(it.key as String, it.value) } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| // Copyright 2026 The Terasology Foundation | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package org.terasology.subsystem.nakama; | ||
|
|
||
| import org.terasology.engine.config.flexible.AutoConfig; | ||
| import org.terasology.engine.config.flexible.Setting; | ||
|
|
||
| import static org.terasology.engine.config.flexible.SettingArgument.defaultValue; | ||
| import static org.terasology.engine.config.flexible.SettingArgument.name; | ||
| import static org.terasology.engine.config.flexible.SettingArgument.type; | ||
|
|
||
| /** | ||
| * Persistent configuration for the Nakama subsystem. | ||
| * Auto-discovered by the engine and saved to ~/.terasology/configs/nakama/NakamaAutoConfig.cfg | ||
| */ | ||
| public class NakamaAutoConfig extends AutoConfig { | ||
|
|
||
| public final Setting<Boolean> enabled = setting( | ||
| type(Boolean.class), | ||
| defaultValue(false), | ||
| name("Enable Nakama") | ||
| ); | ||
|
|
||
| public final Setting<String> host = setting( | ||
| type(String.class), | ||
| defaultValue("localhost"), | ||
| name("Nakama Server Host") | ||
| ); | ||
|
|
||
| public final Setting<Integer> grpcPort = setting( | ||
| type(Integer.class), | ||
| defaultValue(7349), | ||
| name("gRPC Port") | ||
| ); | ||
|
|
||
| public final Setting<Integer> wsPort = setting( | ||
| type(Integer.class), | ||
| defaultValue(7350), | ||
| name("WebSocket Port") | ||
| ); | ||
|
|
||
| public final Setting<String> channel = setting( | ||
| type(String.class), | ||
| defaultValue("bifrost.lobby"), | ||
| name("Chat Channel") | ||
| ); | ||
|
|
||
| public final Setting<String> playerName = setting( | ||
| type(String.class), | ||
| defaultValue(""), | ||
| name("Player Name") | ||
| ); | ||
|
|
||
| @Override | ||
| public String getName() { | ||
| return "Nakama Settings"; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| // Copyright 2026 The Terasology Foundation | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| package org.terasology.subsystem.nakama; | ||
|
|
||
| /** | ||
| * Configuration for the Nakama subsystem. | ||
| * Read from system properties for the POC. | ||
| */ | ||
| public class NakamaConfig { | ||
| private boolean enabled = false; | ||
| private String host = "localhost"; | ||
| private int grpcPort = 7349; | ||
| private int wsPort = 7350; | ||
| private String channel = "bifrost.lobby"; | ||
| private String playerName = ""; | ||
|
|
||
| public boolean isEnabled() { return enabled; } | ||
| public void setEnabled(boolean enabled) { this.enabled = enabled; } | ||
|
|
||
| public String getHost() { return host; } | ||
| public void setHost(String host) { this.host = host; } | ||
|
|
||
| /** gRPC port for API calls (auth, account). Default: 7349. */ | ||
| public int getGrpcPort() { return grpcPort; } | ||
| public void setGrpcPort(int grpcPort) { this.grpcPort = grpcPort; } | ||
|
|
||
| /** @deprecated Use {@link #getGrpcPort()}. Kept for backwards compatibility. */ | ||
| @Deprecated | ||
| public int getPort() { return grpcPort; } | ||
| /** @deprecated Use {@link #setGrpcPort(int)}. */ | ||
| @Deprecated | ||
| public void setPort(int port) { this.grpcPort = port; } | ||
|
|
||
| /** WebSocket port for realtime (chat, presence). Default: 7350. */ | ||
| public int getWsPort() { return wsPort; } | ||
| public void setWsPort(int wsPort) { this.wsPort = wsPort; } | ||
|
|
||
| public String getChannel() { return channel; } | ||
| public void setChannel(String channel) { this.channel = channel; } | ||
|
|
||
| public String getPlayerName() { return playerName; } | ||
| public void setPlayerName(String playerName) { this.playerName = playerName; } | ||
|
|
||
| /** | ||
| * Load config from system properties (nakama.enabled, nakama.host, etc.) | ||
| * Falls back to defaults if not set. | ||
| */ | ||
| public static NakamaConfig fromSystemProperties() { | ||
| NakamaConfig config = new NakamaConfig(); | ||
| config.setEnabled(Boolean.parseBoolean(System.getProperty("nakama.enabled", "false"))); | ||
| config.setHost(System.getProperty("nakama.host", "localhost")); | ||
| config.setGrpcPort(Integer.parseInt(System.getProperty("nakama.grpcPort", "7349"))); | ||
| config.setWsPort(Integer.parseInt(System.getProperty("nakama.wsPort", "7350"))); | ||
|
Comment on lines
+53
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If 🛡️ Proposed defensive parsing- config.setGrpcPort(Integer.parseInt(System.getProperty("nakama.grpcPort", "7349")));
- config.setWsPort(Integer.parseInt(System.getProperty("nakama.wsPort", "7350")));
+ config.setGrpcPort(parseIntOrDefault(System.getProperty("nakama.grpcPort"), 7349));
+ config.setWsPort(parseIntOrDefault(System.getProperty("nakama.wsPort"), 7350));Add a helper method: private static int parseIntOrDefault(String value, int defaultValue) {
if (value == null || value.isEmpty()) {
return defaultValue;
}
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return defaultValue;
}
}🤖 Prompt for AI Agents |
||
| config.setChannel(System.getProperty("nakama.channel", "bifrost.lobby")); | ||
| config.setPlayerName(System.getProperty("nakama.playerName", "")); | ||
| return config; | ||
| } | ||
|
Comment on lines
+49
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify whether NakamaConfig is actually used anywhere in the codebase
echo "=== Searching for NakamaConfig usage ==="
rg -n 'NakamaConfig' --type java -g '!**/NakamaConfig.java' -g '!**/NakamaConfigTest.java'Repository: MovingBlocks/Terasology Length of output: 107 🏁 Script executed: # Find and examine NakamaSubSystem.java to verify it only uses NakamaAutoConfig
find . -name "NakamaSubSystem.java" -type fRepository: MovingBlocks/Terasology Length of output: 153 🏁 Script executed: # Check NakamaSubSystem's usage of config classes
rg -n "initialise\|NakamaAutoConfig\|NakamaConfig" subsystems/Nakama/src/main/java/org/terasology/subsystem/nakama/ --type javaRepository: MovingBlocks/Terasology Length of output: 49 🏁 Script executed: # Look at the actual NakamaConfig file to check for exception handling and comments
cat -n subsystems/Nakama/src/main/java/org/terasology/subsystem/nakama/NakamaConfig.javaRepository: MovingBlocks/Terasology Length of output: 2875 🏁 Script executed: cat -n subsystems/Nakama/src/main/java/org/terasology/subsystem/nakama/NakamaSubSystem.javaRepository: MovingBlocks/Terasology Length of output: 10875 🏁 Script executed: # Also check what files exist in the Nakama subsystem directory
ls -la subsystems/Nakama/src/main/java/org/terasology/subsystem/nakama/Repository: MovingBlocks/Terasology Length of output: 453
The search returned zero matches for Additionally, 🤖 Prompt for AI Agents |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: MovingBlocks/Terasology
Length of output: 15943
🌐 Web query:
What are the breaking changes between protobuf-java 3.x and 4.x?💡 Result:
The primary breaking changes in protobuf-java 4.x (starting with v4.26.0 / protoc v26.0, released March 2024) compared to 3.x revolve around internal cleanups and support for new features like Protobuf Editions, breaking binary compatibility with older generated code. Key breaking changes: - Removal of GeneratedMessageV3 class and related APIs (e.g., PARSER field replaced by parser method; makeExtensionsImmutable and other deprecated methods removed). Generated messages now extend GeneratedMessage. - Breaking compatibility with pre-v3.22 generated code from 3.x; requires regeneration with protoc >=3.22 (ideally 3.25.x) for runtime compatibility via shims added in later 4.x releases (e.g., 4.27.4+, 4.33+ supports all 3.x gencode). - Removal of deprecated descriptor syntax APIs; use feature accessors like FieldDescriptor.hasPresence, EnumDescriptor.isClosed. - Runtime methods for v2 gencode compatibility removed. - Introduction of "poison pills" to enforce gencode/runtime version matching. - Refactoring of Java generator into separate packages. - Support for Editions (edition = "2023" etc.) changes generated code; old proto2/proto3 syntax still supported but may warn. Migration steps: - Regenerate .proto files with matching/newer protoc version (protoc 25.x+ for 3.x/4.x compatibility). - Update non-generated code referencing removed classes/methods (use Message interface instead of GeneratedMessageV3). - For libraries, use protoc 25.x for 3.x+4.x support; latest for 4.x+5.x. - protobuf-java 3.x supported until March 2027; 4.x until 2028. Binary wire format remains unchanged. Later 4.x versions (4.27+) added shims for gradual migration.
Citations:
makeExtensionsImmutable()disappeared in 4.26.0 from the supposedly backwards-compatible GeneratedMessageV3 protocolbuffers/protobuf#19540Protobuf 4.x requires .proto files to be regenerated with matching protoc version.
Protobuf 4.x has breaking changes from 3.x, particularly removal of GeneratedMessageV3 and changes to descriptor APIs. The
.protofiles inengine/src/main/protobuf/must be regenerated with protoc 4.x (or ≥3.22 for 4.x compatibility).The codebase's heavy use of builder patterns (
.newBuilder(),.addField(),.build()) is compatible with 4.x. However, verify that code usingcom.google.protobuf.Descriptors(inEntityDataJSONFormat.java,ProtobufPersistedDataSerializer.java) works correctly with the new API, then run full test suite to confirm compatibility before merging.🤖 Prompt for AI Agents