wrote 90% of the server side (host) code
This commit is contained in:
parent
b70eb6bdc6
commit
8111b7f756
|
@ -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
24
sp-relay/protocol.txt
Normal 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
|
|
@ -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)")));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
308
src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java
Normal file
308
src/main/java/net/lax1dude/eaglercraft/IntegratedServerLAN.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
88
src/main/java/net/lax1dude/eaglercraft/LANPeerEvent.java
Normal file
88
src/main/java/net/lax1dude/eaglercraft/LANPeerEvent.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -19,4 +19,6 @@ public interface RelayServerSocket {
|
|||
|
||||
RateLimit getRatelimitHistory();
|
||||
|
||||
String getURI();
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user