Skip to content

Instantly share code, notes, and snippets.

@gamerchamper
Created April 2, 2026 04:40
Show Gist options
  • Select an option

  • Save gamerchamper/dce40aebca811eb57c956a5d95ee565d to your computer and use it in GitHub Desktop.

Select an option

Save gamerchamper/dce40aebca811eb57c956a5d95ee565d to your computer and use it in GitHub Desktop.
velocity-main
package com.normalsmp.normalSurvivalWorlds;
import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import org.slf4j.Logger;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@Plugin(id = "normalsurvivalworlds", name = "NormalSurvivalWorlds", version = "3.0")
public class NormalSurvivalWorlds {
public static final MinecraftChannelIdentifier CHANNEL =
MinecraftChannelIdentifier.from("nsw:playerdata");
private final ProxyServer server;
private final Logger logger;
private final boolean DEBUG = true;
// 🔥 THIS IS THE MAGIC NUMBER (size of server1 border * 2)
private static final double SHIFT = 16000;
private final Map<UUID, PlayerData> playerDataMap = new ConcurrentHashMap<>();
private final Map<UUID, Long> lastTransfer = new ConcurrentHashMap<>();
@Inject
public NormalSurvivalWorlds(ProxyServer server, Logger logger) {
this.server = server;
this.logger = logger;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
server.getChannelRegistrar().register(CHANNEL);
logger.info("[NSW] Velocity initialized.");
}
@Subscribe
public void onPluginMessage(PluginMessageEvent event) {
if (!event.getIdentifier().equals(CHANNEL)) return;
ByteArrayDataInput in = ByteStreams.newDataInput(event.getData());
try {
String sub = in.readUTF();
// =========================
// 📥 RECEIVE PLAYER DATA
// =========================
if (sub.equals("DATA")) {
UUID uuid = UUID.fromString(in.readUTF());
String username = in.readUTF();
String serverName = in.readUTF();
String world = in.readUTF();
double x = in.readDouble();
double y = in.readDouble();
double z = in.readDouble();
float yaw = in.readFloat();
float pitch = in.readFloat();
boolean borderHit = in.readBoolean();
String targetServerName = in.readUTF();
String edge = in.readUTF();
// 🔥 APPLY OFFSET IF CROSSING
double newX = x;
double newZ = z;
if (borderHit) {
switch (edge) {
case "EAST" -> newX = x - SHIFT;
case "WEST" -> newX = x + SHIFT;
case "SOUTH" -> newZ = z - SHIFT;
case "NORTH" -> newZ = z + SHIFT;
}
if (DEBUG) {
logger.info("[OFFSET] {} {} -> X:{} Z:{}",
username, edge,
round(newX), round(newZ));
}
}
PlayerData data = new PlayerData(
uuid, username, serverName, world,
newX, y, newZ, yaw, pitch, edge
);
playerDataMap.put(uuid, data);
if (borderHit) {
long now = System.currentTimeMillis();
long last = lastTransfer.getOrDefault(uuid, 0L);
if (now - last < 2000) {
if (DEBUG) logger.info("[SKIP] Cooldown {}", username);
return;
}
lastTransfer.put(uuid, now);
server.getPlayer(uuid).ifPresent(player -> {
server.getServer(targetServerName).ifPresent(target -> {
logger.info("[TRANSFER] {} -> {} EDGE:{}",
username, targetServerName, edge);
player.createConnectionRequest(target).fireAndForget();
});
});
}
}
// =========================
// 📤 HANDLE REQUEST
// =========================
if (sub.equals("REQUEST")) {
UUID uuid = UUID.fromString(in.readUTF());
PlayerData data = playerDataMap.get(uuid);
if (data == null) {
logger.warn("[REQUEST] No data for {}", uuid);
return;
}
server.getPlayer(uuid).ifPresent(player -> {
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeUTF("RESPONSE");
out.writeDouble(data.getX());
out.writeDouble(data.getY());
out.writeDouble(data.getZ());
out.writeFloat(data.getYaw());
out.writeFloat(data.getPitch());
player.sendPluginMessage(CHANNEL, out.toByteArray());
if (DEBUG) {
logger.info("[RESPONSE] {} -> X:{} Z:{}",
data.getUsername(),
round(data.getX()),
round(data.getZ()));
}
});
}
} catch (Exception e) {
logger.error("[ERROR] Plugin message failed", e);
}
}
private double round(double val) {
return Math.round(val * 100.0) / 100.0;
}
}
package com.normalsmp.normalSurvivalWorlds;
import java.util.UUID;
public class PlayerData {
private final UUID uuid;
private final String username;
private final String server;
private final String world;
private final double x, y, z;
private final float yaw, pitch;
private final String edge;
public PlayerData(UUID uuid, String username, String server, String world,
double x, double y, double z,
float yaw, float pitch,
String edge) {
this.uuid = uuid;
this.username = username;
this.server = server;
this.world = world;
this.x = x;
this.y = y;
this.z = z;
this.yaw = yaw;
this.pitch = pitch;
this.edge = edge;
}
public String getEdge() { return edge; }
public UUID getUuid() { return uuid; }
public String getUsername() { return username; }
public String getServer() { return server; }
public String getWorld() { return world; }
public double getX() { return x; }
public double getY() { return y; }
public double getZ() { return z; }
public float getYaw() { return yaw; }
public float getPitch() { return pitch; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment