added LAN skins and worked on LAN voice chat

This commit is contained in:
LAX1DUDE 2022-08-21 00:21:13 -07:00
parent dd02a35b48
commit f42aac7664
19 changed files with 33993 additions and 33387 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -3,6 +3,8 @@ package net.lax1dude.eaglercraft.sp.ipc;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class IPCPacket17ConfigureLAN implements IPCPacketBase {
@ -10,25 +12,37 @@ public class IPCPacket17ConfigureLAN implements IPCPacketBase {
public int gamemode;
public boolean cheats;
public final List<String> iceServers;
public IPCPacket17ConfigureLAN() {
iceServers = new ArrayList();
}
public IPCPacket17ConfigureLAN(int gamemode, boolean cheats) {
public IPCPacket17ConfigureLAN(int gamemode, boolean cheats, List<String> iceServers) {
this.gamemode = gamemode;
this.cheats = cheats;
this.iceServers = iceServers;
}
@Override
public void deserialize(DataInput bin) throws IOException {
gamemode = bin.readUnsignedByte();
cheats = bin.readBoolean();
iceServers.clear();
int iceCount = bin.readUnsignedByte();
for(int i = 0; i < iceCount; ++i) {
iceServers.add(bin.readUTF());
}
}
@Override
public void serialize(DataOutput bin) throws IOException {
bin.writeByte(gamemode);
bin.writeBoolean(cheats);
bin.writeByte(iceServers.size());
for(int i = 0, l = iceServers.size(); i < l; ++i) {
bin.writeUTF(iceServers.get(i));
}
}
@Override
@ -38,7 +52,12 @@ public class IPCPacket17ConfigureLAN implements IPCPacketBase {
@Override
public int size() {
return 2;
int s = 0;
for(int i = 0, l = iceServers.size(); i < l; ++i) {
s += 2;
s += iceServers.get(i).length();
}
return 2 + 1 + s;
}
}

View File

@ -88,11 +88,20 @@ public class EAGMinecraftServer extends MinecraftServer {
@Override
protected boolean startServer() throws IOException {
SkinsPlugin.reset();
VoiceChatPlugin.reset();
this.loadAllWorlds(folderName, 0l, newWorldSettings);
this.lastTick = System.currentTimeMillis();
return true;
}
@Override
public void stopServer() {
super.stopServer();
SkinsPlugin.reset();
VoiceChatPlugin.reset();
}
@Override
public boolean canStructuresSpawn() {
return false;

View File

@ -0,0 +1,74 @@
package net.lax1dude.eaglercraft.sp;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
// note that there's a few things not implemented, but I don't care.
public class ExpiringSet<T> extends HashSet<T> {
private final long expiration;
private final ExpiringEvent<T> event;
private final Map<T, Long> timestamps = new HashMap<>();
public ExpiringSet(long expiration) {
this.expiration = expiration;
this.event = null;
}
public ExpiringSet(long expiration, ExpiringEvent<T> event) {
this.expiration = expiration;
this.event = event;
}
public interface ExpiringEvent<T> {
void onExpiration(T item);
}
public void checkForExpirations() {
Iterator<T> iterator = this.timestamps.keySet().iterator();
long now = System.currentTimeMillis();
while (iterator.hasNext()) {
T element = iterator.next();
if (super.contains(element)) {
if (this.timestamps.get(element) + this.expiration < now) {
if (this.event != null)
this.event.onExpiration(element);
iterator.remove();
super.remove(element);
}
} else {
iterator.remove();
super.remove(element);
}
}
}
public boolean add(T o) {
checkForExpirations();
boolean success = super.add(o);
if (success)
timestamps.put(o, System.currentTimeMillis());
return success;
}
public boolean remove(Object o) {
checkForExpirations();
boolean success = super.remove(o);
if (success)
timestamps.remove(o);
return success;
}
public void clear() {
this.timestamps.clear();
super.clear();
}
public boolean contains(Object o) {
checkForExpirations();
return super.contains(o);
}
}

View File

@ -106,11 +106,11 @@ public class IntegratedServer {
public static void throwExceptionToClient(String msg, Throwable t) {
String str = t.toString();
System.err.println("Exception was raised to client: " + str);
t.printStackTrace();
List<String> arr = new LinkedList();
for(StackTraceElement e : t.getStackTrace()) {
String st = e.toString();
arr.add(st);
System.err.println(" " + st);
}
sendIPCPacket(new IPCPacket15ThrowException(str, arr));
}
@ -660,7 +660,7 @@ public class IntegratedServer {
break;
case IPCPacket17ConfigureLAN.ID: {
IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)packet;
currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats);
currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats, pkt.iceServers);
}
break;
default:

View File

@ -0,0 +1,108 @@
package net.lax1dude.eaglercraft.sp;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.Packet250CustomPayload;
public class SkinsPlugin {
private static final HashMap<String,byte[]> skinCollection = new HashMap();
private static final HashMap<String,byte[]> capeCollection = new HashMap();
private static final HashMap<String,Long> lastSkinLayerUpdate = new HashMap();
private static final int[] SKIN_DATA_SIZE = new int[] { 64*32*4, 64*64*4, -9, -9, 1, 64*64*4, -9 }; // 128 pixel skins crash clients
private static final int[] CAPE_DATA_SIZE = new int[] { 32*32*4, -9, 1 };
public static boolean handleMessage(EntityPlayerMP player, Packet250CustomPayload payload) {
if(payload.data.length > 0) {
String user = player.username;
byte[] msg = payload.data;
try {
if("EAG|MySkin".equals(payload.channel)) {
if(!skinCollection.containsKey(user)) {
int t = (int)msg[0] & 0xFF;
if(t < SKIN_DATA_SIZE.length && msg.length == (SKIN_DATA_SIZE[t] + 1)) {
skinCollection.put(user, msg);
}
}
return true;
}
if("EAG|MyCape".equals(payload.channel)) {
if(!capeCollection.containsKey(user)) {
int t = (int)msg[0] & 0xFF;
if(t < CAPE_DATA_SIZE.length && msg.length == (CAPE_DATA_SIZE[t] + 2)) {
capeCollection.put(user, msg);
}
}
return true;
}
if("EAG|FetchSkin".equals(payload.channel)) {
if(msg.length > 2) {
String fetch = new String(msg, 2, msg.length - 2, StandardCharsets.UTF_8);
byte[] data;
if((data = skinCollection.get(fetch)) != null) {
byte[] conc = new byte[data.length + 2];
conc[0] = msg[0]; conc[1] = msg[1]; //synchronization cookie
System.arraycopy(data, 0, conc, 2, data.length);
if((data = capeCollection.get(fetch)) != null) {
byte[] conc2 = new byte[conc.length + data.length];
System.arraycopy(conc, 0, conc2, 0, conc.length);
System.arraycopy(data, 0, conc2, conc.length, data.length);
conc = conc2;
}
player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|UserSkin", conc));
}
}
return true;
}
if("EAG|SkinLayers".equals(payload.channel)) {
long millis = System.currentTimeMillis();
Long lsu = lastSkinLayerUpdate.get(user);
if(lsu != null && millis - lsu < 700L) { // DoS protection
return true;
}
lastSkinLayerUpdate.put(user, millis);
byte[] data;
if((data = capeCollection.get(user)) != null) {
data[1] = msg[0];
}else {
data = new byte[] { (byte)2, msg[0], (byte)0 };
capeCollection.put(user, data);
}
ByteArrayOutputStream bao = new ByteArrayOutputStream();
DataOutputStream dd = new DataOutputStream(bao);
dd.write(msg[0]);
dd.writeUTF(user);
byte[] bpacket = bao.toByteArray();
for(Object o : player.mcServer.getConfigurationManager().playerEntityList) {
EntityPlayerMP pl = (EntityPlayerMP) o;
if(!pl.username.equals(user)) {
pl.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|SkinLayers", bpacket));
}
}
return true;
}
}catch(Throwable t) {
// hacker
}
}
return false;
}
public static void handleDisconnect(EntityPlayerMP player) {
skinCollection.remove(player.username);
capeCollection.remove(player.username);
lastSkinLayerUpdate.remove(player.username);
}
public static void reset() {
skinCollection.clear();
capeCollection.clear();
lastSkinLayerUpdate.clear();
}
}

View File

@ -0,0 +1,290 @@
package net.lax1dude.eaglercraft.sp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import net.minecraft.server.MinecraftServer;
import net.minecraft.src.EntityPlayerMP;
import net.minecraft.src.Packet250CustomPayload;
public class VoiceChatPlugin {
private static final Map<String, EntityPlayerMP> voicePlayers = new HashMap<>();
private static final Map<String, ExpiringSet<String>> voiceRequests = new HashMap<>();
private static final Set<String[]> voicePairs = new HashSet<>();
private static final List<String> iceServers = new ArrayList();
private static final int VOICE_SIGNAL_ALLOWED = 0;
private static final int VOICE_SIGNAL_REQUEST = 0;
private static final int VOICE_SIGNAL_CONNECT = 1;
private static final int VOICE_SIGNAL_DISCONNECT = 2;
private static final int VOICE_SIGNAL_ICE = 3;
private static final int VOICE_SIGNAL_DESC = 4;
private static final int VOICE_SIGNAL_GLOBAL = 5;
public static boolean handleMessage(EntityPlayerMP player, Packet250CustomPayload payload) {
if ("EAG|Voice".equals(payload.channel) && payload.data.length > 0) {
deev: {
String user = player.username;
byte[] msg = payload.data;
try {
DataInputStream streamIn = new DataInputStream(new ByteArrayInputStream(msg));
int sig = streamIn.read();
switch (sig) {
case VOICE_SIGNAL_CONNECT:
if (voicePlayers.containsKey(user))
break deev; // user is already using voice chat
// send out packet for player joined voice
// notice: everyone on the server can see this packet!! however, it doesn't do
// anything but let clients know that the player has turned on voice chat
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.write(VOICE_SIGNAL_CONNECT);
dos.writeUTF(user);
byte[] out = baos.toByteArray();
for (EntityPlayerMP conn : voicePlayers.values())
conn.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", out));
voicePlayers.put(user, player);
for (String username : voicePlayers.keySet())
sendVoicePlayers(username);
break;
case VOICE_SIGNAL_DISCONNECT:
if (!voicePlayers.containsKey(user))
break deev; // user is not using voice chat
try {
String user2 = streamIn.readUTF();
if (!voicePlayers.containsKey(user2))
break deev;
if (removeIf(voicePairs, pair -> (pair[0].equals(user) && pair[1].equals(user2))
|| (pair[0].equals(user2) && pair[1].equals(user)))) {
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
DataOutputStream dos2 = new DataOutputStream(baos2);
dos2.write(VOICE_SIGNAL_DISCONNECT);
dos2.writeUTF(user);
voicePlayers.get(user2).playerNetServerHandler.sendPacket(
new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
baos2 = new ByteArrayOutputStream();
dos2 = new DataOutputStream(baos2);
dos2.write(VOICE_SIGNAL_DISCONNECT);
dos2.writeUTF(user2);
player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
}
} catch (EOFException e) {
removeUser(user);
}
break;
case VOICE_SIGNAL_REQUEST:
if (!voicePlayers.containsKey(user))
break deev; // user is not using voice chat
String targetUser = streamIn.readUTF();
if (user.equals(targetUser))
break deev; // prevent duplicates
if (checkVoicePair(user, targetUser))
break deev; // already paired
if (!voicePlayers.containsKey(targetUser))
break deev; // target user is not using voice chat
if (!voiceRequests.containsKey(user))
voiceRequests.put(user, new ExpiringSet<>(2000));
if (voiceRequests.get(user).contains(targetUser))
break deev;
voiceRequests.get(user).add(targetUser);
// check if other has requested earlier
if (voiceRequests.containsKey(targetUser) && voiceRequests.get(targetUser).contains(user)) {
if (voiceRequests.containsKey(targetUser)) {
voiceRequests.get(targetUser).remove(user);
if (voiceRequests.get(targetUser).isEmpty())
voiceRequests.remove(targetUser);
}
if (voiceRequests.containsKey(user)) {
voiceRequests.get(user).remove(targetUser);
if (voiceRequests.get(user).isEmpty())
voiceRequests.remove(user);
}
// send each other add data
voicePairs.add(new String[] { user, targetUser });
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
DataOutputStream dos2 = new DataOutputStream(baos2);
dos2.write(VOICE_SIGNAL_CONNECT);
dos2.writeUTF(user);
dos2.writeBoolean(false);
voicePlayers.get(targetUser).playerNetServerHandler.sendPacket(
new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
baos2 = new ByteArrayOutputStream();
dos2 = new DataOutputStream(baos2);
dos2.write(VOICE_SIGNAL_CONNECT);
dos2.writeUTF(targetUser);
dos2.writeBoolean(true);
player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
}
break;
case VOICE_SIGNAL_ICE:
case VOICE_SIGNAL_DESC:
if (!voicePlayers.containsKey(user))
break deev; // user is not using voice chat
String targetUser2 = streamIn.readUTF();
if (checkVoicePair(user, targetUser2)) {
String data = streamIn.readUTF();
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
DataOutputStream dos2 = new DataOutputStream(baos2);
dos2.write(sig);
dos2.writeUTF(user);
dos2.writeUTF(data);
player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos2.toByteArray()));
}
break;
default:
break;
}
} catch (Throwable t) {
// hacker
// t.printStackTrace(); // todo: remove in production
removeUser(user);
}
}
return true;
}
return false;
}
public static void activate(List<String> ice) {
if(iceServers.size() == 0) {
iceServers.clear();
iceServers.addAll(ice);
for(Object o : MinecraftServer.getServer().getConfigurationManager().playerEntityList) {
handleConnect((EntityPlayerMP) o);
}
}
}
public static void handleConnect(EntityPlayerMP player) {
if(iceServers.size() > 0) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.write(VOICE_SIGNAL_ALLOWED);
dos.writeBoolean(true);
dos.write(iceServers.size());
for (String str : iceServers) {
dos.writeUTF(str);
}
player.playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
sendVoicePlayers(player.username);
} catch (IOException ignored) {
}
}
}
public static void handleDisconnect(EntityPlayerMP player) {
removeUser(player.username);
}
private static void removeUser(String name) {
voicePlayers.remove(name);
for (String username : voicePlayers.keySet()) {
if (!name.equals(username))
sendVoicePlayers(username);
}
for (String[] voicePair : voicePairs) {
String target = null;
if (voicePair[0].equals(name)) {
target = voicePair[1];
} else if (voicePair[1].equals(name)) {
target = voicePair[0];
}
if (target != null && voicePlayers.containsKey(target)) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.write(VOICE_SIGNAL_DISCONNECT);
dos.writeUTF(name);
voicePlayers.get(target).playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
} catch (IOException ignored) {
}
}
}
removeIf(voicePairs, pair -> pair[0].equals(name) || pair[1].equals(name));
}
public static void reset() {
voicePlayers.clear();
voiceRequests.clear();
voicePairs.clear();
iceServers.clear();
}
private static void sendVoicePlayers(String name) {
if (!voicePlayers.containsKey(name))
return;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.write(VOICE_SIGNAL_GLOBAL);
Set<String> mostlyGlobalPlayers = new HashSet<>();
for (String username : voicePlayers.keySet()) {
if (username.equals(name))
continue;
if (anyMatch(voicePairs, pair -> (pair[0].equals(name) && pair[1].equals(username))
|| (pair[0].equals(username) && pair[1].equals(name))))
continue;
mostlyGlobalPlayers.add(username);
}
if (mostlyGlobalPlayers.size() > 0) {
dos.writeInt(mostlyGlobalPlayers.size());
for (String username : mostlyGlobalPlayers)
dos.writeUTF(username);
voicePlayers.get(name).playerNetServerHandler.sendPacket(new Packet250CustomPayload("EAG|Voice", baos.toByteArray()));
}
} catch (IOException ignored) {
}
}
private static boolean checkVoicePair(String user1, String user2) {
return anyMatch(voicePairs, pair -> (pair[0].equals(user1) && pair[1].equals(user2))
|| (pair[0].equals(user2) && pair[1].equals(user1)));
}
/**
* JDK 8 function not available in TeaVM
*/
private static <T> boolean removeIf(Collection<T> collection, Predicate<T> pre) {
boolean ret = false;
Iterator<T> itr = collection.iterator();
while(itr.hasNext()) {
if(pre.test(itr.next())) {
itr.remove();
ret = true;
}
}
return ret;
}
/**
* JDK 8 function not available in TeaVM
*/
private static <T> boolean anyMatch(Collection<T> collection, Predicate<T> pre) {
boolean ret = false;
Iterator<T> itr = collection.iterator();
while(itr.hasNext()) {
if(pre.test(itr.next())) {
return true;
}
}
return false;
}
}

