wrote 90% of the server side (host) code

This commit is contained in:
LAX1DUDE 2022-08-18 00:19:30 -07:00
parent b70eb6bdc6
commit 8111b7f756
21 changed files with 606 additions and 94 deletions

View File

@ -601,10 +601,6 @@ window.initializeLANServer = (() => {
// nothing to do!
}
setRecieveCodeHandler(cb) {
// not yet implemented!
}
setICEServers(urls) {
this.ICEServers.length = 0;
for(var i = 0; i < urls.length; ++i) {
@ -701,7 +697,7 @@ window.initializeLANServer = (() => {
try {
thePeer.disconnect();
}catch(e) {}
this.remoteClientDisconnectHandler(peerId, quiet);
this.remoteClientDisconnectHandler(peerId);
}
}
this.peerList.clear();
@ -713,7 +709,7 @@ window.initializeLANServer = (() => {
try {
thePeer.disconnect();
}catch(e) {}
this.remoteClientDisconnectHandler(peerId, quiet);
this.remoteClientDisconnectHandler(peerId);
}
}

24
sp-relay/protocol.txt Normal file
View File

@ -0,0 +1,24 @@
Relay Packet Order:
~~~~~~~~~~~~~~~~~~
Opening LAN world:
[Server -> Relay] Open WebSocket
[Server -> Relay] PKT 0x00: Send protocol id, identify as server
[Relay -> Server] PKT 0x00: Reply protocol id, assign join code
[Relay -> Server] PKT 0x01: Send ICE server list to server
Client connects:
[Client -> Relay] Open WebSocket
[Client -> Relay] PKT 0x00: Send protocol id, identify as client, send server join code
[Relay -> Client] PKT 0x00: Reply protocol id, assign client id
[Relay -> Client] PKT 0x01: Send ICE server list to client
[Relay -> Server] PKT 0x02: Notify server of the client, send client's id to server
[Client -> Relay -> Server] PKT 0x03: Send client ICE Candidate to server
[Server -> Relay -> Client] PKT 0x03: Send server ICE Candidate to client
[Client -> Relay -> Server] PKT 0x04: Send client description to server
[Server -> Relay -> Client] PKT 0x04: Send server description to client
[Client -> Relay -> Server] PKT 0x05 or 0x06: Client signals sucess or failure
[Relay -> Client] PKT 0xFE: Signal to close WebSocket

View File

@ -208,7 +208,7 @@ public class EaglerSPRelay extends WebSocketServer {
IPacket00Handshake ipkt = (IPacket00Handshake)pkt;
if(ipkt.connectionVersion != Constants.protocolVersion) {
logger.debug("[{}]: Connected with unsupported protocol version: {} (supported "
+ "version: {})", arg0.getAttachment(), Constants.protocolVersion);
+ "version: {})", arg0.getAttachment(), ipkt.connectionVersion, Constants.protocolVersion);
if(ipkt.connectionVersion < Constants.protocolVersion) {
arg0.send(IPacket.writePacket(new IPacketFFErrorCode(IPacketFFErrorCode.TYPE_PROTOCOL_VERSION,
"Outdated Client! (v" + Constants.protocolVersion + " req)")));

View File

@ -35,7 +35,7 @@ public class IPacket00Handshake extends IPacket {
@Override
public int packetLength() {
return 1 + 1 + (connectionCode != null ? 1 + connectionCode.length() : 0);
return 1 + (connectionCode != null ? 1 + connectionCode.length() : 0);
}
}

View File

@ -12,6 +12,7 @@ public class IPacketFEDisconnectClient extends IPacket {
public static final int TYPE_TIMEOUT = 0x02;
public static final int TYPE_INVALID_OPERATION = 0x03;
public static final int TYPE_INTERNAL_ERROR = 0x04;
public static final int TYPE_SERVER_DISCONNECT = 0x05;
public static final int TYPE_UNKNOWN = 0xFF;
public String clientId;

View File

@ -0,0 +1,44 @@
package net.lax1dude.eaglercraft.sp.ipc;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class IPCPacket17ConfigureLAN implements IPCPacketBase {
public static final int ID = 0x17;
public int gamemode;
public boolean cheats;
public IPCPacket17ConfigureLAN() {
}
public IPCPacket17ConfigureLAN(int gamemode, boolean cheats) {
this.gamemode = gamemode;
this.cheats = cheats;
}
@Override
public void deserialize(DataInput bin) throws IOException {
gamemode = bin.readUnsignedByte();
cheats = bin.readBoolean();
}
@Override
public void serialize(DataOutput bin) throws IOException {
bin.writeByte(gamemode);
bin.writeBoolean(cheats);
}
@Override
public int id() {
return ID;
}
@Override
public int size() {
return 2;
}
}

View File

@ -38,6 +38,7 @@ public class IPCPacketManager {
mappings.put(IPCPacket14StringList.ID, () -> new IPCPacket14StringList());
mappings.put(IPCPacket15ThrowException.ID, () -> new IPCPacket15ThrowException());
mappings.put(IPCPacket16NBTList.ID, () -> new IPCPacket16NBTList());
mappings.put(IPCPacket17ConfigureLAN.ID, () -> new IPCPacket17ConfigureLAN());
mappings.put(IPCPacketFFProcessKeepAlive.ID, () -> new IPCPacketFFProcessKeepAlive());
}

View File

@ -658,6 +658,11 @@ public class IntegratedServer {
}
}
break;
case IPCPacket17ConfigureLAN.ID: {
IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)packet;
currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats);
}
break;
default:
System.err.println("IPC packet type 0x" + Integer.toHexString(id) + " class '" + packet.getClass().getSimpleName() + "' was not handled");
sendTaskFailed();

View File

@ -48,6 +48,9 @@ public class ServerConfigurationManager {
* hardcoded to max at 200 players
*/
private int playerPingIndex = 0;
private EnumGameType lanGamemode = EnumGameType.SURVIVAL;
private boolean lanCheats = false;
public ServerConfigurationManager(MinecraftServer par1MinecraftServer) {
this.mcServer = par1MinecraftServer;
@ -521,7 +524,7 @@ public class ServerConfigurationManager {
* Returns true if the specific player is allowed to use commands.
*/
public boolean areCommandsAllowed(String par1Str) {
return this.ops.contains(par1Str.trim().toLowerCase())
return lanCheats || this.ops.contains(par1Str.trim().toLowerCase())
|| this.mcServer.isSinglePlayer() && this.mcServer.worldServers[0].getWorldInfo().areCommandsAllowed()
&& this.mcServer.getServerOwner().equalsIgnoreCase(par1Str)
|| this.commandsAllowedForAll;
@ -820,14 +823,18 @@ public class ServerConfigurationManager {
}
private void func_72381_a(EntityPlayerMP par1EntityPlayerMP, EntityPlayerMP par2EntityPlayerMP, World par3World) {
if (par2EntityPlayerMP != null) {
par1EntityPlayerMP.theItemInWorldManager
.setGameType(par2EntityPlayerMP.theItemInWorldManager.getGameType());
} else if (this.gameType != null) {
par1EntityPlayerMP.theItemInWorldManager.setGameType(this.gameType);
}
if(par1EntityPlayerMP.username.equals(mcServer.getServerOwner())) {
if (par2EntityPlayerMP != null) {
par1EntityPlayerMP.theItemInWorldManager
.setGameType(par2EntityPlayerMP.theItemInWorldManager.getGameType());
} else if (this.gameType != null) {
par1EntityPlayerMP.theItemInWorldManager.setGameType(this.gameType);
}
par1EntityPlayerMP.theItemInWorldManager.initializeGameType(par3World.getWorldInfo().getGameType());
par1EntityPlayerMP.theItemInWorldManager.initializeGameType(par3World.getWorldInfo().getGameType());
}else {
par1EntityPlayerMP.theItemInWorldManager.setGameType(lanGamemode);
}
}
/**
@ -846,4 +853,9 @@ public class ServerConfigurationManager {
this.mcServer.logInfo(par1Str);
this.sendPacketToAllPlayers(new Packet3Chat(par1Str));
}
public void configureLAN(int gamemode, boolean cheats) {
lanGamemode = EnumGameType.getByID(gamemode);
lanCheats = cheats;
}
}

View File

@ -432,18 +432,8 @@ public class IntegratedServer {
sendIPCPacket(new IPCPacket0CPlayerChannel(channel, false));
}
private static boolean hostingLAN = false;
public static final String shareToLAN(EnumGameType gameType, boolean allowCommands) {
hostingLAN = true;
return "yee";
public static void configureLAN(EnumGameType enumGameType, boolean allowCommands) {
sendIPCPacket(new IPCPacket17ConfigureLAN(enumGameType.getID(), allowCommands));
}
public static final void closeLAN() {
hostingLAN = false;
}
public static final boolean isHostingLAN() {
return hostingLAN;
}
}
}

View File

@ -0,0 +1,308 @@
package net.lax1dude.eaglercraft;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import net.lax1dude.eaglercraft.sp.relay.pkt.*;
public class IntegratedServerLAN {
private static RelayServerSocket lanRelaySocket = null;
public static String shareToLAN(Consumer<String> progressCallback, String worldName, boolean worldHidden) {
RelayServerSocket sock = IntegratedServer.relayManager.getWorkingRelay((str) -> progressCallback.accept("Connecting: " + str),
IntegratedServer.preferredRelayVersion, worldName + (worldHidden ? ";1" : ";0"));
if(sock == null) {
lanRelaySocket = null;
return null;
}else {
progressCallback.accept("Opening: " + sock.getURI());
IPacket00Handshake hs = (IPacket00Handshake)sock.readPacket();
lanRelaySocket = sock;
String code = hs.connectionCode;
System.out.println("Relay [" + sock.getURI() + "] connected as 'server', code: " + code);
progressCallback.accept("Opened '" + code + "' on " + sock.getURI());
long millis = System.currentTimeMillis();
do {
if(sock.isClosed()) {
System.out.println("Relay [" + sock.getURI() + "] connection lost");
lanRelaySocket = null;
return null;
}
IPacket pkt = sock.readPacket();
if(pkt != null) {
if(pkt instanceof IPacket01ICEServers) {
IPacket01ICEServers ipkt = (IPacket01ICEServers)pkt;
System.out.println("Relay [" + sock.getURI() + "] provided ICE servers:");
List<String> servers = new ArrayList();
for(net.lax1dude.eaglercraft.sp.relay.pkt.ICEServerSet.RelayServer srv : ipkt.servers) {
System.out.println("Relay [" + sock.getURI() + "] " + srv.type.name()
+ ": " + srv.address);
servers.add(srv.getICEString());
}
EaglerAdapter.serverLANInitializeServer(servers.toArray(new String[servers.size()]));
return code;
}else {
System.err.println("Relay [" + sock.getURI() + "] unexpected packet: " + pkt.getClass().getSimpleName());
closeLAN();
return null;
}
}
try {
Thread.sleep(50l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - millis > 1000l);
System.out.println("Relay [" + sock.getURI() + "] relay provide ICE servers timeout");
closeLAN();
return null;
}
}
public static void closeLAN() {
if(lanRelaySocket != null) {
lanRelaySocket.close();
lanRelaySocket = null;
}
cleanupLAN();
}
static void cleanupLAN() {
Iterator<LANClient> itr = clients.values().iterator();
while(itr.hasNext()) {
itr.next().disconnect();
}
clients.clear();
}
public static boolean isHostingLAN() {
return lanRelaySocket != null;
}
private static final Map<String, LANClient> clients = new HashMap();
public static void updateLANServer() {
if(lanRelaySocket != null) {
IPacket pkt;
while((pkt = lanRelaySocket.nextPacket()) != null) {
if(pkt instanceof IPacket02NewClient) {
IPacket02NewClient ipkt = (IPacket02NewClient) pkt;
if(clients.containsKey(ipkt.clientId)) {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] relay provided duplicate client '" + ipkt.clientId + "'");
}else {
clients.put(ipkt.clientId, new LANClient(ipkt.clientId));
}
}else if(pkt instanceof IPacket03ICECandidate) {
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
LANClient c = clients.get(ipkt.peerId);
if(c != null) {
c.handleICECandidates(ipkt.candidate);
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] relay sent IPacket03ICECandidate for unknown client '" + ipkt.peerId + "'");
}
}else if(pkt instanceof IPacket04Description) {
IPacket04Description ipkt = (IPacket04Description) pkt;
LANClient c = clients.get(ipkt.peerId);
if(c != null) {
c.handleDescription(ipkt.description);
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] relay sent IPacket04Description for unknown client '" + ipkt.peerId + "'");
}
}else if(pkt instanceof IPacket05ClientSuccess) {
IPacket05ClientSuccess ipkt = (IPacket05ClientSuccess) pkt;
LANClient c = clients.get(ipkt.clientId);
if(c != null) {
c.handleSuccess();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] relay sent IPacket05ClientSuccess for unknown client '" + ipkt.clientId + "'");
}
}else if(pkt instanceof IPacket06ClientFailure) {
IPacket06ClientFailure ipkt = (IPacket06ClientFailure) pkt;
LANClient c = clients.get(ipkt.clientId);
if(c != null) {
c.handleFailure();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] relay sent IPacket06ClientFailure for unknown client '" + ipkt.clientId + "'");
}
}else if(pkt instanceof IPacketFFErrorCode) {
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
System.err.println("Relay [" + lanRelaySocket.getURI() + "] error code thrown: " +
IPacketFFErrorCode.code2string(ipkt.code) + "(" + ipkt.code + "): " + ipkt.desc);
Throwable t;
while((t = lanRelaySocket.getException()) != null) {
t.printStackTrace();
}
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected packet: " + pkt.getClass().getSimpleName());
}
}
if(lanRelaySocket.isClosed()) {
lanRelaySocket = null;
cleanupLAN();
}else {
Iterator<LANClient> itr = clients.values().iterator();
while(itr.hasNext()) {
LANClient cl = itr.next();
cl.update();
if(cl.dead) {
itr.remove();
}
}
}
}
}
private static final class LANClient {
private static final int PRE = 0, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3, CONNECTED = 4, CLOSED = 5;
protected final String clientId;
protected int state = PRE;
protected boolean dead = false;
protected LANClient(String clientId) {
this.clientId = clientId;
}
protected void handleICECandidates(String candidates) {
if(state == PRE) {
EaglerAdapter.serverLANPeerICECandidates(clientId, candidates);
long millis = System.currentTimeMillis();
do {
LANPeerEvent evt;
if((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) {
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
lanRelaySocket.writePacket(new IPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
state = SENT_ICE_CANDIDATE;
return;
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
System.err.println("LAN client '" + clientId + "' disconnected while waiting for server ICE candidates");
}else {
System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName());
}
disconnect();
return;
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - millis > 3000l);
System.err.println("Getting server ICE candidates for '" + clientId + "' timed out!");
disconnect();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket03ICECandidate for '" + clientId + "'");
}
}
protected void handleDescription(String description) {
if(state == SENT_ICE_CANDIDATE) {
EaglerAdapter.serverLANPeerDescription(clientId, description);
long millis = System.currentTimeMillis();
do {
LANPeerEvent evt;
if((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) {
if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) {
lanRelaySocket.writePacket(new IPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description));
state = SENT_DESCRIPTION;
return;
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
System.err.println("LAN client '" + clientId + "' disconnected while waiting for server description");
}else {
System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName());
}
disconnect();
return;
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - millis > 3000l);
System.err.println("Getting server description for '" + clientId + "' timed out!");
disconnect();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket04Description for '" + clientId + "'");
}
}
protected void handleSuccess() {
if(state == SENT_DESCRIPTION) {
long millis = System.currentTimeMillis();
do {
LANPeerEvent evt;
if((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) {
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
EaglerAdapter.enableChannel("NET|" + clientId);
state = CONNECTED;
return;
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
System.err.println("LAN client '" + clientId + "' disconnected while waiting for connection");
}else {
System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName());
}
disconnect();
return;
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - millis > 3000l);
System.err.println("Getting server description for '" + clientId + "' timed out!");
disconnect();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket05ClientSuccess for '" + clientId + "'");
}
}
protected void handleFailure() {
if(state == SENT_DESCRIPTION) {
System.err.println("Client '" + clientId + "' failed to connect");
disconnect();
}else {
System.err.println("Relay [" + lanRelaySocket.getURI() + "] unexpected IPacket06ClientFailure for '" + clientId + "'");
}
}
protected void update() {
if(state == CONNECTED) {
LANPeerEvent evt;
while((evt = EaglerAdapter.serverLANGetEvent(clientId)) != null) {
if(state == CONNECTED) {
if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
EaglerAdapter.sendToIntegratedServer(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload);
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
System.err.println("LAN client '" + clientId + "' disconnected");
disconnect();
}else {
System.err.println("LAN client '" + clientId + "' had an accident: " + evt.getClass().getSimpleName());
disconnect();
}
}
}
if(state == CONNECTED) {
PKT pk = EaglerAdapter.recieveFromIntegratedServer(clientId);
EaglerAdapter.serverLANWritePacket(clientId, pk.data);
}
}
}
protected void disconnect() {
if(!dead) {
if(state == CONNECTED) {
EaglerAdapter.disableChannel("NET|" + clientId);
}
state = CLOSED;
lanRelaySocket.writePacket(new IPacketFEDisconnectClient(clientId, IPacketFEDisconnectClient.TYPE_SERVER_DISCONNECT, "Connection Closed"));
dead = true;
}
}
}
}

View File

@ -90,6 +90,10 @@ public class LANClientNetworkManager implements INetworkManager {
connectState = SENT_ICE_CANDIDATE;
continue mainLoop;
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - lm > 3000l);
// no ice candidates were sent
@ -127,6 +131,10 @@ public class LANClientNetworkManager implements INetworkManager {
connectState = SENT_DESCRIPTION;
continue mainLoop;
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - lm > 3000l);
// no description was sent
@ -163,6 +171,10 @@ public class LANClientNetworkManager implements INetworkManager {
return new LANClientNetworkManager(displayCode, displayRelay);
}
try {
Thread.sleep(20l);
} catch (InterruptedException e) {
}
}while(System.currentTimeMillis() - lm > 3000l);
// no channel was opened

View File

@ -0,0 +1,88 @@
package net.lax1dude.eaglercraft;
public interface LANPeerEvent {
String getPeerId();
public static class LANPeerICECandidateEvent implements LANPeerEvent {
public final String clientId;
public final String candidates;
public LANPeerICECandidateEvent(String clientId, String candidates) {
this.clientId = clientId;
this.candidates = candidates;
}
@Override
public String getPeerId() {
return clientId;
}
}
public static class LANPeerDescriptionEvent implements LANPeerEvent {
public final String clientId;
public final String description;
public LANPeerDescriptionEvent(String clientId, String description) {
this.clientId = clientId;
this.description = description;
}
@Override
public String getPeerId() {
return clientId;
}
}
public static class LANPeerDataChannelEvent implements LANPeerEvent {
public final String clientId;
public LANPeerDataChannelEvent(String clientId) {
this.clientId = clientId;
}
@Override
public String getPeerId() {
return clientId;
}
}
public static class LANPeerPacketEvent implements LANPeerEvent {
public final String clientId;
public final byte[] payload;
public LANPeerPacketEvent(String clientId, byte[] payload) {
this.clientId = clientId;
this.payload = payload;
}
@Override
public String getPeerId() {
return clientId;
}
}
public static class LANPeerDisconnectEvent implements LANPeerEvent {
public final String clientId;
public LANPeerDisconnectEvent(String clientId) {
this.clientId = clientId;
}
@Override
public String getPeerId() {
return clientId;
}
}
}

View File

@ -241,7 +241,9 @@ public class RelayManager {
progressCallback.accept(relay.address);
RelayServerSocket sock = connectHandshake(relay, type, code);
if(sock != null) {
return sock;
if(!sock.isFailed()) {
return sock;
}
}else {
brokenServers.add(relay);
}
@ -253,7 +255,9 @@ public class RelayManager {
progressCallback.accept(relayEtr.address);
RelayServerSocket sock = connectHandshake(relayEtr, type, code);
if(sock != null) {
return sock;
if(!sock.isFailed()) {
return sock;
}
}else {
brokenServers.add(relayEtr);
}
@ -275,7 +279,9 @@ public class RelayManager {
progressCallback.accept(srv.address);
RelayServerSocket sock = connectHandshake(srv, type, code);
if(sock != null) {
return sock;
if(!sock.isFailed()) {
return sock;
}
}else {
brokenServers.add(srv);
}

View File

@ -19,4 +19,6 @@ public interface RelayServerSocket {
RateLimit getRatelimitHistory();
String getURI();
}

View File

@ -35,7 +35,7 @@ public class IPacket00Handshake extends IPacket {
@Override
public int packetLength() {
return 1 + 1 + (connectionCode != null ? 1 + connectionCode.length() : 0);
return 1 + (connectionCode != null ? 1 + connectionCode.length() : 0);
}
}

View File

@ -12,6 +12,7 @@ public class IPacketFEDisconnectClient extends IPacket {
public static final int TYPE_TIMEOUT = 0x02;
public static final int TYPE_INVALID_OPERATION = 0x03;
public static final int TYPE_INTERNAL_ERROR = 0x04;
public static final int TYPE_SERVER_DISCONNECT = 0x05;
public static final int TYPE_UNKNOWN = 0xFF;
public String clientId;

View File

@ -6,6 +6,7 @@ import net.lax1dude.eaglercraft.EaglerAdapter;
import net.lax1dude.eaglercraft.GuiScreenSkinCapeSettings;
import net.lax1dude.eaglercraft.GuiVoiceMenu;
import net.lax1dude.eaglercraft.IntegratedServer;
import net.lax1dude.eaglercraft.IntegratedServerLAN;
import net.minecraft.client.Minecraft;
public class GuiIngameMenu extends GuiScreen {
@ -31,7 +32,7 @@ public class GuiIngameMenu extends GuiScreen {
this.buttonList.add(new GuiButton(4, this.width / 2 - 100, this.height / 4 + 24 + var1, StatCollector.translateToLocal("menu.returnToGame")));
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal("menu.options")));
GuiButton var3;
this.buttonList.add(var3 = new GuiButton(7, this.width / 2 + 2, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal(IntegratedServer.isHostingLAN() ? "menu.closeLan" : "menu.shareToLan")));
this.buttonList.add(var3 = new GuiButton(7, this.width / 2 + 2, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal(IntegratedServerLAN.isHostingLAN() ? "menu.closeLan" : "menu.shareToLan")));
var3.enabled = mc.isSingleplayer();
this.buttonList.add(new GuiButton(8, 3, 3, 120, 20, StatCollector.translateToLocal("menu.skinCapeSettings")));
}
@ -64,8 +65,8 @@ public class GuiIngameMenu extends GuiScreen {
break;
case 7:
if (IntegratedServer.isHostingLAN()) {
IntegratedServer.closeLAN();
if (IntegratedServerLAN.isHostingLAN()) {
IntegratedServerLAN.closeLAN();
this.mc.displayGuiScreen((GuiScreen) null);
this.mc.setIngameFocus();
this.mc.sndManager.resumeAllSounds();

View File

@ -1,6 +1,7 @@
package net.minecraft.src;
import net.lax1dude.eaglercraft.IntegratedServer;
import net.lax1dude.eaglercraft.IntegratedServerLAN;
public class GuiShareToLan extends GuiScreen {
/**
@ -77,11 +78,16 @@ public class GuiShareToLan extends GuiScreen {
this.func_74088_g();
} else if (par1GuiButton.id == 101) {
this.mc.displayGuiScreen((GuiScreen) null);
String var2 = IntegratedServer.shareToLAN(EnumGameType.getByName(this.gameMode), this.allowCommands);
LoadingScreenRenderer ls = mc.loadingScreen;
IntegratedServer.configureLAN(EnumGameType.getByName(this.gameMode), this.allowCommands);
String code = IntegratedServerLAN.shareToLAN((str) -> ls.displayProgressMessage(str), null, false);
//TODO: handle code success or failure, redirect to relay list on failure, on success store code and relay and display in pause menu
//TODO: must call IntegratedServer.configureLAN(mc.theWorld.getGameType(), false); when world is closed
String var3;
if (var2 != null) {
var3 = StatCollector.translateToLocalFormatted("commands.publish.started", var2);
if (code != null) {
var3 = StatCollector.translateToLocalFormatted("commands.publish.started", code);
} else {
var3 = StatCollector.translateToLocal("commands.publish.failed");
}

View File

@ -85,11 +85,13 @@ import org.teavm.jso.workers.Worker;
import net.lax1dude.eaglercraft.AssetRepository;
import net.lax1dude.eaglercraft.Base64;
import net.lax1dude.eaglercraft.EaglerAdapter;
import net.lax1dude.eaglercraft.EaglerImage;
import net.lax1dude.eaglercraft.EaglerProfile;
import net.lax1dude.eaglercraft.EarlyLoadScreen;
import net.lax1dude.eaglercraft.ExpiringSet;
import net.lax1dude.eaglercraft.IntegratedServer;
import net.lax1dude.eaglercraft.LANPeerEvent;
import net.lax1dude.eaglercraft.LocalStorageManager;
import net.lax1dude.eaglercraft.PKT;
import net.lax1dude.eaglercraft.RelayQuery;
@ -1848,6 +1850,9 @@ public class EaglerAdapterImpl2 {
if(IntegratedServer.doesChannelExist(EaglerProfile.username) && IntegratedServer.isWorldRunning()) {
return true;
}
if(!EaglerAdapter.clientLANClosed()) {
return true;
}
if(sock == null || sock.getReadyState() == 3) {
sockIsConnecting = false;
}
@ -3599,6 +3604,11 @@ public class EaglerAdapterImpl2 {
return RateLimit.NONE;
}
@Override
public String getURI() {
return uri;
}
}
private static class RelayServerSocketRatelimitDummy implements RelayServerSocket {
@ -3652,6 +3662,11 @@ public class EaglerAdapterImpl2 {
return limit;
}
@Override
public String getURI() {
return "<disconnected>";
}
}
public static final RelayServerSocket openRelayConnection(String addr) {
@ -3812,38 +3827,34 @@ public class EaglerAdapterImpl2 {
private static native EaglercraftLANServer startRTCLANServer();
private static boolean serverLANinit = false;
private static final List<LANPeerPacket> serverLANPacketBuffer = new ArrayList<>();
private static final List<LANPeerEvent> serverLANEventBuffer = new LinkedList<>();
public static final boolean serverLANSupported() {
return rtcLANServer.LANServerSupported();
}
public static final String serverLANInitializeServer(String relay) {
public static final void serverLANInitializeServer(String[] servers) {
serverLANEventBuffer.clear();
rtcLANServer.setICEServers(servers);
rtcLANServer.initializeServer();
if(!serverLANinit) {
serverLANinit = true;
rtcLANServer.setDescriptionHandler(new EaglercraftLANServer.DescriptionHandler() {
@Override
public void call(String peerId, String candidate) {
serverLANEventBuffer.add(new LANPeerEvent.LANPeerDisconnectEvent(peerId));
}
});
rtcLANServer.setICECandidateHandler(new EaglercraftLANServer.ICECandidateHandler() {
@Override
public void call(String peerId, String candidate) {
}
});
rtcLANServer.setRecieveCodeHandler(new EaglercraftLANServer.CodeHandler() {
@Override
public void call(String code) {
serverLANEventBuffer.add(new LANPeerEvent.LANPeerDisconnectEvent(peerId));
}
});
rtcLANServer.setRemoteClientDataChannelHandler(new EaglercraftLANServer.ClientSignalHandler() {
@Override
public void call() {
// unused
public void call(String peerId) {
serverLANEventBuffer.add(new LANPeerEvent.LANPeerDataChannelEvent(peerId));
}
});
rtcLANServer.setRemoteClientPacketHandler(new EaglercraftLANServer.PeerPacketHandler() {
@ -3854,18 +3865,16 @@ public class EaglerAdapterImpl2 {
for(int i = 0; i < ret.length; ++i) {
ret[i] = (byte) array.get(i);
}
serverLANPacketBuffer.add(new LANPeerPacket(peerId, ret));
serverLANEventBuffer.add(new LANPeerEvent.LANPeerPacketEvent(peerId, ret));
}
});
rtcLANServer.setRemoteClientDisconnectHandler(new EaglercraftLANServer.ClientSignalHandler() {
@Override
public void call() {
clientDataChannelClosed = true;
public void call(String peerId) {
serverLANEventBuffer.add(new LANPeerEvent.LANPeerDisconnectEvent(peerId));
}
});
}
// todo: java-side: register in relay & return code!!
return null;
}
public static final boolean serverLANServerOpen() {
@ -3877,39 +3886,40 @@ public class EaglerAdapterImpl2 {
// todo: java-side: disconnect from relay server
}
public static interface LANConnectionEvent {
public String getPeerName();
public void accept();
public void reject();
public static final LANPeerEvent serverLANGetEvent() {
return serverLANEventBuffer.size() > 0 ? serverLANEventBuffer.remove(0) : null;
}
public static final LANConnectionEvent serverLANGetConnectionEvent() {
return null;
}
public static final String serverLANGetDisconnectEvent() {
return null;
}
public static class LANPeerPacket {
public final String peer;
public final byte[] packet;
protected LANPeerPacket(String peer, byte[] packet) {
this.peer = peer;
this.packet = packet;
public static final LANPeerEvent serverLANGetEvent(String clientId) {
if(serverLANEventBuffer.size() > 0) {
Iterator<LANPeerEvent> i = serverLANEventBuffer.iterator();
while(i.hasNext()) {
LANPeerEvent evt = i.next();
if(evt.getPeerId().equals(clientId)) {
i.remove();
return evt;
}
}
return null;
}else {
return null;
}
}
public static final LANPeerPacket serverLANReadPacket() {
return serverLANPacketBuffer.size() > 0 ? serverLANPacketBuffer.remove(0) : null;
public static final <T extends LANPeerEvent> T serverLANGetEvent(String clientId, Class<T> eventType) {
if(serverLANEventBuffer.size() > 0) {
Iterator<LANPeerEvent> i = serverLANEventBuffer.iterator();
while(i.hasNext()) {
LANPeerEvent evt = i.next();
if(evt.getPeerId().equals(clientId) && eventType.isInstance(evt)) {
i.remove();
return (T)evt;
}
}
return null;
}else {
return null;
}
}
public static final void serverLANWritePacket(String peer, byte[] data) {
@ -3918,6 +3928,18 @@ public class EaglerAdapterImpl2 {
rtcLANServer.sendPacketToRemoteClient(peer, arr);
}
public static final void serverLANCreatePeer(String peer) {
rtcLANServer.signalRemoteConnect(peer);
}
public static final void serverLANPeerICECandidates(String peer, String iceCandidates) {
rtcLANServer.signalRemoteICECandidate(peer, iceCandidates);
}
public static final void serverLANPeerDescription(String peer, String description) {
rtcLANServer.signalRemoteDescription(peer, description);
}
public static final void serverLANDisconnectPeer(String peer) {
rtcLANServer.signalRemoteDisconnect(peer);
}

View File

@ -14,8 +14,6 @@ public interface EaglercraftLANServer extends JSObject {
void initializeServer();
void setRecieveCodeHandler(CodeHandler cb);
void setICEServers(String[] urls);
void setICECandidateHandler(ICECandidateHandler cb);
@ -55,11 +53,6 @@ public interface EaglercraftLANServer extends JSObject {
void call(String peerId, String candidate);
}
@JSFunctor
public static interface CodeHandler extends JSObject {
void call(String code);
}
@JSFunctor
public static interface DescriptionHandler extends JSObject {
void call(String peerId, String candidate);
@ -67,7 +60,7 @@ public interface EaglercraftLANServer extends JSObject {
@JSFunctor
public static interface ClientSignalHandler extends JSObject {
void call();
void call(String peerId);
}
@JSFunctor