Created
April 2, 2026 04:41
-
-
Save gamerchamper/ab735970609f7e1f344e2989f272be1a to your computer and use it in GitHub Desktop.
main-paper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package com.normalsmp.normalSurvivalWorldsPaper; | |
| import com.google.common.io.ByteArrayDataInput; | |
| import com.google.common.io.ByteArrayDataOutput; | |
| import com.google.common.io.ByteStreams; | |
| import net.kyori.adventure.text.Component; | |
| import org.bukkit.*; | |
| import org.bukkit.entity.Player; | |
| import org.bukkit.event.*; | |
| import org.bukkit.event.player.PlayerJoinEvent; | |
| import org.bukkit.plugin.java.JavaPlugin; | |
| import org.bukkit.scheduler.BukkitRunnable; | |
| public final class NormalSurvivalWorldsPaper extends JavaPlugin implements Listener { | |
| private static final String CHANNEL = "nsw:playerdata"; | |
| private String serverName; | |
| private String targetServer; | |
| private double minX, maxX, minZ, maxZ; | |
| private double buffer; | |
| private final boolean DEBUG = true; | |
| @Override | |
| public void onEnable() { | |
| saveDefaultConfig(); | |
| serverName = getConfig().getString("server-name"); | |
| targetServer = getConfig().getString("target-server"); | |
| minX = getConfig().getDouble("border.min-x"); | |
| maxX = getConfig().getDouble("border.max-x"); | |
| minZ = getConfig().getDouble("border.min-z"); | |
| maxZ = getConfig().getDouble("border.max-z"); | |
| buffer = getConfig().getDouble("border.buffer", 2); | |
| getServer().getMessenger().registerOutgoingPluginChannel(this, CHANNEL); | |
| getServer().getMessenger().registerIncomingPluginChannel(this, CHANNEL, this::onMessage); | |
| Bukkit.getPluginManager().registerEvents(this, this); | |
| // 🔁 Constant sync loop | |
| new BukkitRunnable() { | |
| @Override | |
| public void run() { | |
| for (Player p : Bukkit.getOnlinePlayers()) { | |
| sendData(p); | |
| } | |
| } | |
| }.runTaskTimer(this, 10L, 10L); | |
| getLogger().info("[NSW] Paper initialized."); | |
| getLogger().info("[NSW] Server: " + serverName + " -> Target: " + targetServer); | |
| getLogger().info("[NSW] Border X: " + minX + " → " + maxX + " | Z: " + minZ + " → " + maxZ); | |
| } | |
| // ========================= | |
| // 📥 RECEIVE RESPONSE | |
| // ========================= | |
| private void onMessage(String channel, Player player, byte[] message) { | |
| ByteArrayDataInput in = ByteStreams.newDataInput(message); | |
| try { | |
| String sub = in.readUTF(); | |
| if (sub.equals("RESPONSE")) { | |
| double x = in.readDouble(); | |
| double y = in.readDouble(); | |
| double z = in.readDouble(); | |
| float yaw = in.readFloat(); | |
| float pitch = in.readFloat(); | |
| Location loc = new Location(player.getWorld(), x, y, z, yaw, pitch); | |
| player.teleport(loc); | |
| if (DEBUG) { | |
| getLogger().info("[SYNCED] " + player.getName() + | |
| " -> X:" + round(x) + " Y:" + round(y) + " Z:" + round(z)); | |
| } | |
| } | |
| } catch (Exception e) { | |
| getLogger().severe("[ERROR] Failed to read incoming message"); | |
| e.printStackTrace(); | |
| } | |
| } | |
| // ========================= | |
| // 📤 REQUEST DATA ON JOIN | |
| // ========================= | |
| @EventHandler | |
| public void onJoin(PlayerJoinEvent e) { | |
| Player p = e.getPlayer(); | |
| Bukkit.getScheduler().runTaskLater(this, () -> { | |
| requestData(p); | |
| }, 20L); | |
| } | |
| private void requestData(Player player) { | |
| ByteArrayDataOutput out = ByteStreams.newDataOutput(); | |
| out.writeUTF("REQUEST"); | |
| out.writeUTF(player.getUniqueId().toString()); | |
| player.sendPluginMessage(this, CHANNEL, out.toByteArray()); | |
| if (DEBUG) { | |
| getLogger().info("[REQUEST] Sent for " + player.getName()); | |
| } | |
| } | |
| // ========================= | |
| // 📤 SEND DATA TO VELOCITY | |
| // ========================= | |
| private void sendData(Player player) { | |
| Location loc = player.getLocation(); | |
| double x = loc.getX(); | |
| double y = loc.getY(); | |
| double z = loc.getZ(); | |
| String edge = detectEdge(x, z); | |
| String nearEdge = detectNearEdge(x, z); | |
| double distance = distanceToBorder(x, z); | |
| boolean borderHit = !edge.equals("NONE"); | |
| // 🔔 Actionbar warning | |
| if (!nearEdge.equals("NONE") && distance <= 10 && distance > 0) { | |
| player.sendActionBar(Component.text("§cBorder in " + (int) distance + " blocks!")); | |
| } | |
| ByteArrayDataOutput out = ByteStreams.newDataOutput(); | |
| out.writeUTF("DATA"); | |
| out.writeUTF(player.getUniqueId().toString()); | |
| out.writeUTF(player.getName()); | |
| out.writeUTF(serverName); | |
| out.writeUTF(player.getWorld().getName()); | |
| out.writeDouble(x); | |
| out.writeDouble(y); | |
| out.writeDouble(z); | |
| out.writeFloat(loc.getYaw()); | |
| out.writeFloat(loc.getPitch()); | |
| out.writeBoolean(borderHit); | |
| out.writeUTF(targetServer); | |
| out.writeUTF(edge); | |
| player.sendPluginMessage(this, CHANNEL, out.toByteArray()); | |
| if (DEBUG && borderHit) { | |
| getLogger().info("[BORDER HIT] " + player.getName() + | |
| " EDGE:" + edge + | |
| " X:" + round(x) + | |
| " Z:" + round(z)); | |
| } | |
| } | |
| // ========================= | |
| // EDGE LOGIC (BOX) | |
| // ========================= | |
| private String detectEdge(double x, double z) { | |
| if (x >= maxX) return "EAST"; | |
| if (x <= minX) return "WEST"; | |
| if (z >= maxZ) return "SOUTH"; | |
| if (z <= minZ) return "NORTH"; | |
| return "NONE"; | |
| } | |
| private String detectNearEdge(double x, double z) { | |
| if (x >= maxX - buffer) return "EAST"; | |
| if (x <= minX + buffer) return "WEST"; | |
| if (z >= maxZ - buffer) return "SOUTH"; | |
| if (z <= minZ + buffer) return "NORTH"; | |
| return "NONE"; | |
| } | |
| private double distanceToBorder(double x, double z) { | |
| double dx = Math.min(Math.abs(maxX - x), Math.abs(x - minX)); | |
| double dz = Math.min(Math.abs(maxZ - z), Math.abs(z - minZ)); | |
| return Math.min(dx, dz); | |
| } | |
| private double round(double val) { | |
| return Math.round(val * 100.0) / 100.0; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment