added LAN skins and worked on LAN voice chat
This commit is contained in:
parent
dd02a35b48
commit
f42aac7664
35513
javascript/classes.js
35513
javascript/classes.js
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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -11,6 +11,8 @@ import net.lax1dude.eaglercraft.sp.ipc.IPCPacket0CPlayerChannel;
|
|||
import net.lax1dude.eaglercraft.sp.relay.pkt.*;
|
||||
|
||||
public class IntegratedServerLAN {
|
||||
|
||||
public static final List<String> currentICEServers = new ArrayList();
|
||||
|
||||
private static RelayServerSocket lanRelaySocket = 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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user