<1.0.2> Fixed various handshake issues with EaglerXVelocity
This commit is contained in:
parent
b5fd4cc2aa
commit
79d0e232f6
Binary file not shown.
|
@ -23,7 +23,7 @@ public class EaglerXVelocityVersion {
|
||||||
public static final String PLUGIN_ID = "eaglerxvelocity";
|
public static final String PLUGIN_ID = "eaglerxvelocity";
|
||||||
public static final String NAME = "EaglercraftXVelocity";
|
public static final String NAME = "EaglercraftXVelocity";
|
||||||
public static final String DESCRIPTION = "Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks";
|
public static final String DESCRIPTION = "Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks";
|
||||||
public static final String VERSION = "1.0.1";
|
public static final String VERSION = "1.0.2";
|
||||||
public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" };
|
public static final String[] AUTHORS = new String[] { "lax1dude", "ayunami2000" };
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler;
|
||||||
import io.netty.util.ReferenceCountUtil;
|
import io.netty.util.ReferenceCountUtil;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import net.kyori.adventure.translation.GlobalTranslator;
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity;
|
import net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity;
|
||||||
|
@ -101,6 +102,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
private static final Constructor<InitialInboundConnection> stupidConstructor;
|
private static final Constructor<InitialInboundConnection> stupidConstructor;
|
||||||
private static final Field remoteAddressField;
|
private static final Field remoteAddressField;
|
||||||
|
private static final Field stateField;
|
||||||
|
private static final Field protocolVersionField;
|
||||||
private static final Constructor<LoginInboundConnection> stupid2Constructor;
|
private static final Constructor<LoginInboundConnection> stupid2Constructor;
|
||||||
private static final Method loginEventFiredMethod;
|
private static final Method loginEventFiredMethod;
|
||||||
private static final Constructor<ConnectedPlayer> stupid3Constructor;
|
private static final Constructor<ConnectedPlayer> stupid3Constructor;
|
||||||
|
@ -113,6 +116,10 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
stupidConstructor.setAccessible(true);
|
stupidConstructor.setAccessible(true);
|
||||||
remoteAddressField = MinecraftConnection.class.getDeclaredField("remoteAddress");
|
remoteAddressField = MinecraftConnection.class.getDeclaredField("remoteAddress");
|
||||||
remoteAddressField.setAccessible(true);
|
remoteAddressField.setAccessible(true);
|
||||||
|
stateField = MinecraftConnection.class.getDeclaredField("state");
|
||||||
|
stateField.setAccessible(true);
|
||||||
|
protocolVersionField = MinecraftConnection.class.getDeclaredField("protocolVersion");
|
||||||
|
protocolVersionField.setAccessible(true);
|
||||||
stupid2Constructor = LoginInboundConnection.class.getDeclaredConstructor(InitialInboundConnection.class);
|
stupid2Constructor = LoginInboundConnection.class.getDeclaredConstructor(InitialInboundConnection.class);
|
||||||
stupid2Constructor.setAccessible(true);
|
stupid2Constructor.setAccessible(true);
|
||||||
loginEventFiredMethod = LoginInboundConnection.class.getDeclaredMethod("loginEventFired", Runnable.class);
|
loginEventFiredMethod = LoginInboundConnection.class.getDeclaredMethod("loginEventFired", Runnable.class);
|
||||||
|
@ -212,7 +219,6 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
if (i >= conf.getMaxPlayer()) {
|
if (i >= conf.getMaxPlayer()) {
|
||||||
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full")
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Proxy is full")
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
connectionClosed = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +246,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(loginRateLimit == RateLimitStatus.LOCKED_OUT) {
|
if(loginRateLimit == RateLimitStatus.LOCKED_OUT) {
|
||||||
ctx.close();
|
|
||||||
connectionClosed = true;
|
connectionClosed = true;
|
||||||
|
ctx.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,7 +257,6 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
? HandshakePacketTypes.SERVER_ERROR_RATELIMIT_LOCKED
|
? HandshakePacketTypes.SERVER_ERROR_RATELIMIT_LOCKED
|
||||||
: HandshakePacketTypes.SERVER_ERROR_RATELIMIT_BLOCKED,
|
: HandshakePacketTypes.SERVER_ERROR_RATELIMIT_BLOCKED,
|
||||||
"Too many logins!").addListener(ChannelFutureListener.CLOSE);
|
"Too many logins!").addListener(ChannelFutureListener.CLOSE);
|
||||||
connectionClosed = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +297,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
return;
|
return;
|
||||||
}else if(buffer.readUnsignedByte() != minecraftProtocolVersion) {
|
}else if(buffer.readUnsignedByte() != minecraftProtocolVersion) {
|
||||||
clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE;
|
clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE;
|
||||||
|
connectionClosed = true;
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH);
|
buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH);
|
||||||
buf.writeByte(1);
|
buf.writeByte(1);
|
||||||
|
@ -365,6 +371,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
if(versMisMatch) {
|
if(versMisMatch) {
|
||||||
clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE;
|
clientLoginState = HandshakePacketTypes.STATE_CLIENT_COMPLETE;
|
||||||
|
connectionClosed = true;
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH);
|
buf.writeByte(HandshakePacketTypes.PROTOCOL_VERSION_MISMATCH);
|
||||||
|
|
||||||
|
@ -610,7 +617,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
final VelocityServer bungee = EaglerXVelocity.proxy();
|
final VelocityServer bungee = EaglerXVelocity.proxy();
|
||||||
String usernameStr = clientUsername.toString();
|
String usernameStr = clientUsername.toString();
|
||||||
if (bungee.getPlayer(usernameStr).isPresent()) {
|
if (bungee.getPlayer(usernameStr).isPresent()) {
|
||||||
sendLoginDenied(ctx, LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy", NamedTextColor.RED), Locale.getDefault())))
|
sendLoginDenied(ctx, LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault())))
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -777,7 +784,7 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
final String usernameStr = clientUsername.toString();
|
final String usernameStr = clientUsername.toString();
|
||||||
if (bungee.getPlayer(usernameStr).isPresent()) {
|
if (bungee.getPlayer(usernameStr).isPresent()) {
|
||||||
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy", NamedTextColor.RED), Locale.getDefault())))
|
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault())))
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -790,9 +797,8 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
ProtocolVersion protocolVers = ProtocolVersion.getProtocolVersion(gameProtocolVersion);
|
ProtocolVersion protocolVers = ProtocolVersion.getProtocolVersion(gameProtocolVersion);
|
||||||
if(!protocolVers.isSupported()) {
|
if(!protocolVers.isSupported()) {
|
||||||
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
//TODO: localize somehow
|
||||||
"outdated_client")
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE, "Outdated Client!").addListener(ChannelFutureListener.CLOSE);
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,29 +810,12 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
fakeHandshake.setServerAddress(hostName);
|
fakeHandshake.setServerAddress(hostName);
|
||||||
fakeHandshake.setPort(localAddress.getPort());
|
fakeHandshake.setPort(localAddress.getPort());
|
||||||
|
|
||||||
ChannelPipeline pp = ctx.channel().pipeline();
|
final MinecraftConnection con = new MinecraftConnection(ctx.channel(), bungee);
|
||||||
|
|
||||||
pp.remove(HttpWebSocketHandler.this);
|
|
||||||
|
|
||||||
pp
|
|
||||||
.addLast("EaglerMinecraftByteBufDecoder", new EaglerMinecraftDecoder())
|
|
||||||
.addLast(LEGACY_PING_DECODER, new LegacyPingDecoder())
|
|
||||||
.addLast(READ_TIMEOUT,
|
|
||||||
new ReadTimeoutHandler(bungee.getConfiguration().getReadTimeout(),
|
|
||||||
TimeUnit.MILLISECONDS))
|
|
||||||
.addLast("EaglerMinecraftByteBufEncoder", new EaglerMinecraftEncoder())
|
|
||||||
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
|
|
||||||
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolUtils.Direction.SERVERBOUND))
|
|
||||||
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolUtils.Direction.CLIENTBOUND));
|
|
||||||
|
|
||||||
MinecraftConnection con = new MinecraftConnection(ctx.channel(), bungee);
|
|
||||||
|
|
||||||
pp.addLast(Connections.HANDLER, con);
|
|
||||||
|
|
||||||
con.setProtocolVersion(protocolVers);
|
|
||||||
con.setState(StateRegistry.LOGIN);
|
|
||||||
try {
|
try {
|
||||||
remoteAddressField.set(con, baseAddress);
|
remoteAddressField.set(con, baseAddress);
|
||||||
|
stateField.set(con, StateRegistry.LOGIN);
|
||||||
|
protocolVersionField.set(con, protocolVers);
|
||||||
} catch (IllegalAccessException e) {
|
} catch (IllegalAccessException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
@ -835,13 +824,14 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
EaglerUpdateConfig updateconf = eaglerConf.getUpdateConfig();
|
EaglerUpdateConfig updateconf = eaglerConf.getUpdateConfig();
|
||||||
boolean blockUpdate = updateconf.isBlockAllClientUpdates();
|
boolean blockUpdate = updateconf.isBlockAllClientUpdates();
|
||||||
EaglerPlayerData.ClientCertificateHolder cert = null;
|
EaglerPlayerData.ClientCertificateHolder mycert = null;
|
||||||
if(!blockUpdate && !updateconf.isDiscardLoginPacketCerts()) {
|
if(!blockUpdate && !updateconf.isDiscardLoginPacketCerts()) {
|
||||||
byte[] b = profileData.get("update_cert_v1");
|
byte[] b = profileData.get("update_cert_v1");
|
||||||
if(b != null && b.length < 32759) {
|
if(b != null && b.length < 32759) {
|
||||||
EaglerUpdateSvc.sendCertificateToPlayers(EaglerUpdateSvc.tryMakeHolder(b));
|
EaglerUpdateSvc.sendCertificateToPlayers(mycert = EaglerUpdateSvc.tryMakeHolder(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final EaglerPlayerData.ClientCertificateHolder cert = mycert;
|
||||||
|
|
||||||
InitialInboundConnection inboundCon;
|
InitialInboundConnection inboundCon;
|
||||||
try {
|
try {
|
||||||
|
@ -851,18 +841,17 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!bungee.getIpAttemptLimiter().attempt(baseAddress.getAddress())) {
|
if (!bungee.getIpAttemptLimiter().attempt(baseAddress.getAddress())) {
|
||||||
con.setState(StateRegistry.LOGIN);
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
inboundCon.disconnectQuietly(Component.translatable("velocity.error.logging-in-too-fast"));
|
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.logging-in-too-fast", NamedTextColor.RED), Locale.getDefault())))
|
||||||
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
con.setState(StateRegistry.LOGIN);
|
|
||||||
|
|
||||||
if (bungee.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
if (bungee.getConfiguration().getPlayerInfoForwardingMode() == PlayerInfoForwarding.MODERN
|
||||||
&& protocolVers.lessThan(ProtocolVersion.MINECRAFT_1_13)) {
|
&& protocolVers.lessThan(ProtocolVersion.MINECRAFT_1_13)) {
|
||||||
con.setState(StateRegistry.LOGIN);
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
inboundCon.disconnectQuietly(
|
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.modern-forwarding-needs-new-client", NamedTextColor.RED), Locale.getDefault())))
|
||||||
Component.translatable("velocity.error.modern-forwarding-needs-new-client"));
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,7 +872,9 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
PreLoginEvent.PreLoginComponentResult result = event1.getResult();
|
PreLoginEvent.PreLoginComponentResult result = event1.getResult();
|
||||||
Optional<Component> disconnectReason = result.getReasonComponent();
|
Optional<Component> disconnectReason = result.getReasonComponent();
|
||||||
if (disconnectReason.isPresent()) {
|
if (disconnectReason.isPresent()) {
|
||||||
lic.disconnect(disconnectReason.get());
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
|
JSONComponentSerializer.json().serialize(GlobalTranslator.render(disconnectReason.get(), Locale.getDefault())))
|
||||||
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -907,104 +898,6 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
} else {
|
} else {
|
||||||
GameProfile gp = profileEvent.getGameProfile();
|
GameProfile gp = profileEvent.getGameProfile();
|
||||||
|
|
||||||
boolean doRegisterSkins = true;
|
|
||||||
|
|
||||||
EaglercraftRegisterSkinEvent registerSkinEvent = bungee.getEventManager().fire(new EaglercraftRegisterSkinEvent(usernameStr, clientUUID)).join();
|
|
||||||
|
|
||||||
Property prop = registerSkinEvent.getForceUseMojangProfileProperty();
|
|
||||||
boolean useExistingProp = registerSkinEvent.getForceUseLoginResultObjectTextures();
|
|
||||||
if(prop != null) {
|
|
||||||
texturesOverrideProperty = prop;
|
|
||||||
overrideEaglerToVanillaSkins = true;
|
|
||||||
}else {
|
|
||||||
if(useExistingProp) {
|
|
||||||
overrideEaglerToVanillaSkins = true;
|
|
||||||
}else {
|
|
||||||
byte[] custom = registerSkinEvent.getForceSetUseCustomPacket();
|
|
||||||
if(custom != null) {
|
|
||||||
profileData.put("skin_v1", custom);
|
|
||||||
overrideEaglerToVanillaSkins = false;
|
|
||||||
}else {
|
|
||||||
String customUrl = registerSkinEvent.getForceSetUseURL();
|
|
||||||
if(customUrl != null) {
|
|
||||||
EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(customUrl, gp.getId());
|
|
||||||
doRegisterSkins = false;
|
|
||||||
overrideEaglerToVanillaSkins = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(texturesOverrideProperty != null) {
|
|
||||||
gp = gp.addProperties(Arrays.asList(texturesOverrideProperty, EaglerVelocityConfig.isEaglerProperty));
|
|
||||||
}else {
|
|
||||||
if(!useExistingProp) {
|
|
||||||
String vanillaSkin = eaglerConf.getEaglerPlayersVanillaSkin();
|
|
||||||
if(vanillaSkin != null) {
|
|
||||||
gp = gp.addProperties(Arrays.asList(eaglerConf.getEaglerPlayersVanillaSkinProperties()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(overrideEaglerToVanillaSkins) {
|
|
||||||
List<Property> props = gp.getProperties();
|
|
||||||
if(props != null) {
|
|
||||||
for(int i = 0; i < props.size(); ++i) {
|
|
||||||
if("textures".equals(props.get(i).getName())) {
|
|
||||||
try {
|
|
||||||
String jsonStr = SkinPackets.bytesToAscii(Base64.getDecoder().decode(props.get(i).getValue()));
|
|
||||||
JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject();
|
|
||||||
JsonObject skinObj = json.getAsJsonObject("SKIN");
|
|
||||||
if(skinObj != null) {
|
|
||||||
JsonElement url = json.get("url");
|
|
||||||
if(url != null) {
|
|
||||||
String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
|
|
||||||
EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(urlStr, gp.getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doRegisterSkins = false;
|
|
||||||
}catch(Throwable t) {
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(doRegisterSkins) {
|
|
||||||
if(profileData.containsKey("skin_v1")) {
|
|
||||||
try {
|
|
||||||
SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v1"),
|
|
||||||
EaglerXVelocity.getEagler().getSkinService());
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService());
|
|
||||||
EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid skin packet: " + ex.toString());
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EaglercraftRegisterCapeEvent registerCapeEvent = bungee.getEventManager().fire(new EaglercraftRegisterCapeEvent(usernameStr, clientUUID)).join();
|
|
||||||
|
|
||||||
byte[] forceCape = registerCapeEvent.getForceSetUseCustomPacket();
|
|
||||||
if(forceCape != null) {
|
|
||||||
profileData.put("cape_v1", forceCape);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(profileData.containsKey("cape_v1")) {
|
|
||||||
try {
|
|
||||||
CapePackets.registerEaglerPlayer(clientUUID, profileData.get("cape_v1"),
|
|
||||||
EaglerXVelocity.getEagler().getCapeService());
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService());
|
|
||||||
EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid cape packet: " + ex.toString());
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(eaglerConf.getEnableIsEaglerPlayerProperty()) {
|
if(eaglerConf.getEnableIsEaglerPlayerProperty()) {
|
||||||
gp = gp.addProperty(EaglerVelocityConfig.isEaglerProperty);
|
gp = gp.addProperty(EaglerVelocityConfig.isEaglerProperty);
|
||||||
}
|
}
|
||||||
|
@ -1015,14 +908,131 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
con.setAssociation(player);
|
||||||
|
|
||||||
if (!bungee.canRegisterConnection(player)) {
|
if (!bungee.canRegisterConnection(player)) {
|
||||||
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy", NamedTextColor.RED), true);
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
|
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault())))
|
||||||
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
} else {
|
} else {
|
||||||
|
boolean doRegisterSkins = true;
|
||||||
|
|
||||||
|
EaglercraftRegisterSkinEvent registerSkinEvent = bungee.getEventManager().fire(new EaglercraftRegisterSkinEvent(usernameStr, clientUUID)).join();
|
||||||
|
|
||||||
|
Property prop = registerSkinEvent.getForceUseMojangProfileProperty();
|
||||||
|
boolean useExistingProp = registerSkinEvent.getForceUseLoginResultObjectTextures();
|
||||||
|
if(prop != null) {
|
||||||
|
texturesOverrideProperty = prop;
|
||||||
|
overrideEaglerToVanillaSkins = true;
|
||||||
|
}else {
|
||||||
|
if(useExistingProp) {
|
||||||
|
overrideEaglerToVanillaSkins = true;
|
||||||
|
}else {
|
||||||
|
byte[] custom = registerSkinEvent.getForceSetUseCustomPacket();
|
||||||
|
if(custom != null) {
|
||||||
|
profileData.put("skin_v1", custom);
|
||||||
|
overrideEaglerToVanillaSkins = false;
|
||||||
|
}else {
|
||||||
|
String customUrl = registerSkinEvent.getForceSetUseURL();
|
||||||
|
if(customUrl != null) {
|
||||||
|
EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(customUrl, gp.getId());
|
||||||
|
doRegisterSkins = false;
|
||||||
|
overrideEaglerToVanillaSkins = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(texturesOverrideProperty != null) {
|
||||||
|
gp = gp.addProperties(Arrays.asList(texturesOverrideProperty, EaglerVelocityConfig.isEaglerProperty));
|
||||||
|
}else {
|
||||||
|
if(!useExistingProp) {
|
||||||
|
String vanillaSkin = eaglerConf.getEaglerPlayersVanillaSkin();
|
||||||
|
if(vanillaSkin != null) {
|
||||||
|
gp = gp.addProperties(Arrays.asList(eaglerConf.getEaglerPlayersVanillaSkinProperties()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(overrideEaglerToVanillaSkins) {
|
||||||
|
List<Property> props = gp.getProperties();
|
||||||
|
if(props != null) {
|
||||||
|
for(int i = 0; i < props.size(); ++i) {
|
||||||
|
if("textures".equals(props.get(i).getName())) {
|
||||||
|
try {
|
||||||
|
String jsonStr = SkinPackets.bytesToAscii(Base64.getDecoder().decode(props.get(i).getValue()));
|
||||||
|
JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject();
|
||||||
|
JsonObject skinObj = json.getAsJsonObject("SKIN");
|
||||||
|
if(skinObj != null) {
|
||||||
|
JsonElement url = json.get("url");
|
||||||
|
if(url != null) {
|
||||||
|
String urlStr = SkinService.sanitizeTextureURL(url.getAsString());
|
||||||
|
EaglerXVelocity.getEagler().getSkinService().registerTextureToPlayerAssociation(urlStr, gp.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doRegisterSkins = false;
|
||||||
|
}catch(Throwable t) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doRegisterSkins) {
|
||||||
|
if(profileData.containsKey("skin_v1")) {
|
||||||
|
try {
|
||||||
|
SkinPackets.registerEaglerPlayer(clientUUID, profileData.get("skin_v1"),
|
||||||
|
EaglerXVelocity.getEagler().getSkinService());
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService());
|
||||||
|
EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid skin packet: " + ex.toString());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
SkinPackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getSkinService());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglercraftRegisterCapeEvent registerCapeEvent = bungee.getEventManager().fire(new EaglercraftRegisterCapeEvent(usernameStr, clientUUID)).join();
|
||||||
|
|
||||||
|
byte[] forceCape = registerCapeEvent.getForceSetUseCustomPacket();
|
||||||
|
if(forceCape != null) {
|
||||||
|
profileData.put("cape_v1", forceCape);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(profileData.containsKey("cape_v1")) {
|
||||||
|
try {
|
||||||
|
CapePackets.registerEaglerPlayer(clientUUID, profileData.get("cape_v1"),
|
||||||
|
EaglerXVelocity.getEagler().getCapeService());
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService());
|
||||||
|
EaglerXVelocity.logger().info("[" + ctx.channel().remoteAddress() + "]: Invalid cape packet: " + ex.toString());
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
CapePackets.registerEaglerPlayerFallback(clientUUID, EaglerXVelocity.getEagler().getCapeService());
|
||||||
|
}
|
||||||
|
|
||||||
EaglerXVelocity.logger().info("{} has connected", player);
|
EaglerXVelocity.logger().info("{} has connected", player);
|
||||||
if(conf.getEnableVoiceChat()) {
|
if(conf.getEnableVoiceChat()) {
|
||||||
EaglerXVelocity.getEagler().getVoiceService().handlePlayerLoggedIn(player);
|
EaglerXVelocity.getEagler().getVoiceService().handlePlayerLoggedIn(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EaglerPlayerData epd = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().eaglerData = new EaglerPlayerData(conf, ctx.channel().attr(EaglerPipeline.ORIGIN).get(), cert);
|
||||||
|
if(!blockUpdate) {
|
||||||
|
List<EaglerPlayerData.ClientCertificateHolder> set = EaglerUpdateSvc.getCertList();
|
||||||
|
synchronized(set) {
|
||||||
|
epd.certificatesToSend.addAll(set);
|
||||||
|
}
|
||||||
|
for (Player p : bungee.getAllPlayers()) {
|
||||||
|
EaglerPlayerData ppp = EaglerPipeline.getEaglerHandle(p);
|
||||||
|
if(ppp != null && ppp.clientCertificate != null && ppp.clientCertificate != cert) {
|
||||||
|
epd.certificatesToSend.add(ppp.clientCertificate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PermissionProvider prov;
|
PermissionProvider prov;
|
||||||
try {
|
try {
|
||||||
prov = (PermissionProvider) defaultPermissionsField.get(null);
|
prov = (PermissionProvider) defaultPermissionsField.get(null);
|
||||||
|
@ -1041,43 +1051,53 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con.setAssociation(player);
|
|
||||||
EaglerPlayerData epd = ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().eaglerData = new EaglerPlayerData(conf, ctx.channel().attr(EaglerPipeline.ORIGIN).get(), cert);
|
|
||||||
if(!blockUpdate) {
|
|
||||||
List<EaglerPlayerData.ClientCertificateHolder> set = EaglerUpdateSvc.getCertList();
|
|
||||||
synchronized(set) {
|
|
||||||
epd.certificatesToSend.addAll(set);
|
|
||||||
}
|
|
||||||
for (Player p : bungee.getAllPlayers()) {
|
|
||||||
EaglerPlayerData ppp = EaglerPipeline.getEaglerHandle(p);
|
|
||||||
if(ppp != null && ppp.clientCertificate != null && ppp.clientCertificate != cert) {
|
|
||||||
epd.certificatesToSend.add(ppp.clientCertificate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bungee.getEventManager().fire(new LoginEvent(player)).thenAcceptAsync(event3 -> {
|
bungee.getEventManager().fire(new LoginEvent(player)).thenAcceptAsync(event3 -> {
|
||||||
if (con.isClosed()) {
|
if (con.isClosed()) {
|
||||||
// The player was disconnected
|
// The player was disconnected
|
||||||
bungee.getEventManager().fireAndForget(new DisconnectEvent(player,
|
bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CANCELLED_BY_USER_BEFORE_COMPLETE));
|
||||||
DisconnectEvent.LoginStatus.CANCELLED_BY_USER_BEFORE_COMPLETE));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<Component> reason = event3.getResult().getReasonComponent();
|
Optional<Component> reason = event3.getResult().getReasonComponent();
|
||||||
if (reason.isPresent()) {
|
if (reason.isPresent()) {
|
||||||
player.disconnect0(reason.get(), true);
|
bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CANCELLED_BY_PROXY));
|
||||||
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
|
JSONComponentSerializer.json().serialize(GlobalTranslator.render(reason.get(), Locale.getDefault())))
|
||||||
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (!bungee.registerConnection(player)) {
|
if (!bungee.registerConnection(player)) {
|
||||||
player.disconnect0(Component.translatable("velocity.error.already-connected-proxy"),
|
bungee.getEventManager().fireAndForget(new DisconnectEvent(player, DisconnectEvent.LoginStatus.CONFLICTING_LOGIN));
|
||||||
true);
|
sendErrorCode(ctx, HandshakePacketTypes.SERVER_ERROR_CUSTOM_MESSAGE,
|
||||||
|
LegacyComponentSerializer.legacySection().serialize(GlobalTranslator.render(Component.translatable("velocity.error.already-connected-proxy"), Locale.getDefault())))
|
||||||
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuf buf = Unpooled.buffer();
|
ByteBuf buf = Unpooled.buffer();
|
||||||
buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_FINISH_LOGIN);
|
buf.writeByte(HandshakePacketTypes.PROTOCOL_SERVER_FINISH_LOGIN);
|
||||||
ctx.channel().writeAndFlush(buf).addListener(future -> {
|
ctx.channel().writeAndFlush(new BinaryWebSocketFrame(buf)).addListener(future -> {
|
||||||
|
ChannelPipeline pp = ctx.channel().pipeline();
|
||||||
|
|
||||||
|
pp.remove(HttpWebSocketHandler.this);
|
||||||
|
|
||||||
|
pp
|
||||||
|
.addLast("EaglerMinecraftByteBufDecoder", new EaglerMinecraftDecoder())
|
||||||
|
.addLast(LEGACY_PING_DECODER, new LegacyPingDecoder())
|
||||||
|
.addLast(READ_TIMEOUT,
|
||||||
|
new ReadTimeoutHandler(bungee.getConfiguration().getReadTimeout(),
|
||||||
|
TimeUnit.MILLISECONDS))
|
||||||
|
.addLast("EaglerMinecraftByteBufEncoder", new EaglerMinecraftEncoder())
|
||||||
|
.addLast(LEGACY_PING_ENCODER, LegacyPingEncoder.INSTANCE)
|
||||||
|
.addLast(MINECRAFT_DECODER, new MinecraftDecoder(ProtocolUtils.Direction.SERVERBOUND))
|
||||||
|
.addLast(MINECRAFT_ENCODER, new MinecraftEncoder(ProtocolUtils.Direction.CLIENTBOUND));
|
||||||
|
|
||||||
|
pp.addLast(Connections.HANDLER, con);
|
||||||
|
|
||||||
|
con.setProtocolVersion(protocolVers);
|
||||||
|
con.setState(StateRegistry.PLAY);
|
||||||
con.setActiveSessionHandler(StateRegistry.PLAY, stupid4Constructor.newInstance(player, bungee));
|
con.setActiveSessionHandler(StateRegistry.PLAY, stupid4Constructor.newInstance(player, bungee));
|
||||||
|
|
||||||
bungee.getEventManager().fire(new PostLoginEvent(player)).thenCompose((ignored) -> {
|
bungee.getEventManager().fire(new PostLoginEvent(player)).thenCompose((ignored) -> {
|
||||||
ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().hasBeenForwarded = true;
|
ctx.channel().attr(EaglerPipeline.CONNECTION_INSTANCE).get().hasBeenForwarded = true;
|
||||||
Optional<RegisteredServer> initialFromConfig = player.getNextServerToTry();
|
Optional<RegisteredServer> initialFromConfig = player.getNextServerToTry();
|
||||||
|
@ -1151,9 +1171,9 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
hasBinaryConnection = false;
|
hasBinaryConnection = false;
|
||||||
|
|
||||||
if(CommandConfirmCode.confirmHash != null && str.equalsIgnoreCase(CommandConfirmCode.confirmHash)) {
|
if(CommandConfirmCode.confirmHash != null && str.equalsIgnoreCase(CommandConfirmCode.confirmHash)) {
|
||||||
|
connectionClosed = true;
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame("OK")).addListener(ChannelFutureListener.CLOSE);
|
ctx.writeAndFlush(new TextWebSocketFrame("OK")).addListener(ChannelFutureListener.CLOSE);
|
||||||
CommandConfirmCode.confirmHash = null;
|
CommandConfirmCode.confirmHash = null;
|
||||||
connectionClosed = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1178,17 +1198,17 @@ public class HttpWebSocketHandler extends ChannelInboundHandlerAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(queryRateLimit == RateLimitStatus.LOCKED_OUT) {
|
if(queryRateLimit == RateLimitStatus.LOCKED_OUT) {
|
||||||
ctx.close();
|
|
||||||
connectionClosed = true;
|
connectionClosed = true;
|
||||||
|
ctx.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(queryRateLimit != RateLimitStatus.OK) {
|
if(queryRateLimit != RateLimitStatus.OK) {
|
||||||
|
connectionClosed = true;
|
||||||
final RateLimitStatus rateLimitTypeFinal = queryRateLimit;
|
final RateLimitStatus rateLimitTypeFinal = queryRateLimit;
|
||||||
ctx.writeAndFlush(new TextWebSocketFrame(
|
ctx.writeAndFlush(new TextWebSocketFrame(
|
||||||
rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "{\"type\":\"locked\"}" : "{\"type\":\"blocked\"}"))
|
rateLimitTypeFinal == RateLimitStatus.LIMITED_NOW_LOCKED_OUT ? "{\"type\":\"locked\"}" : "{\"type\":\"blocked\"}"))
|
||||||
.addListener(ChannelFutureListener.CLOSE);
|
.addListener(ChannelFutureListener.CLOSE);
|
||||||
connectionClosed = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"id":"eaglerxvelocity","name":"EaglercraftXVelocity","version":"1.0.1","description":"Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks","authors":["lax1dude", "ayunami2000"],"dependencies":[],"main":"net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity"}
|
{"id":"eaglerxvelocity","name":"EaglercraftXVelocity","version":"1.0.2","description":"Plugin to allow EaglercraftX 1.8 players to join your network, or allow EaglercraftX 1.8 players to use your network as a proxy to join other networks","authors":["lax1dude", "ayunami2000"],"dependencies":[],"main":"net.lax1dude.eaglercraft.v1_8.plugin.gateway_velocity.EaglerXVelocity"}
|
|
@ -1 +1 @@
|
||||||
1.0.1
|
1.0.2
|
Loading…
Reference in New Issue
Block a user