Compare commits
No commits in common. "non-api" and "v1.5.2-beta" have entirely different histories.
non-api
...
v1.5.2-bet
|
|
@ -3,8 +3,7 @@
|
||||||
This is a Velocity plugin that makes it possible to host a modern Forge server behind a Velocity proxy!
|
This is a Velocity plugin that makes it possible to host a modern Forge server behind a Velocity proxy!
|
||||||
|
|
||||||
Unlike other solutions, this plugin does not require any special modifications to the backend server nor the client. (The player doesn't need to do anything)
|
Unlike other solutions, this plugin does not require any special modifications to the backend server nor the client. (The player doesn't need to do anything)
|
||||||
## Only for 1.13-1.20.1
|
|
||||||
Velocity has now added built-in support for newer mc versions and therefore don't need Ambassador. You might still need PCF mod on the server-side, for more info please visit: https://github.com/adde0109/Proxy-Compatible-Forge
|
|
||||||
## How to get started:
|
## How to get started:
|
||||||
1. Download and install this plugin to your proxy.
|
1. Download and install this plugin to your proxy.
|
||||||
2. After starting the server, configure the plugin it to your liking using the config file found in the folder "Ambassador".
|
2. After starting the server, configure the plugin it to your liking using the config file found in the folder "Ambassador".
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "org.adde0109"
|
group = "org.adde0109"
|
||||||
version = "1.5.3-beta"
|
version = "1.5.2-beta"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ import java.util.Map;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
import com.velocitypowered.proxy.connection.MinecraftConnection;
|
||||||
import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
|
|
||||||
import com.velocitypowered.proxy.network.ConnectionManager;
|
import com.velocitypowered.proxy.network.ConnectionManager;
|
||||||
import com.velocitypowered.proxy.protocol.StateRegistry;
|
import com.velocitypowered.proxy.protocol.StateRegistry;
|
||||||
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
|
import com.velocitypowered.proxy.protocol.packet.DisconnectPacket;
|
||||||
|
|
@ -29,8 +28,6 @@ import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertySeria
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
|
||||||
import org.adde0109.ambassador.velocity.VelocityBackendChannelInitializer;
|
import org.adde0109.ambassador.velocity.VelocityBackendChannelInitializer;
|
||||||
import org.adde0109.ambassador.velocity.VelocityServerChannelInitializer;
|
import org.adde0109.ambassador.velocity.VelocityServerChannelInitializer;
|
||||||
import org.adde0109.ambassador.velocity.VelocityEventHandler;
|
import org.adde0109.ambassador.velocity.VelocityEventHandler;
|
||||||
|
|
@ -46,7 +43,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19;
|
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_19;
|
||||||
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
|
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
|
||||||
|
|
||||||
@Plugin(id = "ambassador", name = "Ambassador", version = "1.5.3-beta", authors = {"adde0109"})
|
@Plugin(id = "ambassador", name = "Ambassador", version = "1.5.2-beta", authors = {"adde0109"})
|
||||||
public class Ambassador {
|
public class Ambassador {
|
||||||
|
|
||||||
//Don't forget to update checkCompatibleVersion() when changing this value
|
//Don't forget to update checkCompatibleVersion() when changing this value
|
||||||
|
|
@ -156,16 +153,6 @@ public class Ambassador {
|
||||||
return TEMPORARY_FORCED;
|
return TEMPORARY_FORCED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reconnectSwitchPlayer(ConnectedPlayer player) {
|
|
||||||
TEMPORARY_FORCED.put(player.getUsername(), player.getConnectionInFlight().getServer(),
|
|
||||||
config.getServerSwitchCancellationTime(), TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
MiniMessage mm = MiniMessage.miniMessage();
|
|
||||||
Component parsed = mm.deserialize(config.getKickReconnectMessageString());
|
|
||||||
|
|
||||||
player.disconnect(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initMetrics() {
|
private void initMetrics() {
|
||||||
Metrics metrics = metricsFactory.make(this, 15655);
|
Metrics metrics = metricsFactory.make(this, 15655);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,119 +14,92 @@ import java.nio.file.Path;
|
||||||
|
|
||||||
public class AmbassadorConfig {
|
public class AmbassadorConfig {
|
||||||
|
|
||||||
@Expose
|
@Expose
|
||||||
private int serverSwitchCancellationTime = 30;
|
private int serverSwitchCancellationTime = 30;
|
||||||
|
|
||||||
@Expose
|
@Expose
|
||||||
private boolean silenceWarnings = false;
|
private boolean silenceWarnings = false;
|
||||||
@Expose
|
|
||||||
private boolean bypassRegistryCheck = false;
|
|
||||||
@Expose
|
|
||||||
private boolean bypassModCheck = false;
|
|
||||||
|
|
||||||
@Expose
|
@Expose
|
||||||
private boolean debugMode = false;
|
private boolean bypassRegistryCheck = false;
|
||||||
|
@Expose
|
||||||
|
private boolean bypassModCheck = false;
|
||||||
|
|
||||||
@Expose
|
@Expose
|
||||||
private boolean enableKickReset = false;
|
private boolean debugMode = false;
|
||||||
|
|
||||||
@Expose
|
private AmbassadorConfig(boolean silenceWarnings, boolean bypassRegistryCheck, boolean bypassModCheck, boolean debugMode) {
|
||||||
private String kickReconnectMessageString = "<red>Please reconnect.</red>";
|
this.silenceWarnings = silenceWarnings;
|
||||||
|
this.bypassRegistryCheck = bypassRegistryCheck;
|
||||||
|
this.bypassModCheck = bypassModCheck;
|
||||||
|
this.debugMode = debugMode;
|
||||||
|
};
|
||||||
|
|
||||||
private AmbassadorConfig(boolean silenceWarnings, boolean bypassRegistryCheck, boolean bypassModCheck,
|
public static AmbassadorConfig read(Path path) throws IOException {
|
||||||
boolean debugMode, boolean enableKickReset, String kickReconnectMessageString) {
|
URL defaultConfigLocation = AmbassadorConfig.class.getClassLoader()
|
||||||
this.silenceWarnings = silenceWarnings;
|
.getResource("default-ambassador.toml");
|
||||||
this.bypassRegistryCheck = bypassRegistryCheck;
|
if (defaultConfigLocation == null) {
|
||||||
this.bypassModCheck = bypassModCheck;
|
throw new RuntimeException("Default configuration file does not exist.");
|
||||||
this.debugMode = debugMode;
|
|
||||||
this.enableKickReset = enableKickReset;
|
|
||||||
this.kickReconnectMessageString = kickReconnectMessageString;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AmbassadorConfig read(Path path) throws IOException {
|
CommentedFileConfig config = CommentedFileConfig.builder(path)
|
||||||
URL defaultConfigLocation = AmbassadorConfig.class.getClassLoader()
|
.defaultData(defaultConfigLocation)
|
||||||
.getResource("default-ambassador.toml");
|
.autosave()
|
||||||
if (defaultConfigLocation == null) {
|
.preserveInsertionOrder()
|
||||||
throw new RuntimeException("Default configuration file does not exist.");
|
.sync()
|
||||||
}
|
.build();
|
||||||
|
config.load();
|
||||||
|
|
||||||
CommentedFileConfig config = CommentedFileConfig.builder(path)
|
double configVersion;
|
||||||
.defaultData(defaultConfigLocation)
|
try {
|
||||||
.autosave()
|
configVersion = Double.parseDouble(config.getOrElse("config-version", "1.0"));
|
||||||
.preserveInsertionOrder()
|
} catch (NumberFormatException e) {
|
||||||
.sync()
|
configVersion = 1.0;
|
||||||
.build();
|
|
||||||
config.load();
|
|
||||||
|
|
||||||
double configVersion;
|
|
||||||
try {
|
|
||||||
configVersion = Double.parseDouble(config.getOrElse("config-version", "1.0"));
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
configVersion = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean silenceWarnings = config.getOrElse("silence-warnings", false);
|
|
||||||
|
|
||||||
int serverSwitchCancellationTime = config.getOrElse("serverRedirectTimeout", 30);
|
|
||||||
|
|
||||||
boolean bypassRegistryCheck = config.getOrElse("bypass-registry-checks", false);
|
|
||||||
|
|
||||||
boolean bypassModCheck = config.getOrElse("bypass-mod-checks", false);
|
|
||||||
|
|
||||||
boolean debugMode = config.getOrElse("debug-mode", false);
|
|
||||||
|
|
||||||
String kickReconnectMessageString = config.getOrElse("disconnect-reset-message",
|
|
||||||
config.getOrElse("reconnect-message", "<red>Please reconnect.</red>"));
|
|
||||||
|
|
||||||
//Upgrade config
|
|
||||||
if (configVersion <= 2.0) {
|
|
||||||
Files.delete(path);
|
|
||||||
config = CommentedFileConfig.builder(path)
|
|
||||||
.defaultData(defaultConfigLocation)
|
|
||||||
.autosave()
|
|
||||||
.preserveInsertionOrder()
|
|
||||||
.sync()
|
|
||||||
.build();
|
|
||||||
config.load();
|
|
||||||
config.set("silence-warnings", silenceWarnings);
|
|
||||||
config.set("serverRedirectTimeout", serverSwitchCancellationTime);
|
|
||||||
config.set("bypass-registry-checks", bypassRegistryCheck);
|
|
||||||
config.set("bypass-mod-checks", bypassModCheck);
|
|
||||||
config.set("debug-mode", debugMode);
|
|
||||||
config.set("reconnect-message", kickReconnectMessageString);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean enableKickReset = config.getOrElse("enable-kick-reset", false);
|
|
||||||
|
|
||||||
return new AmbassadorConfig(silenceWarnings, bypassRegistryCheck, bypassModCheck,
|
|
||||||
debugMode, enableKickReset, kickReconnectMessageString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getServerSwitchCancellationTime() {
|
boolean silenceWarnings = config.getOrElse("silence-warnings", false);
|
||||||
return serverSwitchCancellationTime;
|
|
||||||
|
//Upgrade config
|
||||||
|
if (configVersion <= 1.2) {
|
||||||
|
Files.delete(path);
|
||||||
|
config = CommentedFileConfig.builder(path)
|
||||||
|
.defaultData(defaultConfigLocation)
|
||||||
|
.autosave()
|
||||||
|
.preserveInsertionOrder()
|
||||||
|
.sync()
|
||||||
|
.build();
|
||||||
|
config.load();
|
||||||
|
config.set("silence-warnings", silenceWarnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSilenceWarnings() {
|
int serverSwitchCancellationTime = config.getOrElse("serverRedirectTimeout", 30);
|
||||||
return silenceWarnings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBypassRegistryCheck() {
|
boolean bypassRegistryCheck = config.getOrElse("bypass-registry-checks", false);
|
||||||
return bypassRegistryCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isBypassModCheck() {
|
boolean bypassModCheck = config.getOrElse("bypass-mod-checks", false);
|
||||||
return bypassModCheck;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDebugMode() {
|
boolean debugMode = config.getOrElse("debug-mode", false);
|
||||||
return debugMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnableKickReset() {
|
return new AmbassadorConfig(bypassRegistryCheck, bypassModCheck, silenceWarnings, debugMode);
|
||||||
return enableKickReset;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public String getKickReconnectMessageString() {
|
public int getServerSwitchCancellationTime() {
|
||||||
return kickReconnectMessageString;
|
return serverSwitchCancellationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSilenceWarnings() {
|
||||||
|
return silenceWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBypassRegistryCheck() {
|
||||||
|
return bypassRegistryCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBypassModCheck() {
|
||||||
|
return bypassModCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugMode() {
|
||||||
|
return debugMode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,10 +72,6 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
|
||||||
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
|
VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase();
|
||||||
|
|
||||||
|
|
||||||
if (!player.isActive()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!clientPhase.consideredComplete()) {
|
if (!clientPhase.consideredComplete()) {
|
||||||
//Initial Forge
|
//Initial Forge
|
||||||
if (message instanceof ModListPacket modListPacket) {
|
if (message instanceof ModListPacket modListPacket) {
|
||||||
|
|
@ -96,16 +92,10 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
|
||||||
|
|
||||||
if (clientPhase.forgeHandshake.getModListReplyPacket() == null) {
|
if (clientPhase.forgeHandshake.getModListReplyPacket() == null) {
|
||||||
//We have nothing to respond with during this handshake. Unable to proceed.
|
//We have nothing to respond with during this handshake. Unable to proceed.
|
||||||
if (Ambassador.getInstance().config.isEnableKickReset()) {
|
Ambassador.getInstance().logger.error("Unable for {} to switch servers. " +
|
||||||
//Kick-reset
|
"Vanilla({}) -> Forge({}) switch without reset is not yet supported!", player.getGameProfile().getName(),
|
||||||
Ambassador.getInstance().reconnectSwitchPlayer(player);
|
player.getConnectedServer().getServerInfo().getName(), server.getServerInfo().getName());
|
||||||
} else {
|
server.disconnect();
|
||||||
Ambassador.getInstance().logger.error("Unable for {} to switch servers. Vanilla({}) -> Forge({}) switch " +
|
|
||||||
"without client side mod or kick-reset enabled is not yet supported!",
|
|
||||||
player.getGameProfile().getName(), player.getConnectedServer().getServerInfo().getName(),
|
|
||||||
server.getServerInfo().getName());
|
|
||||||
server.disconnect();
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,9 +124,6 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas
|
||||||
if (Ambassador.getInstance().config.isBypassRegistryCheck() ||
|
if (Ambassador.getInstance().config.isBypassRegistryCheck() ||
|
||||||
clientPhase.forgeHandshake.isCompatible(handshake)) {
|
clientPhase.forgeHandshake.isCompatible(handshake)) {
|
||||||
server.ensureConnected().write(clientPhase.forgeHandshake.getModListReplyPacket());
|
server.ensureConnected().write(clientPhase.forgeHandshake.getModListReplyPacket());
|
||||||
} else if (Ambassador.getInstance().config.isEnableKickReset()) {
|
|
||||||
//Kick-reset
|
|
||||||
Ambassador.getInstance().reconnectSwitchPlayer(player);
|
|
||||||
} else {
|
} else {
|
||||||
Ambassador.getInstance().logger.error("Unable to switch due to the registries of " +
|
Ambassador.getInstance().logger.error("Unable to switch due to the registries of " +
|
||||||
server.getServer().getServerInfo().getName() + " being different from the registries of " +
|
server.getServer().getServerInfo().getName() + " being different from the registries of " +
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ import org.adde0109.ambassador.velocity.client.OutboundSuccessHolder;
|
||||||
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
|
import org.adde0109.ambassador.velocity.client.ClientPacketQueue;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase {
|
public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase {
|
||||||
|
|
||||||
|
|
@ -256,8 +255,6 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase
|
||||||
buf.writeBytes((player.getVirtualHost().get().getHostName() + ":"
|
buf.writeBytes((player.getVirtualHost().get().getHostName() + ":"
|
||||||
+ player.getVirtualHost().get().getPort()).getBytes(StandardCharsets.UTF_8));
|
+ player.getVirtualHost().get().getPort()).getBytes(StandardCharsets.UTF_8));
|
||||||
player.getConnection().write(new PluginMessagePacket("srvredirect:red", buf));
|
player.getConnection().write(new PluginMessagePacket("srvredirect:red", buf));
|
||||||
|
|
||||||
Ambassador.getInstance().reconnectSwitchPlayer(player);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Do not change this
|
# Do not change this
|
||||||
config-version = "2.1"
|
config-version = "2.0"
|
||||||
|
|
||||||
# How much time the player has to reconnect before canceling the server switch. (In seconds)
|
# How much time the player has to reconnect before canceling the server switch. (In seconds)
|
||||||
# Only for players with ServerRedirect mod installed. Set to -1 to disable ServerRedirect mod support.
|
# Only for players with ServerRedirect mod installed. Set to -1 to disable ServerRedirect mod support.
|
||||||
|
|
@ -17,13 +17,5 @@ bypass-registry-checks = false
|
||||||
# Warning: This is a safety measure for when bypassRegistryCheck is true. Setting this to also true can cause crashes.
|
# Warning: This is a safety measure for when bypassRegistryCheck is true. Setting this to also true can cause crashes.
|
||||||
bypass-mod-checks = false
|
bypass-mod-checks = false
|
||||||
|
|
||||||
# Only for debug/troubleshooting
|
#Only for debug/troubleshooting
|
||||||
debug-mode = false
|
debug-mode = false
|
||||||
|
|
||||||
# Make the player reconnect when server switching as a last resort if
|
|
||||||
# the player can't reset or switch servers without resetting.
|
|
||||||
enable-kick-reset = false
|
|
||||||
|
|
||||||
# Message to display when player gets kicked due to server switching according to enable-kick-reset.
|
|
||||||
# This input is deserialzied as MiniMessage and support formating according to the MiniMessage format.
|
|
||||||
reconnect-message = "<red>Please reconnect.</red>"
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user