Skip to content
Closed
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
514d60d
Switch to Bun
Protonull Jun 10, 2025
62164a9
Switch to bun:sqlite
Protonull Jun 10, 2025
3e2db02
Fix server port compilation issue
Protonull Jun 10, 2025
b85a19f
Update BufWriter to use ArrayBufferSink
Protonull Jun 10, 2025
a63ce4d
Switch to Bun.listen()
Protonull Jun 10, 2025
ee41818
Fix type-import warnings
Protonull Jun 10, 2025
8c03847
Add compile-to-executable build script
Protonull Jun 10, 2025
037628e
Minor fixup of packet serialisation
Protonull Jun 10, 2025
29baa44
Move encryption and ciphers to crypto file
Protonull Jun 10, 2025
ffe097d
Update typescript version
Protonull Jun 10, 2025
e79d43c
Resolve ProtocolHandler cleanup todo
Protonull Jun 10, 2025
3c6e558
Consolidate packets into single file
Protonull Jun 10, 2025
0956769
Consolidate buffer helper classes into single file
Protonull Jun 10, 2025
d26820d
Run prettier
Protonull Jun 10, 2025
d75a4a4
Slight reorganisation
Protonull Jun 10, 2025
13b09aa
Switch handshake and auth to a state model
Protonull Jun 10, 2025
d429342
Switch to websockets
Protonull Jun 10, 2025
b0f377f
Drastically improve database performance
Protonull Jun 11, 2025
1810c87
Set max frame/payload length to max u16 value
Protonull Jun 11, 2025
e7e5700
Turns out where-in is WAY more efficient than where-and-or-chaining
Protonull Jun 11, 2025
26bae6b
Fix Zod dependency error
Protonull Jun 11, 2025
632bca3
Add gen prefixes to columns and add transactions
Protonull Jun 11, 2025
003df47
Add database migrations
Protonull Jun 11, 2025
71ba397
Update workflows
Protonull Jun 14, 2025
de077a4
Create database test
Protonull Jun 14, 2025
8de3cb4
Destaticify database connection
Protonull Jun 14, 2025
5261d2b
Fix websocket close handler
Protonull Jun 14, 2025
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
15 changes: 6 additions & 9 deletions .github/workflows/build-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
version: ["lts/*", "latest"]
version: ["1.2.15", "latest"]
steps:
- uses: actions/checkout@v3
- name: Use latest Node.js LTS
uses: actions/setup-node@v3
- name: Setup bun.sh
uses: oven-sh/setup-bun@v1
with:
node-version: ${{ matrix.version }}
# cache: "yarn"
- run: yarn
bun-version: ${{ matrix.version }}
- run: bun install
working-directory: ./server
- run: yarn build
working-directory: ./server
- run: yarn test
- run: bun test
working-directory: ./server
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ You can control who has access to a Sync Server by editing its `allowed-users.tx
<summary>System Install</summary>
<br />

- install recent nodejs (~17)
- install [Bun](https://bun.sh/)
- clone code, `cd server`
- `npm install`
- `npm run build` -- this has to be run after every time the code is edited
- `npm run start`
- `bun install`
- `bun start`
- to stop, press Ctrl+C twice
</details>

Expand Down
3 changes: 3 additions & 0 deletions mod/common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ dependencies {
modCompileOnly("maven.modrinth:journeymap:5JbcGXLn")
// https://modrinth.com/mod/xaeros-minimap/version/23.6.2_Fabric_1.18.2 (23.6.2 fabric)
modCompileOnly("maven.modrinth:xaeros-minimap:Jwydpps9")

// https://github.com/TooTallNate/Java-WebSocket
compileOnly("org.java-websocket:Java-WebSocket:1.6.0")
}

tasks {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void addCatchupChunks(List<CatchupChunk> catchupChunks) {
if (catchupChunks.isEmpty()) return;
var catchupDim = catchupChunks.get(0).dimension();
if (!dimensionState.dimension.equals(catchupDim)) {
logger.warn("Catchup chunks from wrong dimension " + catchupDim + ", expected " + dimensionState.dimension);
LOGGER.warn("Catchup chunks from wrong dimension " + catchupDim + ", expected " + dimensionState.dimension);
return;
}
synchronized (this.catchupChunks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@
import gjum.minecraft.mapsync.common.config.ModConfig;
import gjum.minecraft.mapsync.common.config.ServerConfig;
import gjum.minecraft.mapsync.common.data.*;
import gjum.minecraft.mapsync.common.net.SyncAddress;
import gjum.minecraft.mapsync.common.net.SyncClient;
import gjum.minecraft.mapsync.common.net.packet.*;
import java.util.stream.Collectors;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
import net.minecraft.network.protocol.game.ClientboundRespawnPacket;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW;

import java.util.*;
import java.util.stream.Collectors;

import static gjum.minecraft.mapsync.common.Cartography.chunkTileFromLevel;

Expand All @@ -27,7 +29,7 @@ public abstract class MapSyncMod {

private static final Minecraft mc = Minecraft.getInstance();

public static final Logger logger = LogManager.getLogger(MapSyncMod.class);
public static final Logger LOGGER = LogManager.getLogger(MapSyncMod.class);

private static MapSyncMod INSTANCE;

Expand Down Expand Up @@ -123,30 +125,41 @@ public void handleRespawn(ClientboundRespawnPacket packet) {
if (syncServerAddresses.isEmpty()) return shutDownSyncClients();

// will be filled with clients that are still wanted (address) and are still connected
var existingClients = new HashMap<String, SyncClient>();
var existingClients = new HashMap<SyncAddress, SyncClient>();

for (SyncClient client : syncClients) {
if (client.isShutDown) continue;
for (final SyncClient client : this.syncClients) {
if (client.isShutDown) {
continue;
}
// avoid reconnecting to same sync server, to keep shared state (expensive to resync)
if (!client.gameAddress.equals(serverConfig.gameAddress)) {
debugLog("Disconnecting sync client; different game server");
if (!StringUtils.equals(client.gameAddress, serverConfig.gameAddress)) {
LOGGER.warn("Disconnecting sync client; different game server");
client.shutDown();
} else if (!syncServerAddresses.contains(client.address)) {
debugLog("Disconnecting sync client; different sync address");
}
else if (!syncServerAddresses.contains(client.syncAddress.toString())) {
LOGGER.warn("Disconnecting sync client; different sync address");
client.shutDown();
} else {
existingClients.put(client.address, client);
}
else {
existingClients.put(client.syncAddress, client);
}
}

syncClients = syncServerAddresses.stream().map(address -> {
var client = existingClients.get(address);
if (client == null) client = new SyncClient(address, serverConfig.gameAddress);
client.autoReconnect = true;
return client;
}).collect(Collectors.toList());

return syncClients;
this.syncClients = syncServerAddresses.stream()
.map(SyncAddress::of)
.filter(Objects::nonNull)
.distinct()
.map((address) -> {
SyncClient client = existingClients.get(address);
if (client == null) {
client = new SyncClient(address, serverConfig.gameAddress);
}
client.autoReconnect = true;
return client;
})
.collect(Collectors.toCollection(ArrayList::new));

return this.syncClients;
}

public List<SyncClient> shutDownSyncClients() {
Expand Down Expand Up @@ -214,11 +227,6 @@ public void handleMcChunkPartialChange(int cx, int cz) {
// TODO update ChunkTile in a second or so; remember dimension in case it changes til then
}

public void handleSyncServerEncryptionSuccess() {
debugLog("tcp encrypted");
// TODO tell server our current dimension
}

public void handleRegionTimestamps(ClientboundRegionTimestampsPacket packet, SyncClient client) {
DimensionState dimension = getDimensionState();
if (dimension == null) return;
Expand Down Expand Up @@ -258,7 +266,7 @@ public void handleSharedChunk(ChunkTile chunkTile) {
public void handleCatchupData(ClientboundChunkTimestampsResponsePacket packet) {
var dimensionState = getDimensionState();
if (dimensionState == null) return;
debugLog("received catchup: " + packet.chunks.size() + " " + packet.chunks.get(0).syncClient.address);
debugLog("received catchup: " + packet.chunks.size() + " " + packet.chunks.get(0).syncClient.syncAddress);
dimensionState.addCatchupChunks(packet.chunks);
}

Expand All @@ -269,9 +277,9 @@ public void requestCatchupData(List<CatchupChunk> chunks) {
}

debugLog("requesting more catchup: " + chunks.size());
var byServer = new HashMap<String, List<CatchupChunk>>();
var byServer = new HashMap<SyncAddress, List<CatchupChunk>>();
for (CatchupChunk chunk : chunks) {
var list = byServer.computeIfAbsent(chunk.syncClient.address, (a) -> new ArrayList<>());
var list = byServer.computeIfAbsent(chunk.syncClient.syncAddress, (a) -> new ArrayList<>());
list.add(chunk);
}
for (List<CatchupChunk> chunksForServer : byServer.values()) {
Expand All @@ -283,7 +291,7 @@ public void requestCatchupData(List<CatchupChunk> chunks) {
public static void debugLog(String msg) {
// we could also make use of slf4j's debug() but I don't know how to reconfigure that at runtime based on globalConfig
if (modConfig.isShowDebugLog()) {
logger.info(msg);
LOGGER.info(msg);
}
}
}
18 changes: 12 additions & 6 deletions mod/common/src/main/java/gjum/minecraft/mapsync/common/ModGui.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

import com.mojang.blaze3d.vertex.PoseStack;
import gjum.minecraft.mapsync.common.config.ServerConfig;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.TextComponent;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.util.List;

import static gjum.minecraft.mapsync.common.MapSyncMod.getMod;

public class ModGui extends Screen {
Expand Down Expand Up @@ -78,8 +80,12 @@ protected void init() {
public void connectClicked(Button btn) {
try {
if (syncServerAddressField == null) return;
var addresses = List.of(syncServerAddressField.getValue().split("[^-_.:A-Za-z0-9]+"));
serverConfig.setSyncServerAddresses(addresses);
serverConfig.setSyncServerAddresses(
Stream.of(StringUtils.split(syncServerAddressField.getValue(), ","))
.map(String::trim)
.filter(StringUtils::isNotEmpty)
.collect(Collectors.toCollection(ArrayList::new))
);
getMod().shutDownSyncClients();
getMod().getSyncClients();
btn.active = false;
Expand Down Expand Up @@ -117,7 +123,7 @@ public void render(@NotNull PoseStack poseStack, int i, int j, float f) {
for (var client : syncClients) {
int statusColor;
String statusText;
if (client.isEncrypted()) {
if (client.isEstablished()) {
numConnected++;
statusColor = 0x008800;
statusText = "Connected";
Expand All @@ -128,7 +134,7 @@ public void render(@NotNull PoseStack poseStack, int i, int j, float f) {
statusColor = 0xffffff;
statusText = "Connecting...";
}
statusText = client.address + " " + statusText;
statusText = client.syncAddress + " " + statusText;
drawString(poseStack, font, statusText, left, msgY, statusColor);
msgY += 10;
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,13 @@ static void writeResourceKey(
resourceKey.location().toString()
);
}

static void assertNoRemainder(
final @NotNull ByteBuf in
) {
final int remainder = in.readableBytes();
if (remainder > 0) {
throw new IllegalStateException("Found [" + remainder + "] remaining bytes!");
}
}
}

This file was deleted.

Loading
Loading