View File

@ -7,6 +7,8 @@ import java.util.ArrayList;
import java.util.Iterator;
import net.lax1dude.eaglercraft.sp.EaglercraftRandom;
import net.lax1dude.eaglercraft.sp.SkinsPlugin;
import net.lax1dude.eaglercraft.sp.VoiceChatPlugin;
import net.minecraft.server.MinecraftServer;
public class NetServerHandler extends NetHandler {
@ -1005,6 +1007,12 @@ public class NetServerHandler extends NetHandler {
} else {
var14.updateItemName("");
}
} else {
if(!SkinsPlugin.handleMessage(playerEntity, par1Packet250CustomPayload)) {
if(!VoiceChatPlugin.handleMessage(playerEntity, par1Packet250CustomPayload)) {
System.err.println("Unexpected Packet250CustomPayload: '" + par1Packet250CustomPayload.channel + "'");
}
}
}
}
}

View File

@ -10,6 +10,8 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import net.lax1dude.eaglercraft.sp.SkinsPlugin;
import net.lax1dude.eaglercraft.sp.VoiceChatPlugin;
import net.minecraft.server.MinecraftServer;
public class ServerConfigurationManager {
@ -89,6 +91,7 @@ public class ServerConfigurationManager {
par2EntityPlayerMP.rotationYaw, par2EntityPlayerMP.rotationPitch);
//this.mcServer.getNetworkThread().addPlayer(var7);
var7.sendPacket(new Packet4UpdateTime(var5.getTotalWorldTime(), var5.getWorldTime()));
VoiceChatPlugin.handleConnect(par2EntityPlayerMP);
//if (this.mcServer.getTexturePack().length() > 0) {
// par2EntityPlayerMP.requestTexturePackLoad(this.mcServer.getTexturePack(), this.mcServer.textureSize());
@ -231,6 +234,8 @@ public class ServerConfigurationManager {
var2.getPlayerManager().removePlayer(par1EntityPlayerMP);
this.playerEntityList.remove(par1EntityPlayerMP);
this.sendPacketToAllPlayers(new Packet201PlayerInfo(par1EntityPlayerMP.username, false, 9999));
SkinsPlugin.handleDisconnect(par1EntityPlayerMP);
VoiceChatPlugin.handleDisconnect(par1EntityPlayerMP);
}
/**
@ -238,7 +243,16 @@ public class ServerConfigurationManager {
* on success, or an error message
*/
public String allowUserToConnect(String par2Str) {
return this.playerEntityList.size() >= this.maxPlayers ? "The server is full!" : null;
if(this.playerEntityList.size() >= this.maxPlayers) {
return "The server is full!";
}else {
for(EntityPlayerMP pp : (List<EntityPlayerMP>)this.playerEntityList) {
if(pp.username.equals(par2Str)) {
return "Someone with your username is already on this world";
}
}
return null;
}
}
/**
@ -854,8 +868,9 @@ public class ServerConfigurationManager {
this.sendPacketToAllPlayers(new Packet3Chat(par1Str));
}
public void configureLAN(int gamemode, boolean cheats) {
public void configureLAN(int gamemode, boolean cheats, List<String> iceServers) {
lanGamemode = EnumGameType.getByID(gamemode);
lanCheats = cheats;
VoiceChatPlugin.activate(iceServers);
}
}

View File

@ -6,6 +6,7 @@ import net.minecraft.src.GuiDisconnected;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.LoadingScreenRenderer;
import net.minecraft.src.NetClientHandler;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.Packet2ClientProtocol;
import net.minecraft.src.StringTranslate;
@ -78,6 +79,8 @@ public class GuiScreenLANConnecting extends GuiScreen {
this.mc.setNetManager(netMgr);
netMgr.setNetHandler(netHandler);
netHandler.addToSendQueue(new Packet2ClientProtocol(61, EaglerProfile.username, "127.0.0.1", mc.gameSettings.renderDistance));
netHandler.addToSendQueue(new Packet250CustomPayload("EAG|MySkin", EaglerProfile.getSkinPacket()));
netHandler.addToSendQueue(new Packet250CustomPayload("EAG|MyCape", EaglerProfile.getCapePacket()));
} catch (IOException e) {
this.mc.displayGuiScreen(new GuiDisconnected(parent, "connect.failed", "disconnect.genericReason", "could not create nethandler", ""));
e.printStackTrace();

View File

@ -7,6 +7,7 @@ import net.minecraft.src.GuiButton;
import net.minecraft.src.GuiDisconnected;
import net.minecraft.src.GuiScreen;
import net.minecraft.src.NetClientHandler;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.Packet2ClientProtocol;
import net.minecraft.src.WorldClient;
@ -58,6 +59,8 @@ public class GuiScreenSingleplayerConnecting extends GuiScreen {
netHandler = new NetClientHandler(mc, EaglerProfile.username);
this.mc.setNetManager(netHandler.getNetManager());
netHandler.addToSendQueue(new Packet2ClientProtocol(61, EaglerProfile.username, "127.0.0.1", mc.gameSettings.renderDistance));
netHandler.addToSendQueue(new Packet250CustomPayload("EAG|MySkin", EaglerProfile.getSkinPacket()));
netHandler.addToSendQueue(new Packet250CustomPayload("EAG|MyCape", EaglerProfile.getCapePacket()));
} catch (IOException e) {
this.mc.displayGuiScreen(new GuiDisconnected(this.menu, "connect.failed", "disconnect.genericReason", "could not create nethandler", ""));
e.printStackTrace();

View File

@ -439,7 +439,7 @@ public class IntegratedServer {
}
public static void configureLAN(EnumGameType enumGameType, boolean allowCommands) {
sendIPCPacket(new IPCPacket17ConfigureLAN(enumGameType.getID(), allowCommands));
sendIPCPacket(new IPCPacket17ConfigureLAN(enumGameType.getID(), allowCommands, IntegratedServerLAN.currentICEServers));
}
}

View File

@ -12,6 +12,8 @@ import net.lax1dude.eaglercraft.sp.relay.pkt.*;
public class IntegratedServerLAN {
public static final List<String> currentICEServers = new ArrayList();
private static RelayServerSocket lanRelaySocket = null;
private static String currentCode = null;
@ -42,13 +44,13 @@ public class IntegratedServerLAN {
if(pkt instanceof IPacket01ICEServers) {
IPacket01ICEServers ipkt = (IPacket01ICEServers)pkt;
System.out.println("Relay [" + sock.getURI() + "] provided ICE servers:");
List<String> servers = new ArrayList();
currentICEServers.clear();
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());
currentICEServers.add(srv.getICEString());
}
EaglerAdapter.serverLANInitializeServer(servers.toArray(new String[servers.size()]));
EaglerAdapter.serverLANInitializeServer(currentICEServers.toArray(new String[currentICEServers.size()]));
return currentCode = code;
}else {
System.err.println("Relay [" + sock.getURI() + "] unexpected packet: " + pkt.getClass().getSimpleName());

View File

@ -93,7 +93,7 @@ public class GuiIngameMenu extends GuiScreen {
*/
public void updateScreen() {
super.updateScreen();
if(!mc.isSingleplayer()) {
if(!mc.isSingleplayer() || IntegratedServerLAN.isHostingLAN()) {
voiceMenu.updateScreen();
}
}
@ -150,7 +150,7 @@ public class GuiIngameMenu extends GuiScreen {
}
try {
if(!mc.isSingleplayer()) {
if(!mc.isSingleplayer() || IntegratedServerLAN.isHostingLAN()) {
if(voiceMenu.isBlockingInput()) {
super.drawScreen(0, 0, par3);
}else {
@ -171,7 +171,7 @@ public class GuiIngameMenu extends GuiScreen {
*/
protected void keyTyped(char par1, int par2) {
try {
if(!mc.isSingleplayer()) {
if(!mc.isSingleplayer() || IntegratedServerLAN.isHostingLAN()) {
voiceMenu.keyTyped(par1, par2);
}
super.keyTyped(par1, par2);
@ -184,7 +184,7 @@ public class GuiIngameMenu extends GuiScreen {
*/
protected void mouseClicked(int par1, int par2, int par3) {
try {
if(!mc.isSingleplayer()) {
if(!mc.isSingleplayer() || IntegratedServerLAN.isHostingLAN()) {
voiceMenu.mouseClicked(par1, par2, par3);
}
if(par3 == 0) {
@ -223,7 +223,7 @@ public class GuiIngameMenu extends GuiScreen {
protected void mouseMovedOrUp(int par1, int par2, int par3) {
try {
if(!mc.isSingleplayer()) {
if(!mc.isSingleplayer() || IntegratedServerLAN.isHostingLAN()) {
voiceMenu.mouseMovedOrUp(par1, par2, par3);
}
super.mouseMovedOrUp(par1, par2, par3);

View File

@ -115,9 +115,9 @@ public class GuiShareToLan extends GuiScreen {
}
this.mc.displayGuiScreen((GuiScreen) null);
LoadingScreenRenderer ls = mc.loadingScreen;
IntegratedServer.configureLAN(EnumGameType.getByName(this.gameMode), this.allowCommands);
String code = IntegratedServerLAN.shareToLAN((str) -> ls.resetProgresAndWorkingMessage(str), worldName, hiddenToggle);
if (code != null) {
IntegratedServer.configureLAN(EnumGameType.getByName(this.gameMode), this.allowCommands);
this.mc.ingameGUI.getChatGUI().printChatMessage(StringTranslate.getInstance().translateKey("lanServer.opened")
.replace("$relay$", IntegratedServerLAN.getCurrentURI()).replace("$code$", code));
this.mc.lanState = true;

View File

@ -58,16 +58,22 @@ public class NetClientHandler extends NetHandler {
public NetClientHandler(Minecraft par1Minecraft, INetworkManager mgr) throws IOException {
this.mc = par1Minecraft;
this.netManager = mgr;
initializeVCHooks();
}
public NetClientHandler(Minecraft par1Minecraft, String channel) throws IOException {
this.mc = par1Minecraft;
this.netManager = IntegratedServer.openConnection(channel, this);
initializeVCHooks();
}
public NetClientHandler(Minecraft par1Minecraft, String par2Str, int par3) throws IOException {
this.mc = par1Minecraft;
this.netManager = new WebsocketNetworkManager(par2Str, null, this);
initializeVCHooks();
}
private void initializeVCHooks() {
EaglerAdapter.clearVoiceAvailableStatus();
EaglerAdapter.setVoiceSignalHandler(new Consumer<byte[]>() {
@Override
@ -78,13 +84,6 @@ public class NetClientHandler extends NetHandler {
if (EaglerAdapter.getVoiceChannel() != Voice.VoiceChannel.NONE) EaglerAdapter.sendInitialVoice();
}
//public NetClientHandler(Minecraft par1Minecraft, String par2Str, int par3, GuiScreen par4GuiScreen) throws IOException {
// this.mc = par1Minecraft;
// this.field_98183_l = par4GuiScreen;
// Socket var5 = new Socket(InetAddress.getByName(par2Str), par3);
// this.netManager = new TcpConnection(var5, "Client", this);
//}
/**
* sets netManager and worldClient to null
*/