mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #42 - Fixed several WebRTC bugs and other issues
This commit is contained in:
@ -53,18 +53,23 @@ public class PlatformAudio {
|
||||
@Override
|
||||
public void pause(boolean setPaused) {
|
||||
if(setPaused) {
|
||||
if(sndSystem.playing(sourceName)) {
|
||||
if(!paused) {
|
||||
sndSystem.pause(sourceName);
|
||||
paused = true;
|
||||
}
|
||||
paused = true;
|
||||
}else {
|
||||
if(!sndSystem.playing(sourceName)) {
|
||||
if(paused) {
|
||||
sndSystem.play(sourceName);
|
||||
paused = false;
|
||||
}
|
||||
paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repeat(boolean en) {
|
||||
sndSystem.setLooping(sourceName, en);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restart() {
|
||||
this.stall = PlatformRuntime.steadyTimeMillis();
|
||||
@ -172,7 +177,7 @@ public class PlatformAudio {
|
||||
private static int sourceCounter = 0;
|
||||
|
||||
public static IAudioHandle beginPlayback(IAudioResource track, float x, float y, float z,
|
||||
float volume, float pitch) {
|
||||
float volume, float pitch, boolean repeat) {
|
||||
if(sndSystem == null) {
|
||||
return null;
|
||||
}
|
||||
@ -188,12 +193,13 @@ public class PlatformAudio {
|
||||
sndSystem.setTemporary(srcName, true);
|
||||
sndSystem.setPitch(srcName, pitch);
|
||||
sndSystem.setVolume(srcName, volume);
|
||||
sndSystem.setLooping(srcName, repeat);
|
||||
sndSystem.play(srcName);
|
||||
|
||||
return new PaulscodeAudioHandle(srcName);
|
||||
}
|
||||
|
||||
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch) {
|
||||
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch, boolean repeat) {
|
||||
if(sndSystem == null) {
|
||||
return null;
|
||||
}
|
||||
@ -204,6 +210,7 @@ public class PlatformAudio {
|
||||
sndSystem.setTemporary(srcName, true);
|
||||
sndSystem.setPitch(srcName, pitch);
|
||||
sndSystem.setVolume(srcName, volume);
|
||||
sndSystem.setLooping(srcName, repeat);
|
||||
sndSystem.play(srcName);
|
||||
|
||||
return new PaulscodeAudioHandle(srcName);
|
||||
|
@ -567,7 +567,11 @@ public class PlatformRuntime {
|
||||
public static InputStream newGZIPInputStream(InputStream is) throws IOException {
|
||||
return new GZIPInputStream(is);
|
||||
}
|
||||
|
||||
|
||||
public static void downloadRemoteURIByteArray(String assetPackageURI, boolean forceCache, final Consumer<byte[]> cb) {
|
||||
downloadRemoteURIByteArray(assetPackageURI, cb);
|
||||
}
|
||||
|
||||
public static void downloadRemoteURIByteArray(String assetPackageURI, final Consumer<byte[]> cb) {
|
||||
logger.info("Downloading: {}");
|
||||
try(InputStream is = (new URL(assetPackageURI)).openStream()) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState;
|
||||
|
||||
/**
|
||||
@ -89,28 +88,8 @@ public class PlatformVoiceClient {
|
||||
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerState() {
|
||||
return EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelReadyState getReadyState() {
|
||||
return EnumVoiceChannelReadyState.NONE;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateConnect() {
|
||||
return EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateInitial() {
|
||||
return EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateDesc() {
|
||||
return EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateIce() {
|
||||
return EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,18 +5,8 @@ import dev.onvoid.webrtc.internal.NativeLoader;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANPeerEvent;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayLoggerImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryRateLimitDummy;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerRateLimitTracker;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketRateLimitDummy;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryRateLimitDummy;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.json.JSONArray;
|
||||
@ -50,11 +40,8 @@ public class PlatformWebRTC {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("PlatformWebRTC");
|
||||
|
||||
private static final RelayLoggerImpl loggerImpl = new RelayLoggerImpl(LogManager.getLogger("RelayPacket"));
|
||||
|
||||
private static final Object lock1 = new Object();
|
||||
private static final Object lock2 = new Object();
|
||||
private static final Object lock3 = new Object();
|
||||
|
||||
private static final List<ScheduledRunnable> scheduledRunnables = new LinkedList<>();
|
||||
|
||||
@ -93,8 +80,6 @@ public class PlatformWebRTC {
|
||||
return supported;
|
||||
}
|
||||
|
||||
private static final Map<String, RTCDataChannel> fuckTeaVM = new HashMap<>();
|
||||
|
||||
private static final Comparator<ScheduledRunnable> sortTasks = (r1, r2) -> {
|
||||
return (int)(r1.runAt - r2.runAt);
|
||||
};
|
||||
@ -177,9 +162,17 @@ public class PlatformWebRTC {
|
||||
synchronized (lock1) {
|
||||
if (iceCandidate.sdp != null && !iceCandidate.sdp.isEmpty()) {
|
||||
if (iceCandidates.isEmpty()) {
|
||||
scheduleTask(3000l, () -> {
|
||||
final int[] candidateState = new int[2];
|
||||
final Runnable[] runnable = new Runnable[1];
|
||||
scheduleTask(2000l, runnable[0] = () -> {
|
||||
synchronized (lock1) {
|
||||
if (peerConnection != null && peerConnection.getConnectionState() != RTCPeerConnectionState.DISCONNECTED) {
|
||||
int trial = ++candidateState[1];
|
||||
if(candidateState[0] != iceCandidates.size() && trial < 3) {
|
||||
candidateState[0] = iceCandidates.size();
|
||||
scheduleTask(2000l, runnable[0]);
|
||||
return;
|
||||
}
|
||||
clientICECandidate = JSONWriter.valueToString(iceCandidates);
|
||||
iceCandidates.clear();
|
||||
}
|
||||
@ -382,6 +375,8 @@ public class PlatformWebRTC {
|
||||
public LANServer client;
|
||||
public String peerId;
|
||||
public RTCPeerConnection peerConnection;
|
||||
public RTCDataChannel dataChannel;
|
||||
public String ipcChannel;
|
||||
|
||||
public LANPeer(LANServer client, String peerId, RTCPeerConnection peerConnection) {
|
||||
this.client = client;
|
||||
@ -390,10 +385,9 @@ public class PlatformWebRTC {
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
synchronized (fuckTeaVM) {
|
||||
if (fuckTeaVM.get(peerId) != null) {
|
||||
fuckTeaVM.remove(peerId).close();
|
||||
}
|
||||
if(dataChannel != null) {
|
||||
dataChannel.close();
|
||||
dataChannel = null;
|
||||
}
|
||||
peerConnection.close();
|
||||
peerConnection = null;
|
||||
@ -472,16 +466,36 @@ public class PlatformWebRTC {
|
||||
client.signalRemoteDisconnect(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapIPC(String ipcChannel) {
|
||||
if(this.ipcChannel == null) {
|
||||
if(ipcChannel != null) {
|
||||
this.ipcChannel = ipcChannel;
|
||||
synchronized(this.client.ipcMapList) {
|
||||
this.client.ipcMapList.put(ipcChannel, this);
|
||||
}
|
||||
}
|
||||
}else {
|
||||
if(ipcChannel == null) {
|
||||
synchronized(this.client.ipcMapList) {
|
||||
this.client.ipcMapList.remove(this.ipcChannel);
|
||||
}
|
||||
this.ipcChannel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LANServer {
|
||||
public Set<Map<String, String>> iceServers = new HashSet<>();
|
||||
public Map<String, LANPeer> peerList = new HashMap<>();
|
||||
public Map<String, LANPeer> ipcMapList = new HashMap<>();
|
||||
public byte peerState = PEERSTATE_LOADING;
|
||||
public byte peerStateConnect = PEERSTATE_LOADING;
|
||||
public byte peerStateInitial = PEERSTATE_LOADING;
|
||||
public byte peerStateDesc = PEERSTATE_LOADING;
|
||||
public byte peerStateIce = PEERSTATE_LOADING;
|
||||
private final Object lock3 = new Object();
|
||||
|
||||
public void setIceServers(String[] urls) {
|
||||
iceServers.clear();
|
||||
@ -502,23 +516,28 @@ public class PlatformWebRTC {
|
||||
}
|
||||
|
||||
public void sendPacketToRemoteClient(String peerId, RTCDataChannelBuffer buffer) {
|
||||
LANPeer thePeer = this.peerList.get(peerId);
|
||||
LANPeer thePeer;
|
||||
synchronized(peerList) {
|
||||
thePeer = peerList.get(peerId);
|
||||
}
|
||||
if (thePeer != null) {
|
||||
boolean b = false;
|
||||
synchronized (fuckTeaVM) {
|
||||
if (fuckTeaVM.get(thePeer.peerId) != null && fuckTeaVM.get(thePeer.peerId).getState() == RTCDataChannelState.OPEN) {
|
||||
try {
|
||||
fuckTeaVM.get(thePeer.peerId).send(buffer);
|
||||
} catch (Throwable e) {
|
||||
b = true;
|
||||
}
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
if (b) {
|
||||
signalRemoteDisconnect(peerId);
|
||||
sendPacketToRemoteClient(thePeer, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPacketToRemoteClient(LANPeer thePeer, RTCDataChannelBuffer buffer) {
|
||||
boolean b = false;
|
||||
if(thePeer.dataChannel != null && thePeer.dataChannel.getState() == RTCDataChannelState.OPEN) {
|
||||
try {
|
||||
thePeer.dataChannel.send(buffer);
|
||||
} catch (Exception e) {
|
||||
b = true;
|
||||
}
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
if (b) {
|
||||
signalRemoteDisconnect(thePeer.peerId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,16 +556,25 @@ public class PlatformWebRTC {
|
||||
iceServer.password = server.getOrDefault("credential", null);
|
||||
rtcConfig.iceServers.add(iceServer);
|
||||
}
|
||||
RTCPeerConnection[] peerConnection = new RTCPeerConnection[1];
|
||||
final RTCPeerConnection[] peerConnection = new RTCPeerConnection[1];
|
||||
final LANPeer[] peerInstance = new LANPeer[1];
|
||||
peerConnection[0] = pcFactory.createPeerConnection(rtcConfig, new PeerConnectionObserver() {
|
||||
@Override
|
||||
public void onIceCandidate(RTCIceCandidate iceCandidate) {
|
||||
synchronized (lock3) {
|
||||
if (iceCandidate.sdp != null && !iceCandidate.sdp.isEmpty()) {
|
||||
if (iceCandidates.isEmpty()) {
|
||||
scheduleTask(3000l, () -> {
|
||||
final int[] candidateState = new int[2];
|
||||
final Runnable[] runnable = new Runnable[1];
|
||||
scheduleTask(2000l, runnable[0] = () -> {
|
||||
synchronized (lock3) {
|
||||
if (peerConnection[0] != null && peerConnection[0].getConnectionState() != RTCPeerConnectionState.DISCONNECTED) {
|
||||
int trial = ++candidateState[1];
|
||||
if(candidateState[0] != iceCandidates.size() && trial < 3) {
|
||||
candidateState[0] = iceCandidates.size();
|
||||
scheduleTask(2000l, runnable[0]);
|
||||
return;
|
||||
}
|
||||
LANPeerEvent.LANPeerICECandidateEvent e = new LANPeerEvent.LANPeerICECandidateEvent(peerId, JSONWriter.valueToString(iceCandidates));
|
||||
synchronized (serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
@ -582,9 +610,11 @@ public class PlatformWebRTC {
|
||||
return;
|
||||
}
|
||||
if (dataChannel == null) return;
|
||||
synchronized (fuckTeaVM) {
|
||||
fuckTeaVM.put(peerId, dataChannel);
|
||||
if(peerInstance[0].dataChannel != null) {
|
||||
dataChannel.close();
|
||||
return;
|
||||
}
|
||||
peerInstance[0].dataChannel = dataChannel;
|
||||
synchronized (serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, new LANPeerEvent.LANPeerDataChannelEvent(peerId));
|
||||
}
|
||||
@ -604,9 +634,14 @@ public class PlatformWebRTC {
|
||||
if (!buffer.binary) return;
|
||||
byte[] data = new byte[buffer.data.remaining()];
|
||||
buffer.data.get(data);
|
||||
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, data);
|
||||
synchronized (serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
LANPeer peer = peerInstance[0];
|
||||
if(peer.ipcChannel != null) {
|
||||
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(peer.ipcChannel, data));
|
||||
}else {
|
||||
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, data);
|
||||
synchronized (serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -627,8 +662,10 @@ public class PlatformWebRTC {
|
||||
}
|
||||
}
|
||||
});
|
||||
LANPeer peerInstance = new LANPeer(this, peerId, peerConnection[0]);
|
||||
peerList.put(peerId, peerInstance);
|
||||
peerInstance[0] = new LANPeer(this, peerId, peerConnection[0]);
|
||||
synchronized(peerList) {
|
||||
peerList.put(peerId, peerInstance[0]);
|
||||
}
|
||||
if (peerStateConnect != PEERSTATE_SUCCESS) peerStateConnect = PEERSTATE_SUCCESS;
|
||||
} catch (Throwable e) {
|
||||
if (peerStateConnect == PEERSTATE_LOADING) peerStateConnect = PEERSTATE_FAILED;
|
||||
@ -636,14 +673,20 @@ public class PlatformWebRTC {
|
||||
}
|
||||
|
||||
public void signalRemoteDescription(String peerId, String descJSON) {
|
||||
LANPeer thePeer = peerList.get(peerId);
|
||||
LANPeer thePeer;
|
||||
synchronized(peerList) {
|
||||
thePeer = peerList.get(peerId);
|
||||
}
|
||||
if (thePeer != null) {
|
||||
thePeer.setRemoteDescription(descJSON);
|
||||
}
|
||||
}
|
||||
|
||||
public void signalRemoteICECandidate(String peerId, String candidate) {
|
||||
LANPeer thePeer = peerList.get(peerId);
|
||||
LANPeer thePeer;
|
||||
synchronized(peerList) {
|
||||
thePeer = peerList.get(peerId);
|
||||
}
|
||||
if (thePeer != null) {
|
||||
thePeer.addICECandidate(candidate);
|
||||
}
|
||||
@ -651,7 +694,12 @@ public class PlatformWebRTC {
|
||||
|
||||
public void signalRemoteDisconnect(String peerId) {
|
||||
if (peerId == null || peerId.isEmpty()) {
|
||||
for (LANPeer thePeer : peerList.values()) {
|
||||
List<LANPeer> cpy;
|
||||
synchronized(peerList) {
|
||||
cpy = new ArrayList<>(peerList.values());
|
||||
peerList.clear();
|
||||
}
|
||||
for (LANPeer thePeer : cpy) {
|
||||
if (thePeer != null) {
|
||||
try {
|
||||
thePeer.disconnect();
|
||||
@ -662,55 +710,44 @@ public class PlatformWebRTC {
|
||||
}
|
||||
}
|
||||
}
|
||||
peerList.clear();
|
||||
synchronized (fuckTeaVM) {
|
||||
fuckTeaVM.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
LANPeer thePeer = peerList.get(peerId);
|
||||
LANPeer thePeer;
|
||||
synchronized(peerList) {
|
||||
thePeer = peerList.remove(peerId);
|
||||
}
|
||||
if (thePeer != null) {
|
||||
peerList.remove(peerId);
|
||||
if(thePeer.ipcChannel != null) {
|
||||
synchronized(ipcMapList) {
|
||||
ipcMapList.remove(thePeer.ipcChannel);
|
||||
}
|
||||
}
|
||||
try {
|
||||
thePeer.disconnect();
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
synchronized (fuckTeaVM) {
|
||||
fuckTeaVM.remove(peerId);
|
||||
}
|
||||
synchronized (serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(thePeer.peerId, new LANPeerEvent.LANPeerDisconnectEvent(peerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serverPeerMapIPC(String peer, String ipcChannel) {
|
||||
LANPeer peerr;
|
||||
synchronized(peerList) {
|
||||
peerr = peerList.get(peer);
|
||||
}
|
||||
if(peerr != null) {
|
||||
peerr.mapIPC(ipcChannel);
|
||||
}
|
||||
}
|
||||
|
||||
public int countPeers() {
|
||||
return peerList.size();
|
||||
synchronized(peerList) {
|
||||
return peerList.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
public static RelayQuery openRelayQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayWorldsQuery openRelayWorldsQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayWorldsQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayWorldsQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayServerSocket openRelayConnection(String addr, int timeout) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayServerSocketRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayServerSocketImpl(addr, timeout);
|
||||
}
|
||||
|
||||
private static LANClient rtcLANClient = null;
|
||||
|
||||
@ -883,6 +920,27 @@ public class PlatformWebRTC {
|
||||
rtcLANServer.signalRemoteDescription(peer, description);
|
||||
}
|
||||
|
||||
public static void serverLANPeerMapIPC(String peer, String ipcChannel) {
|
||||
rtcLANServer.serverPeerMapIPC(peer, ipcChannel);
|
||||
}
|
||||
|
||||
public static boolean serverLANPeerPassIPC(IPCPacketData ipcPacket) {
|
||||
if(rtcLANServer != null) {
|
||||
LANPeer peer;
|
||||
synchronized(rtcLANServer.ipcMapList) {
|
||||
peer = rtcLANServer.ipcMapList.get(ipcPacket.channel);
|
||||
}
|
||||
if(peer != null) {
|
||||
rtcLANServer.sendPacketToRemoteClient(peer, new RTCDataChannelBuffer(ByteBuffer.wrap(ipcPacket.contents), true));
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void serverLANDisconnectPeer(String peer) {
|
||||
rtcLANServer.signalRemoteDisconnect(peer);
|
||||
}
|
||||
@ -893,4 +951,5 @@ public class PlatformWebRTC {
|
||||
}
|
||||
return rtcLANServer.countPeers();
|
||||
}
|
||||
|
||||
}
|
@ -141,7 +141,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
UnsafeUtils.setMemByte(address + position + l, src.get());
|
||||
UnsafeUtils.setMemByte(address + position + i, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
UnsafeUtils.setMemFloat(address + ((position + l) << SHIFT), src.get());
|
||||
UnsafeUtils.setMemFloat(address + ((position + i) << SHIFT), src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public class EaglerLWJGLIntBuffer implements IntBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
|
||||
UnsafeUtils.setMemInt(address + ((position + i) << SHIFT), src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get());
|
||||
UnsafeUtils.setMemInt(address + ((position + i) << SHIFT), src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import net.lax1dude.eaglercraft.v1_8.Filesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IEaglerFilesystem;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DesktopClientConfigAdapter;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.internal.lwjgl.MemoryConnection;
|
||||
|
||||
@ -45,6 +46,9 @@ public class ServerPlatformSingleplayer {
|
||||
}
|
||||
|
||||
public static void sendPacket(IPCPacketData packet) {
|
||||
if(PlatformWebRTC.serverLANPeerPassIPC(packet)) {
|
||||
return;
|
||||
}
|
||||
synchronized(MemoryConnection.serverToClientQueue) {
|
||||
MemoryConnection.serverToClientQueue.add(packet);
|
||||
}
|
||||
|
@ -215,10 +215,12 @@ public class EagRuntime {
|
||||
}
|
||||
|
||||
public static void getStackTrace(Throwable t, Consumer<String> ret) {
|
||||
if(t == null) return;
|
||||
PlatformRuntime.getStackTrace(t, ret);
|
||||
}
|
||||
|
||||
public static String[] getStackTraceElements(Throwable t) {
|
||||
if(t == null) return new String[0];
|
||||
List<String> lst = new ArrayList<>();
|
||||
PlatformRuntime.getStackTrace(t, (s) -> {
|
||||
lst.add(s);
|
||||
@ -227,6 +229,9 @@ public class EagRuntime {
|
||||
}
|
||||
|
||||
public static String getStackTrace(Throwable t) {
|
||||
if(t == null) {
|
||||
return "[null]";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
getStackTrace0(t, sb);
|
||||
Throwable c = t.getCause();
|
||||
|
@ -21,7 +21,6 @@ import net.minecraft.client.audio.SoundHandler;
|
||||
import net.minecraft.client.audio.SoundPoolEntry;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ITickable;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@ -42,7 +41,7 @@ import net.minecraft.util.ResourceLocation;
|
||||
*/
|
||||
public class EaglercraftSoundManager {
|
||||
|
||||
protected static class ActiveSoundEvent {
|
||||
protected class ActiveSoundEvent {
|
||||
|
||||
protected final EaglercraftSoundManager manager;
|
||||
|
||||
@ -88,14 +87,11 @@ public class EaglercraftSoundManager {
|
||||
activeZ = z;
|
||||
}
|
||||
if(pitch != activePitch) {
|
||||
soundHandle.pitch(MathHelper.clamp_float(pitch * (float)soundConfig.getPitch(), 0.5f, 2.0f));
|
||||
soundHandle.pitch(EaglercraftSoundManager.this.getNormalizedPitch(soundInstance, soundConfig));
|
||||
activePitch = pitch;
|
||||
}
|
||||
if(gain != activeGain) {
|
||||
float attenuatedGain = gain * manager.categoryVolumes[SoundCategory.MASTER.getCategoryId()] *
|
||||
(soundCategory == SoundCategory.MASTER ? 1.0f : manager.categoryVolumes[soundCategory.getCategoryId()])
|
||||
* (float)soundConfig.getVolume();
|
||||
soundHandle.gain(MathHelper.clamp_float(attenuatedGain, 0.0f, 1.0f));
|
||||
soundHandle.gain(EaglercraftSoundManager.this.getNormalizedVolume(soundInstance, soundConfig, soundCategory));
|
||||
activeGain = gain;
|
||||
}
|
||||
}
|
||||
@ -152,10 +148,7 @@ public class EaglercraftSoundManager {
|
||||
ActiveSoundEvent evt = soundItr.next();
|
||||
if((category == SoundCategory.MASTER || evt.soundCategory == category)
|
||||
&& !evt.soundHandle.shouldFree()) {
|
||||
float newVolume = (evt.activeGain = evt.soundInstance.getVolume()) * categoryVolumes[SoundCategory.MASTER.getCategoryId()] *
|
||||
(evt.soundCategory == SoundCategory.MASTER ? 1.0f : categoryVolumes[evt.soundCategory.getCategoryId()])
|
||||
* (float)evt.soundConfig.getVolume();
|
||||
newVolume = MathHelper.clamp_float(newVolume, 0.0f, 1.0f);
|
||||
float newVolume = getNormalizedVolume(evt.soundInstance, evt.soundConfig, evt.soundCategory);
|
||||
if(newVolume > 0.0f) {
|
||||
evt.soundHandle.gain(newVolume);
|
||||
}else {
|
||||
@ -211,34 +204,34 @@ public class EaglercraftSoundManager {
|
||||
Iterator<ActiveSoundEvent> soundItr = activeSounds.iterator();
|
||||
while(soundItr.hasNext()) {
|
||||
ActiveSoundEvent evt = soundItr.next();
|
||||
if(!evt.paused && (evt.soundInstance instanceof ITickable)) {
|
||||
boolean persist = false;
|
||||
if(!evt.paused && (evt.soundInstance instanceof ITickableSound)) {
|
||||
boolean destroy = false;
|
||||
try {
|
||||
((ITickable)evt.soundInstance).update();
|
||||
if ((evt.soundInstance instanceof ITickableSound)
|
||||
&& ((ITickableSound) evt.soundInstance).isDonePlaying()) {
|
||||
ITickableSound snd = (ITickableSound) evt.soundInstance;
|
||||
lbl : {
|
||||
try {
|
||||
snd.update();
|
||||
if(snd.isDonePlaying()) {
|
||||
destroy = true;
|
||||
break lbl;
|
||||
}
|
||||
persist = true;
|
||||
}catch(Throwable t) {
|
||||
logger.error("Error ticking sound: {}", t.toString());
|
||||
logger.error(t);
|
||||
destroy = true;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
logger.error("Error ticking sound: {}", t.toString());
|
||||
logger.error(t);
|
||||
destroy = true;
|
||||
}
|
||||
if(destroy) {
|
||||
if(!evt.soundHandle.shouldFree()) {
|
||||
evt.soundHandle.end();
|
||||
}
|
||||
soundItr.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(evt.soundHandle.shouldFree()) {
|
||||
if(evt.soundInstance.canRepeat()) {
|
||||
if(!evt.paused && ++evt.repeatCounter > evt.soundInstance.getRepeatDelay()) {
|
||||
evt.repeatCounter = 0;
|
||||
evt.updateLocation();
|
||||
evt.soundHandle.restart();
|
||||
}
|
||||
}else {
|
||||
if(!persist) {
|
||||
soundItr.remove();
|
||||
}
|
||||
}else {
|
||||
@ -323,17 +316,16 @@ public class EaglercraftSoundManager {
|
||||
|
||||
ActiveSoundEvent newSound = new ActiveSoundEvent(this, sound, accessor.getSoundCategory(), etr, null);
|
||||
|
||||
float pitch = MathHelper.clamp_float(newSound.activePitch * (float)etr.getPitch(), 0.5f, 2.0f);
|
||||
float attenuatedGain = newSound.activeGain * categoryVolumes[SoundCategory.MASTER.getCategoryId()] *
|
||||
(accessor.getSoundCategory() == SoundCategory.MASTER ? 1.0f :
|
||||
categoryVolumes[accessor.getSoundCategory().getCategoryId()]) * (float)etr.getVolume();
|
||||
float pitch = getNormalizedPitch(sound, etr);
|
||||
float attenuatedGain = getNormalizedVolume(sound, etr, accessor.getSoundCategory());
|
||||
boolean repeat = sound.canRepeat();
|
||||
|
||||
AttenuationType tp = sound.getAttenuationType();
|
||||
if(tp == AttenuationType.LINEAR) {
|
||||
newSound.soundHandle = PlatformAudio.beginPlayback(trk, newSound.activeX, newSound.activeY,
|
||||
newSound.activeZ, attenuatedGain, pitch);
|
||||
newSound.activeZ, attenuatedGain, pitch, repeat);
|
||||
}else {
|
||||
newSound.soundHandle = PlatformAudio.beginPlaybackStatic(trk, attenuatedGain, pitch);
|
||||
newSound.soundHandle = PlatformAudio.beginPlaybackStatic(trk, attenuatedGain, pitch, repeat);
|
||||
}
|
||||
|
||||
if(newSound.soundHandle == null) {
|
||||
@ -351,6 +343,17 @@ public class EaglercraftSoundManager {
|
||||
queuedSounds.add(new WaitingSoundEvent(sound, delay));
|
||||
}
|
||||
|
||||
private float getNormalizedVolume(ISound sound, SoundPoolEntry entry, SoundCategory category) {
|
||||
return (float) MathHelper.clamp_double((double) sound.getVolume() * entry.getVolume(), 0.0D, 1.0D)
|
||||
* (category.getCategoryId() == SoundCategory.MASTER.getCategoryId() ? 1.0f
|
||||
: categoryVolumes[category.getCategoryId()])
|
||||
* categoryVolumes[SoundCategory.MASTER.getCategoryId()];
|
||||
}
|
||||
|
||||
private float getNormalizedPitch(ISound sound, SoundPoolEntry entry) {
|
||||
return MathHelper.clamp_float(sound.getPitch() * (float)entry.getPitch(), 0.5f, 2.0f);
|
||||
}
|
||||
|
||||
public void setListener(EntityPlayer player, float partialTicks) {
|
||||
if(!PlatformAudio.available()) {
|
||||
return;
|
||||
|
@ -10,7 +10,7 @@ public class EaglercraftVersion {
|
||||
/// Customize these to fit your fork:
|
||||
|
||||
public static final String projectForkName = "EaglercraftX";
|
||||
public static final String projectForkVersion = "u41";
|
||||
public static final String projectForkVersion = "u42";
|
||||
public static final String projectForkVendor = "lax1dude";
|
||||
|
||||
public static final String projectForkURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8";
|
||||
@ -20,20 +20,20 @@ public class EaglercraftVersion {
|
||||
public static final String projectOriginName = "EaglercraftX";
|
||||
public static final String projectOriginAuthor = "lax1dude";
|
||||
public static final String projectOriginRevision = "1.8";
|
||||
public static final String projectOriginVersion = "u41";
|
||||
public static final String projectOriginVersion = "u42";
|
||||
|
||||
public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace
|
||||
|
||||
// EPK Version Identifier
|
||||
|
||||
public static final String EPKVersionIdentifier = "u41"; // Set to null to disable EPK version check
|
||||
public static final String EPKVersionIdentifier = "u42"; // Set to null to disable EPK version check
|
||||
|
||||
// Updating configuration
|
||||
|
||||
public static final boolean enableUpdateService = true;
|
||||
|
||||
public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client";
|
||||
public static final int updateBundlePackageVersionInt = 41;
|
||||
public static final int updateBundlePackageVersionInt = 42;
|
||||
|
||||
public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName;
|
||||
|
||||
|
@ -16,7 +16,7 @@ package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
*
|
||||
*/
|
||||
public enum EnumPlatformType {
|
||||
DESKTOP("Desktop"), JAVASCRIPT("JavaScript"), ASM("ASM");
|
||||
DESKTOP("Desktop"), JAVASCRIPT("JavaScript"), WASM_GC("ASM");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
@ -21,6 +21,8 @@ public interface IAudioHandle {
|
||||
|
||||
void restart();
|
||||
|
||||
void repeat(boolean en);
|
||||
|
||||
void move(float x, float y, float z);
|
||||
|
||||
void pitch(float f);
|
||||
|
@ -283,7 +283,7 @@ public class EaglerFolderResourcePack extends AbstractResourcePack {
|
||||
return;
|
||||
}
|
||||
}
|
||||
PlatformRuntime.downloadRemoteURIByteArray(url, arr -> {
|
||||
PlatformRuntime.downloadRemoteURIByteArray(url, true, arr -> {
|
||||
ast.accept(() -> {
|
||||
if (arr == null) {
|
||||
cb.accept(null);
|
||||
|
@ -517,6 +517,8 @@ public class FontMappingHelper {
|
||||
return 253;
|
||||
case 9632:
|
||||
return 254;
|
||||
case 160:
|
||||
return 32; //nbsp
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -162,7 +162,6 @@ public class SingleplayerServerController implements ISaveFormat {
|
||||
}else {
|
||||
openLANChannels.add(ch);
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(ch, true));
|
||||
PlatformWebRTC.serverLANCreatePeer(ch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +287,8 @@ public class SingleplayerServerController implements ISaveFormat {
|
||||
logger.warn("Recieved {} byte packet on closed local player connection", packetData.contents.length);
|
||||
}
|
||||
}else {
|
||||
//logger.warn("Recieved packet on IPC channel '{}', forwarding to PlatformWebRTC even though the channel should be mapped", packetData.channel);
|
||||
// just to be safe
|
||||
PlatformWebRTC.serverLANWritePacket(packetData.channel, packetData.contents);
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,7 @@ import net.lax1dude.eaglercraft.v1_8.sp.WorkerStartupFailedException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket15Crashed;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket1CIssueDetected;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiSelectWorld;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
|
@ -151,7 +151,7 @@ public class GuiShareToLan extends GuiScreen {
|
||||
}
|
||||
this.mc.displayGuiScreen(null);
|
||||
LoadingScreenRenderer ls = mc.loadingScreen;
|
||||
String code = LANServerController.shareToLAN(ls::resetProgressAndMessage, worldName, hiddenToggle);
|
||||
String code = LANServerController.shareToLAN((msg) -> ls.eaglerShow(msg, null), worldName, hiddenToggle);
|
||||
if (code != null) {
|
||||
SingleplayerServerController.configureLAN(WorldSettings.GameType.getByName(this.gameMode), this.allowCommands);
|
||||
this.mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(I18n.format("lanServer.opened")
|
||||
|
@ -1,10 +1,8 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
@ -33,42 +31,26 @@ class LANClientPeer {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("LANClientPeer");
|
||||
|
||||
private static final int PRE = 0, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3, CONNECTED = 4, CLOSED = 5;
|
||||
private static final int PRE = 0, RECEIVED_ICE_CANDIDATE = 1, SENT_ICE_CANDIDATE = 2, RECEIVED_DESCRIPTION = 3,
|
||||
SENT_DESCRIPTION = 4, RECEIVED_SUCCESS = 5, CONNECTED = 6, CLOSED = 7;
|
||||
|
||||
protected final String clientId;
|
||||
|
||||
protected int state = PRE;
|
||||
protected boolean dead = false;
|
||||
|
||||
protected long startTime;
|
||||
|
||||
protected LANClientPeer(String clientId) {
|
||||
this.clientId = clientId;
|
||||
this.startTime = EagRuntime.steadyTimeMillis();
|
||||
PlatformWebRTC.serverLANCreatePeer(clientId);
|
||||
}
|
||||
|
||||
protected void handleICECandidates(String candidates) {
|
||||
if(state == SENT_DESCRIPTION) {
|
||||
PlatformWebRTC.serverLANPeerICECandidates(clientId, candidates);
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
do {
|
||||
PlatformWebRTC.runScheduledTasks();
|
||||
LANPeerEvent evt;
|
||||
if((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
|
||||
state = SENT_ICE_CANDIDATE;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for server ICE candidates", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20);
|
||||
}while(EagRuntime.steadyTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server ICE candidates for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
state = RECEIVED_ICE_CANDIDATE;
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket03ICECandidate for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
@ -77,27 +59,7 @@ class LANClientPeer {
|
||||
protected void handleDescription(String description) {
|
||||
if(state == PRE) {
|
||||
PlatformWebRTC.serverLANPeerDescription(clientId, description);
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
do {
|
||||
PlatformWebRTC.runScheduledTasks();
|
||||
LANPeerEvent evt;
|
||||
if((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new RelayPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description));
|
||||
state = SENT_DESCRIPTION;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for server description", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20);
|
||||
}while(EagRuntime.steadyTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server description for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
state = RECEIVED_DESCRIPTION;
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket04Description for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
@ -105,31 +67,8 @@ class LANClientPeer {
|
||||
|
||||
protected void handleSuccess() {
|
||||
if(state == SENT_ICE_CANDIDATE) {
|
||||
long millis = EagRuntime.steadyTimeMillis();
|
||||
do {
|
||||
PlatformWebRTC.runScheduledTasks();
|
||||
LANPeerEvent evt;
|
||||
while((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null && evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
|
||||
// skip ice candidates
|
||||
}
|
||||
if(evt != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
|
||||
SingleplayerServerController.openPlayerChannel(clientId);
|
||||
state = CONNECTED;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for connection", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20);
|
||||
}while(EagRuntime.steadyTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server description for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
state = RECEIVED_SUCCESS;
|
||||
}else if(state != CONNECTED) {
|
||||
logger.error("Relay [{}] unexpected IPacket05ClientSuccess for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
}
|
||||
@ -144,24 +83,67 @@ class LANClientPeer {
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
if(state == CONNECTED) {
|
||||
if(state != CLOSED) {
|
||||
if(state != CONNECTED && EagRuntime.steadyTimeMillis() - startTime > 10000l) {
|
||||
logger.info("LAN client '{}' handshake timed out", clientId);
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
List<LANPeerEvent> l = PlatformWebRTC.serverLANGetAllEvent(clientId);
|
||||
if(l == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<LANPeerEvent> itr = l.iterator();
|
||||
while(state == CONNECTED && itr.hasNext()) {
|
||||
LANPeerEvent evt = itr.next();
|
||||
if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
|
||||
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload));
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
read_loop: for(int i = 0, s = l.size(); i < s; ++i) {
|
||||
LANPeerEvent evt = l.get(i);
|
||||
if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.info("LAN client '{}' disconnected", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
switch(state) {
|
||||
case RECEIVED_ICE_CANDIDATE: {
|
||||
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new RelayPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
|
||||
state = SENT_ICE_CANDIDATE;
|
||||
continue read_loop;
|
||||
}
|
||||
}
|
||||
case RECEIVED_DESCRIPTION: {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new RelayPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description));
|
||||
state = SENT_DESCRIPTION;
|
||||
continue read_loop;
|
||||
}
|
||||
}
|
||||
case SENT_ICE_CANDIDATE:
|
||||
case RECEIVED_SUCCESS: {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
|
||||
SingleplayerServerController.openPlayerChannel(clientId);
|
||||
PlatformWebRTC.serverLANPeerMapIPC(clientId, clientId);
|
||||
state = CONNECTED;
|
||||
continue read_loop;
|
||||
}
|
||||
}
|
||||
case CONNECTED: {
|
||||
if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
|
||||
//logger.warn("Forwarding packet for '{}' to IPC channel manually, even though the channel should be mapped", clientId);
|
||||
// just to be safe
|
||||
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload));
|
||||
continue read_loop;
|
||||
}
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(state != CLOSED) {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import java.util.Set;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryDispatch;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.RelayPacket07LocalWorlds;
|
||||
@ -123,7 +124,7 @@ public class LANServerList {
|
||||
for(int i = 0, l = RelayManager.relayManager.count(); i < l; ++i) {
|
||||
RelayServer srv = RelayManager.relayManager.get(i);
|
||||
if(!lanServersQueryList.containsKey(srv.address) && !deadURIs.contains(srv.address)) {
|
||||
lanServersQueryList.put(srv.address, PlatformWebRTC.openRelayWorldsQuery(srv.address));
|
||||
lanServersQueryList.put(srv.address, RelayQueryDispatch.openRelayWorldsQuery(srv.address));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class RelayQueryDispatch {
|
||||
|
||||
public static RelayQuery openRelayQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayWorldsQuery openRelayWorldsQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayWorldsQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayWorldsQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayServerSocket openRelayConnection(String addr, int timeout) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayServerSocketRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayServerSocketImpl(addr, timeout);
|
||||
}
|
||||
|
||||
}
|
@ -89,7 +89,7 @@ public class RelayServer {
|
||||
public void ping() {
|
||||
if(PlatformWebRTC.supported()) {
|
||||
close();
|
||||
query = PlatformWebRTC.openRelayQuery(address);
|
||||
query = RelayQueryDispatch.openRelayQuery(address);
|
||||
queriedVersion = -1;
|
||||
queriedComment = null;
|
||||
queriedVendor = null;
|
||||
@ -142,7 +142,7 @@ public class RelayServer {
|
||||
}
|
||||
|
||||
public RelayServerSocket openSocket() {
|
||||
return PlatformWebRTC.openRelayConnection(address, Minecraft.getMinecraft().gameSettings.relayTimeout * 1000);
|
||||
return RelayQueryDispatch.openRelayConnection(address, Minecraft.getMinecraft().gameSettings.relayTimeout * 1000);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerOutputStream;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryDispatch;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.RelayPacket00Handshake;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@ -111,7 +111,7 @@ public class RelayUpdateChecker {
|
||||
private static void connect(RelayEntry socket) {
|
||||
try {
|
||||
socket.handshake = false;
|
||||
socket.currentSocket = PlatformWebRTC.openRelayConnection(socket.uri, 10000);
|
||||
socket.currentSocket = RelayQueryDispatch.openRelayConnection(socket.uri, 10000);
|
||||
if(socket.currentSocket.isClosed()) {
|
||||
socket.currentSocket = null;
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.voice;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public enum EnumVoiceChannelPeerState {
|
||||
FAILED, SUCCESS, LOADING;
|
||||
}
|
@ -20,6 +20,7 @@ import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.client.*;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketVoiceSignalGlobalEAG;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
|
||||
@ -133,23 +134,23 @@ public class VoiceClientController {
|
||||
}
|
||||
|
||||
public static void handleVoiceSignalPacketTypeConnect(EaglercraftUUID user, boolean offer) {
|
||||
PlatformVoiceClient.signalConnect(user, offer);
|
||||
if (voiceChannel != EnumVoiceChannelType.NONE) PlatformVoiceClient.signalConnect(user, offer);
|
||||
}
|
||||
|
||||
public static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) {
|
||||
sendPacketRequest(user);
|
||||
if (voiceChannel != EnumVoiceChannelType.NONE) sendPacketRequest(user);
|
||||
}
|
||||
|
||||
public static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) {
|
||||
PlatformVoiceClient.signalDisconnect(user, true);
|
||||
if (voiceChannel != EnumVoiceChannelType.NONE) PlatformVoiceClient.signalDisconnect(user, true);
|
||||
}
|
||||
|
||||
public static void handleVoiceSignalPacketTypeICECandidate(EaglercraftUUID user, String ice) {
|
||||
PlatformVoiceClient.signalICECandidate(user, ice);
|
||||
if (voiceChannel != EnumVoiceChannelType.NONE) PlatformVoiceClient.signalICECandidate(user, ice);
|
||||
}
|
||||
|
||||
public static void handleVoiceSignalPacketTypeDescription(EaglercraftUUID user, String desc) {
|
||||
PlatformVoiceClient.signalDescription(user, desc);
|
||||
if (voiceChannel != EnumVoiceChannelType.NONE) PlatformVoiceClient.signalDescription(user, desc);
|
||||
}
|
||||
|
||||
public static void tickVoiceClient(Minecraft mc) {
|
||||
@ -161,6 +162,11 @@ public class VoiceClientController {
|
||||
if (getVoiceChannel() != EnumVoiceChannelType.NONE && (getVoiceStatus() == EnumVoiceChannelStatus.CONNECTING || getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED)) {
|
||||
activateVoice((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey));
|
||||
|
||||
if(mc.isSingleplayer() && !LANServerController.isHostingLAN()) {
|
||||
setVoiceChannel(EnumVoiceChannelType.NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mc.theWorld != null && mc.thePlayer != null) {
|
||||
HashSet<EaglercraftUUID> seenPlayers = new HashSet<>();
|
||||
for (EntityPlayer player : mc.theWorld.playerEntities) {
|
||||
@ -209,7 +215,6 @@ public class VoiceClientController {
|
||||
public static void setVoiceChannel(EnumVoiceChannelType channel) {
|
||||
if (voiceChannel == channel) return;
|
||||
if (channel != EnumVoiceChannelType.NONE) PlatformVoiceClient.initializeDevices();
|
||||
PlatformVoiceClient.resetPeerStates();
|
||||
if (channel == EnumVoiceChannelType.NONE) {
|
||||
for (EaglercraftUUID uuid : nearbyPlayers) {
|
||||
PlatformVoiceClient.signalDisconnect(uuid, false);
|
||||
@ -261,13 +266,10 @@ public class VoiceClientController {
|
||||
return voiceChannel;
|
||||
}
|
||||
|
||||
private static boolean voicePeerErrored() {
|
||||
return PlatformVoiceClient.getPeerState() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateConnect() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateInitial() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateDesc() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateIce() == EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
public static EnumVoiceChannelStatus getVoiceStatus() {
|
||||
return (!isClientSupported() || !isServerSupported()) ? EnumVoiceChannelStatus.UNAVAILABLE :
|
||||
(PlatformVoiceClient.getReadyState() != EnumVoiceChannelReadyState.DEVICE_INITIALIZED ?
|
||||
EnumVoiceChannelStatus.CONNECTING : (voicePeerErrored() ? EnumVoiceChannelStatus.UNAVAILABLE : EnumVoiceChannelStatus.CONNECTED));
|
||||
EnumVoiceChannelStatus.CONNECTING : EnumVoiceChannelStatus.CONNECTED);
|
||||
}
|
||||
|
||||
private static boolean talkStatus = false;
|
||||
@ -352,35 +354,47 @@ public class VoiceClientController {
|
||||
}
|
||||
|
||||
public static void sendPacketICE(EaglercraftUUID peerId, String candidate) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalICEEAG(peerId.msb, peerId.lsb, candidate));
|
||||
if(packetSendCallback != null) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalICEEAG(peerId.msb, peerId.lsb, candidate));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacketDesc(EaglercraftUUID peerId, String desc) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDescEAG(peerId.msb, peerId.lsb, desc));
|
||||
if(packetSendCallback != null) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDescEAG(peerId.msb, peerId.lsb, desc));
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacketDisconnect() {
|
||||
if(protocolVersion <= 3) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV3EAG());
|
||||
}else {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV4EAG());
|
||||
if(packetSendCallback != null) {
|
||||
if(protocolVersion <= 3) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV3EAG());
|
||||
}else {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV4EAG());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacketDisconnectPeer(EaglercraftUUID peerId) {
|
||||
if(protocolVersion <= 3) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV3EAG(true, peerId.msb, peerId.lsb));
|
||||
}else {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectPeerV4EAG(peerId.msb, peerId.lsb));
|
||||
if(packetSendCallback != null) {
|
||||
if(protocolVersion <= 3) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectV3EAG(true, peerId.msb, peerId.lsb));
|
||||
}else {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalDisconnectPeerV4EAG(peerId.msb, peerId.lsb));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacketConnect() {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalConnectEAG());
|
||||
if(packetSendCallback != null) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalConnectEAG());
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacketRequest(EaglercraftUUID peerId) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalRequestEAG(peerId.msb, peerId.lsb));
|
||||
if(packetSendCallback != null) {
|
||||
packetSendCallback.accept(new CPacketVoiceSignalRequestEAG(peerId.msb, peerId.lsb));
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendPacketRequestIfNeeded(EaglercraftUUID uuid) {
|
||||
|
@ -1 +1 @@
|
||||
u41
|
||||
u42
|
@ -30,7 +30,6 @@
|
||||
<option class="_eaglercraftX_boot_menu_launch_conf_val_launch_type_opt" value="PEYTON_V1">PeytonPlayz585 Indev</option>
|
||||
<option class="_eaglercraftX_boot_menu_launch_conf_val_launch_type_opt" value="PEYTON_V2">PeytonPlayz585 Alpha/Beta</option>
|
||||
<option class="_eaglercraftX_boot_menu_launch_conf_val_launch_type_opt" value="STANDARD_OFFLINE_V1">Standard Offline</option>
|
||||
<option class="_eaglercraftX_boot_menu_launch_conf_val_launch_type_opt" value="IFRAME_SANDBOX_V1">IFrame HTML File</option>
|
||||
</select>
|
||||
</p>
|
||||
</div>
|
||||
|
Binary file not shown.
@ -1 +1 @@
|
||||
{"pluginName":"EaglercraftXBungee","pluginVersion":"1.3.2","pluginButton":"Download \"EaglerXBungee-1.3.2.jar\"","pluginFilename":"EaglerXBungee.zip"}
|
||||
{"pluginName":"EaglercraftXBungee","pluginVersion":"1.3.3","pluginButton":"Download \"EaglerXBungee-1.3.3.jar\"","pluginFilename":"EaglerXBungee.zip"}
|
Binary file not shown.
@ -119,7 +119,7 @@ public class PlatformApplication {
|
||||
});
|
||||
}
|
||||
|
||||
@JSBody(params = { "cb" }, script = "if(!navigator.clipboard) { cb(null); } else if (!navigator.clipboard.readText) cb(null); else navigator.clipboard.readText().then(function(s) { cb(s || null); }, function() { cb(null); });")
|
||||
@JSBody(params = { "cb" }, script = "if(!navigator.clipboard) { cb(null); } else if (!navigator.clipboard.readText) cb(null); else navigator.clipboard.readText().then(function(s) { cb((typeof s === \"string\") ? s : null); }, function(err) { cb(null); });")
|
||||
private static native void getClipboard1(StupidFunctionResolveString cb);
|
||||
|
||||
@JSBody(params = { "str" }, script = "if(navigator.clipboard) { navigator.clipboard.writeText(str); return true; } else { return false; }")
|
||||
@ -212,7 +212,7 @@ public class PlatformApplication {
|
||||
}
|
||||
|
||||
@JSBody(params = { "ctx", "buffer", "w", "h" }, script = "var imgData = ctx.createImageData(w, h); var ww = w * 4; for(var i = 0; i < h; ++i) { imgData.data.set(new Uint8ClampedArray(buffer, (h - i - 1) * ww, ww), i * ww); } ctx.putImageData(imgData, 0, 0);")
|
||||
private static native JSObject putImageData(CanvasRenderingContext2D ctx, ArrayBuffer buffer, int w, int h);
|
||||
private static native void putImageData(CanvasRenderingContext2D ctx, ArrayBuffer buffer, int w, int h);
|
||||
|
||||
@JSBody(params = { "cvs", "name", "parentElement" }, script =
|
||||
"var vigg = function(el, url){" +
|
||||
@ -474,7 +474,7 @@ public class PlatformApplication {
|
||||
}
|
||||
|
||||
@JSFunctor
|
||||
private static interface DownloadBytesBlobURLRevoke extends JSObject {
|
||||
static interface DownloadBytesBlobURLRevoke extends JSObject {
|
||||
void call();
|
||||
}
|
||||
|
||||
@ -507,6 +507,10 @@ public class PlatformApplication {
|
||||
downloadBytesImpl(str, blobHandle.toExternalForm(), blobHandle::release, PlatformRuntime.parent);
|
||||
}
|
||||
|
||||
static void downloadURLWithNameTeaVM(String str, String url, DownloadBytesBlobURLRevoke revoker) {
|
||||
downloadBytesImpl(str, url, revoker, PlatformRuntime.parent);
|
||||
}
|
||||
|
||||
public static void showDebugConsole() {
|
||||
DebugConsoleWindow.showDebugConsole();
|
||||
}
|
||||
|
@ -87,16 +87,19 @@ public class PlatformAudio {
|
||||
protected final PannerNode panner;
|
||||
protected final GainNode gain;
|
||||
protected float pitch;
|
||||
protected boolean repeat;
|
||||
protected boolean isPaused = false;
|
||||
protected boolean isEnded = false;
|
||||
protected boolean isDisposed = false;
|
||||
|
||||
public BrowserAudioHandle(BrowserAudioResource resource, AudioBufferSourceNode source, PannerNode panner,
|
||||
GainNode gain, float pitch) {
|
||||
GainNode gain, float pitch, boolean repeat) {
|
||||
this.resource = resource;
|
||||
this.source = source;
|
||||
this.panner = panner;
|
||||
this.gain = gain;
|
||||
this.pitch = pitch;
|
||||
this.repeat = repeat;
|
||||
source.setOnEnded(this);
|
||||
}
|
||||
|
||||
@ -115,6 +118,14 @@ public class PlatformAudio {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repeat(boolean en) {
|
||||
repeat = en;
|
||||
if(!isEnded) {
|
||||
source.setLoop(en);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restart() {
|
||||
if(isEnded) {
|
||||
@ -124,11 +135,21 @@ public class PlatformAudio {
|
||||
resource.cacheHit = PlatformRuntime.steadyTimeMillis();
|
||||
src.setBuffer(resource.buffer);
|
||||
src.getPlaybackRate().setValue(pitch);
|
||||
src.setLoop(repeat);
|
||||
source.disconnect();
|
||||
src.connect(panner == null ? gain : panner);
|
||||
if(isDisposed) {
|
||||
isDisposed = false;
|
||||
activeSounds.add(this);
|
||||
gain.connect(audioctx.getDestination());
|
||||
if(gameRecGain != null) {
|
||||
gain.connect(gameRecGain);
|
||||
}
|
||||
}
|
||||
source = src;
|
||||
source.start();
|
||||
}else {
|
||||
isPaused = false;
|
||||
source.getPlaybackRate().setValue(pitch);
|
||||
source.start(0.0);
|
||||
}
|
||||
@ -179,6 +200,12 @@ public class PlatformAudio {
|
||||
isEnded = true;
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
if(!isDisposed) {
|
||||
isDisposed = true;
|
||||
gain.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void initialize() {
|
||||
@ -304,10 +331,9 @@ public class PlatformAudio {
|
||||
gameRecGain = audioctx.createGain();
|
||||
gameRecGain.getGain().setValue(gameVol);
|
||||
for(BrowserAudioHandle handle : activeSounds) {
|
||||
if(handle.panner != null) {
|
||||
handle.panner.connect(gameRecGain);
|
||||
}else {
|
||||
try {
|
||||
handle.gain.connect(gameRecGain);
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
}
|
||||
PlatformVoiceClient.addRecordingDest(gameRecGain);
|
||||
@ -342,11 +368,7 @@ public class PlatformAudio {
|
||||
}
|
||||
for(BrowserAudioHandle handle : activeSounds) {
|
||||
try {
|
||||
if(handle.panner != null) {
|
||||
handle.panner.disconnect(gameRecGain);
|
||||
}else {
|
||||
handle.gain.disconnect(gameRecGain);
|
||||
}
|
||||
handle.gain.disconnect(gameRecGain);
|
||||
}catch(Throwable t) {
|
||||
}
|
||||
}
|
||||
@ -451,8 +473,10 @@ public class PlatformAudio {
|
||||
activeFreeTimer = millis;
|
||||
Iterator<BrowserAudioHandle> itr = activeSounds.iterator();
|
||||
while(itr.hasNext()) {
|
||||
if(itr.next().shouldFree()) {
|
||||
BrowserAudioHandle h = itr.next();
|
||||
if(h.shouldFree()) {
|
||||
itr.remove();
|
||||
h.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -460,6 +484,10 @@ public class PlatformAudio {
|
||||
|
||||
public static void flushAudioCache() {
|
||||
soundCache.clear();
|
||||
Iterator<BrowserAudioHandle> itr = activeSounds.iterator();
|
||||
while(itr.hasNext()) {
|
||||
itr.next().dispose();
|
||||
}
|
||||
activeSounds.clear();
|
||||
}
|
||||
|
||||
@ -468,13 +496,14 @@ public class PlatformAudio {
|
||||
}
|
||||
|
||||
public static IAudioHandle beginPlayback(IAudioResource track, float x, float y, float z,
|
||||
float volume, float pitch) {
|
||||
float volume, float pitch, boolean repeat) {
|
||||
BrowserAudioResource internalTrack = (BrowserAudioResource) track;
|
||||
internalTrack.cacheHit = PlatformRuntime.steadyTimeMillis();
|
||||
|
||||
AudioBufferSourceNode src = audioctx.createBufferSource();
|
||||
src.setBuffer(internalTrack.buffer);
|
||||
src.getPlaybackRate().setValue(pitch);
|
||||
src.setLoop(repeat);
|
||||
|
||||
PannerNode panner = audioctx.createPanner();
|
||||
panner.setPosition(x, y, z);
|
||||
@ -503,18 +532,19 @@ public class PlatformAudio {
|
||||
|
||||
src.start();
|
||||
|
||||
BrowserAudioHandle ret = new BrowserAudioHandle(internalTrack, src, panner, gain, pitch);
|
||||
BrowserAudioHandle ret = new BrowserAudioHandle(internalTrack, src, panner, gain, pitch, repeat);
|
||||
activeSounds.add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch) {
|
||||
public static IAudioHandle beginPlaybackStatic(IAudioResource track, float volume, float pitch, boolean repeat) {
|
||||
BrowserAudioResource internalTrack = (BrowserAudioResource) track;
|
||||
internalTrack.cacheHit = PlatformRuntime.steadyTimeMillis();
|
||||
|
||||
AudioBufferSourceNode src = audioctx.createBufferSource();
|
||||
src.setBuffer(internalTrack.buffer);
|
||||
src.getPlaybackRate().setValue(pitch);
|
||||
src.setLoop(repeat);
|
||||
|
||||
GainNode gain = audioctx.createGain();
|
||||
float v2 = volume;
|
||||
@ -529,7 +559,7 @@ public class PlatformAudio {
|
||||
|
||||
src.start();
|
||||
|
||||
BrowserAudioHandle ret = new BrowserAudioHandle(internalTrack, src, null, gain, pitch);
|
||||
BrowserAudioHandle ret = new BrowserAudioHandle(internalTrack, src, null, gain, pitch, repeat);
|
||||
activeSounds.add(ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ public class PlatformInput {
|
||||
if(tryGrabCursorHook()) return;
|
||||
int b = evt.getButton();
|
||||
b = b == 1 ? 2 : (b == 2 ? 1 : b);
|
||||
buttonStates[b] = true;
|
||||
if(b >= 0 && b < buttonStates.length) buttonStates[b] = true;
|
||||
int eventX = (int)(getOffsetX(evt, touchOffsetXTeaVM) * windowDPI);
|
||||
int eventY = windowHeight - (int)(getOffsetY(evt, touchOffsetYTeaVM) * windowDPI) - 1;
|
||||
synchronized(mouseEvents) {
|
||||
@ -348,7 +348,7 @@ public class PlatformInput {
|
||||
evt.stopPropagation();
|
||||
int b = evt.getButton();
|
||||
b = b == 1 ? 2 : (b == 2 ? 1 : b);
|
||||
buttonStates[b] = false;
|
||||
if(b >= 0 && b < buttonStates.length) buttonStates[b] = false;
|
||||
int eventX = (int)(getOffsetX(evt, touchOffsetXTeaVM) * windowDPI);
|
||||
int eventY = windowHeight - (int)(getOffsetY(evt, touchOffsetYTeaVM) * windowDPI) - 1;
|
||||
synchronized(mouseEvents) {
|
||||
@ -366,8 +366,10 @@ public class PlatformInput {
|
||||
evt.stopPropagation();
|
||||
mouseX = (int)(getOffsetX(evt, touchOffsetXTeaVM) * windowDPI);
|
||||
mouseY = windowHeight - (int)(getOffsetY(evt, touchOffsetYTeaVM) * windowDPI) - 1;
|
||||
mouseDX += evt.getMovementX();
|
||||
mouseDY += -evt.getMovementY();
|
||||
if(pointerLockFlag) {
|
||||
mouseDX += evt.getMovementX();
|
||||
mouseDY += -evt.getMovementY();
|
||||
}
|
||||
if(hasShownPressAnyKey) {
|
||||
int eventX = (int)(getOffsetX(evt, touchOffsetXTeaVM) * windowDPI);
|
||||
int eventY = windowHeight - (int)(getOffsetY(evt, touchOffsetYTeaVM) * windowDPI) - 1;
|
||||
@ -765,7 +767,7 @@ public class PlatformInput {
|
||||
win.addEventListener("gamepaddisconnected", gamepaddisconnected = new EventListener<GamepadEvent>() {
|
||||
@Override
|
||||
public void handleEvent(GamepadEvent evt) {
|
||||
if(evt.getGamepad() == selectedGamepad) {
|
||||
if(selectedGamepad != null && evt.getGamepad().getIndex() == selectedGamepad.getIndex()) {
|
||||
selectedGamepad = null;
|
||||
}
|
||||
enumerateGamepads();
|
||||
@ -1287,7 +1289,7 @@ public class PlatformInput {
|
||||
|
||||
public static int mouseGetDWheel() {
|
||||
int ret = (int)mouseDWheel;
|
||||
mouseDWheel = 0.0D;
|
||||
mouseDWheel -= ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -599,7 +599,11 @@ public class PlatformRuntime {
|
||||
}
|
||||
|
||||
public static void downloadRemoteURIByteArray(String assetPackageURI, final Consumer<byte[]> cb) {
|
||||
downloadRemoteURI(assetPackageURI, arr -> cb.accept(TeaVMUtils.wrapByteArrayBuffer(arr)));
|
||||
downloadRemoteURIByteArray(assetPackageURI, false, cb);
|
||||
}
|
||||
|
||||
public static void downloadRemoteURIByteArray(String assetPackageURI, boolean useCache, final Consumer<byte[]> cb) {
|
||||
downloadRemoteURI(assetPackageURI, useCache, arr -> cb.accept(TeaVMUtils.wrapByteArrayBuffer(arr)));
|
||||
}
|
||||
|
||||
public static void downloadRemoteURI(String assetPackageURI, final Consumer<ArrayBuffer> cb) {
|
||||
|
@ -3,7 +3,6 @@ package net.lax1dude.eaglercraft.v1_8.internal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.teavm.interop.Async;
|
||||
@ -16,7 +15,6 @@ import org.teavm.jso.browser.Window;
|
||||
import org.teavm.jso.canvas.CanvasRenderingContext2D;
|
||||
import org.teavm.jso.dom.events.Event;
|
||||
import org.teavm.jso.dom.events.EventListener;
|
||||
import org.teavm.jso.dom.html.HTMLAnchorElement;
|
||||
import org.teavm.jso.dom.html.HTMLCanvasElement;
|
||||
import org.teavm.jso.webaudio.MediaStream;
|
||||
|
||||
@ -193,19 +191,11 @@ public class PlatformScreenRecord {
|
||||
final String fileName = EaglercraftVersion.mainMenuStringB + " - " + EaglerProfile.getName() + " - " + fmt.format(new Date()) + "." + params.codec.fileExt;
|
||||
if("video/webm".equals(params.codec.container)) {
|
||||
FixWebMDurationJS.getRecUrl(evt, (int) (PlatformRuntime.steadyTimeMillis() - startTime), url -> {
|
||||
HTMLAnchorElement a = (HTMLAnchorElement) win.getDocument().createElement("a");
|
||||
a.setDownload(fileName);
|
||||
a.setHref(url);
|
||||
a.click();
|
||||
TeaVMUtils.freeDataURL(url);
|
||||
PlatformApplication.downloadURLWithNameTeaVM(fileName, url, () -> TeaVMUtils.freeDataURL(url));
|
||||
}, logger::info);
|
||||
}else {
|
||||
String url = TeaVMUtils.getDataURL(evt.getData());
|
||||
HTMLAnchorElement a = (HTMLAnchorElement) win.getDocument().createElement("a");
|
||||
a.setDownload(fileName);
|
||||
a.setHref(url);
|
||||
a.click();
|
||||
TeaVMUtils.freeDataURL(url);
|
||||
PlatformApplication.downloadURLWithNameTeaVM(fileName, url, () -> TeaVMUtils.freeDataURL(url));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelType;
|
||||
import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController;
|
||||
@ -179,32 +178,17 @@ public class PlatformVoiceClient {
|
||||
VoiceClientController.sendPacketDesc(peerId, JSON.stringify(desc));
|
||||
}, err -> {
|
||||
logger.error("Failed to set local description for \"{}\"! {}", peerId, err);
|
||||
if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerStateInitial = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
});
|
||||
}, err -> {
|
||||
logger.error("Failed to set create offer for \"{}\"! {}", peerId, err);
|
||||
if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerStateInitial = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
});
|
||||
}
|
||||
|
||||
TeaVMUtils.addEventListener(peerConnection, "connectionstatechange", (EventListener<Event>) evt -> {
|
||||
String cs = PlatformWebRTC.getConnectionState(peerConnection);
|
||||
if ("disconnected".equals(cs)) {
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
} else if ("connected".equals(cs)) {
|
||||
if (peerState != EnumVoiceChannelPeerState.SUCCESS) {
|
||||
peerState = EnumVoiceChannelPeerState.SUCCESS;
|
||||
}
|
||||
} else if ("failed".equals(cs)) {
|
||||
if (peerState == EnumVoiceChannelPeerState.LOADING) {
|
||||
peerState = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
if ("disconnected".equals(cs) || "failed".equals(cs)) {
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
}
|
||||
});
|
||||
@ -226,26 +210,21 @@ public class PlatformVoiceClient {
|
||||
PlatformWebRTC.createAnswer(peerConnection, desc -> {
|
||||
PlatformWebRTC.setLocalDescription(peerConnection, desc, () -> {
|
||||
VoiceClientController.sendPacketDesc(peerId, JSON.stringify(desc));
|
||||
if (peerStateDesc != EnumVoiceChannelPeerState.SUCCESS) peerStateDesc = EnumVoiceChannelPeerState.SUCCESS;
|
||||
}, err -> {
|
||||
logger.error("Failed to set local description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
});
|
||||
}, err -> {
|
||||
logger.error("Failed to create answer for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
});
|
||||
}
|
||||
}, err -> {
|
||||
logger.error("Failed to set remote description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
});
|
||||
} catch (Throwable err) {
|
||||
logger.error("Failed to parse remote description for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
}
|
||||
}
|
||||
@ -253,10 +232,8 @@ public class PlatformVoiceClient {
|
||||
public void addICECandidate(String candidate) {
|
||||
try {
|
||||
addIceCandidate(peerConnection, candidate);
|
||||
if (peerStateIce != EnumVoiceChannelPeerState.SUCCESS) peerStateIce = EnumVoiceChannelPeerState.SUCCESS;
|
||||
} catch (Throwable err) {
|
||||
logger.error("Failed to parse ice candidate for \"{}\"! {}", peerId, err.getMessage());
|
||||
if (peerStateIce == EnumVoiceChannelPeerState.LOADING) peerStateIce = EnumVoiceChannelPeerState.FAILED;
|
||||
signalDisconnect(VoicePeer.this, false);
|
||||
}
|
||||
}
|
||||
@ -269,11 +246,6 @@ public class PlatformVoiceClient {
|
||||
public static GainNode localMediaStreamGain;
|
||||
public static MediaStream localRawMediaStream;
|
||||
public static EnumVoiceChannelReadyState readyState = EnumVoiceChannelReadyState.NONE;
|
||||
public static EnumVoiceChannelPeerState peerState = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateConnect = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateInitial = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateDesc = EnumVoiceChannelPeerState.LOADING;
|
||||
public static EnumVoiceChannelPeerState peerStateIce = EnumVoiceChannelPeerState.LOADING;
|
||||
public static AudioContext microphoneVolumeAudioContext = null;
|
||||
|
||||
public static void setICEServers(String[] urls) {
|
||||
@ -348,43 +320,16 @@ public class PlatformVoiceClient {
|
||||
}
|
||||
}
|
||||
|
||||
public static void resetPeerStates() {
|
||||
peerState = peerStateConnect = peerStateInitial = peerStateDesc = peerStateIce = EnumVoiceChannelPeerState.LOADING;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerState() {
|
||||
return peerState;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateConnect() {
|
||||
return peerStateConnect;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateInitial() {
|
||||
return peerStateInitial;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateDesc() {
|
||||
return peerStateDesc;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelPeerState getPeerStateIce() {
|
||||
return peerStateIce;
|
||||
}
|
||||
|
||||
public static EnumVoiceChannelReadyState getReadyState() {
|
||||
return readyState;
|
||||
}
|
||||
|
||||
public static void signalConnect(EaglercraftUUID peerId, boolean offer) {
|
||||
if (!hasInit) initializeDevices();
|
||||
try {
|
||||
JSObject peerConnection = PlatformWebRTC.createRTCPeerConnection(JSONWriter.valueToString(iceServers));
|
||||
VoicePeer peerInstance = new VoicePeer(peerId, peerConnection, offer);
|
||||
peerList.put(peerId, peerInstance);
|
||||
if (peerStateConnect != EnumVoiceChannelPeerState.SUCCESS) peerStateConnect = EnumVoiceChannelPeerState.SUCCESS;
|
||||
} catch (Throwable e) {
|
||||
if (peerStateConnect == EnumVoiceChannelPeerState.LOADING) peerStateConnect = EnumVoiceChannelPeerState.FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,23 +4,15 @@ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANPeerEvent;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQueryRateLimitDummy;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerRateLimitTracker;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocketRateLimitDummy;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryImpl;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQueryRateLimitDummy;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONWriter;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSFunctor;
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.browser.TimerHandler;
|
||||
import org.teavm.jso.browser.Window;
|
||||
import org.teavm.jso.core.JSError;
|
||||
import org.teavm.jso.dom.events.Event;
|
||||
@ -326,8 +318,6 @@ public class PlatformWebRTC {
|
||||
@JSBody(params = { "sock", "buffer" }, script = "sock.send(buffer);")
|
||||
static native void nativeBinarySend(WebSocket sock, ArrayBuffer buffer);
|
||||
|
||||
private static final Map<String, JSObject> fuckTeaVM = new HashMap<>();
|
||||
|
||||
public static void runScheduledTasks() {
|
||||
|
||||
}
|
||||
@ -403,12 +393,20 @@ public class PlatformWebRTC {
|
||||
TeaVMUtils.addEventListener(peerConnection, "icecandidate", (EventListener<Event>) evt -> {
|
||||
if (hasCandidate(evt)) {
|
||||
if (iceCandidates.isEmpty()) {
|
||||
Window.setTimeout(() -> {
|
||||
final int[] candidateState = new int[2];
|
||||
final TimerHandler[] runnable = new TimerHandler[1];
|
||||
Window.setTimeout(runnable[0] = () -> {
|
||||
if (peerConnection != null && !"disconnected".equals(getConnectionState(peerConnection))) {
|
||||
int trial = ++candidateState[1];
|
||||
if(candidateState[0] != iceCandidates.size() && trial < 3) {
|
||||
candidateState[0] = iceCandidates.size();
|
||||
Window.setTimeout(runnable[0], 2000);
|
||||
return;
|
||||
}
|
||||
clientICECandidate = JSONWriter.valueToString(iceCandidates);
|
||||
iceCandidates.clear();
|
||||
}
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
}
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("sdpMLineIndex", "" + getSdpMLineIndex(evt));
|
||||
@ -506,6 +504,8 @@ public class PlatformWebRTC {
|
||||
public LANServer client;
|
||||
public String peerId;
|
||||
public JSObject peerConnection;
|
||||
public JSObject dataChannel;
|
||||
public String ipcChannel;
|
||||
|
||||
public LANPeer(LANServer client, String peerId, JSObject peerConnection) {
|
||||
this.client = client;
|
||||
@ -517,15 +517,23 @@ public class PlatformWebRTC {
|
||||
TeaVMUtils.addEventListener(peerConnection, "icecandidate", (EventListener<Event>) evt -> {
|
||||
if (hasCandidate(evt)) {
|
||||
if (iceCandidates.isEmpty()) {
|
||||
Window.setTimeout(() -> {
|
||||
final int[] candidateState = new int[2];
|
||||
final TimerHandler[] runnable = new TimerHandler[1];
|
||||
Window.setTimeout(runnable[0] = () -> {
|
||||
if (peerConnection != null && !"disconnected".equals(getConnectionState(peerConnection))) {
|
||||
int trial = ++candidateState[1];
|
||||
if(candidateState[0] != iceCandidates.size() && trial < 3) {
|
||||
candidateState[0] = iceCandidates.size();
|
||||
Window.setTimeout(runnable[0], 2000);
|
||||
return;
|
||||
}
|
||||
LANPeerEvent.LANPeerICECandidateEvent e = new LANPeerEvent.LANPeerICECandidateEvent(peerId, JSONWriter.valueToString(iceCandidates));
|
||||
synchronized(serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
}
|
||||
iceCandidates.clear();
|
||||
}
|
||||
}, 3000);
|
||||
}, 2000);
|
||||
}
|
||||
Map<String, String> m = new HashMap<>();
|
||||
m.put("sdpMLineIndex", "" + getSdpMLineIndex(evt));
|
||||
@ -542,16 +550,23 @@ public class PlatformWebRTC {
|
||||
}
|
||||
if (getChannel(evt) == null) return;
|
||||
JSObject dataChannel = getChannel(evt);
|
||||
synchronized(fuckTeaVM) {
|
||||
fuckTeaVM.put(peerId, dataChannel);
|
||||
if(this.dataChannel != null) {
|
||||
closeIt(dataChannel);
|
||||
return;
|
||||
}
|
||||
this.dataChannel = dataChannel;
|
||||
synchronized(serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, new LANPeerEvent.LANPeerDataChannelEvent(peerId));
|
||||
}
|
||||
TeaVMUtils.addEventListener(dataChannel, "message", (EventListener<Event>) evt2 -> {
|
||||
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, TeaVMUtils.wrapByteArrayBuffer(getData(evt2)));
|
||||
synchronized(serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
ArrayBuffer data = getData(evt2);
|
||||
if(ipcChannel != null) {
|
||||
ClientPlatformSingleplayer.sendPacketTeaVM(ipcChannel, data);
|
||||
}else {
|
||||
LANPeerEvent.LANPeerPacketEvent e = new LANPeerEvent.LANPeerPacketEvent(peerId, TeaVMUtils.wrapByteArrayBuffer(data));
|
||||
synchronized(serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(peerId, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -572,11 +587,8 @@ public class PlatformWebRTC {
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
synchronized(fuckTeaVM) {
|
||||
if (fuckTeaVM.get(peerId) != null) {
|
||||
closeIt(fuckTeaVM.get(peerId));
|
||||
fuckTeaVM.remove(peerId);
|
||||
}
|
||||
if(dataChannel != null) {
|
||||
closeIt(dataChannel);
|
||||
}
|
||||
closeIt(peerConnection);
|
||||
}
|
||||
@ -627,11 +639,26 @@ public class PlatformWebRTC {
|
||||
client.signalRemoteDisconnect(peerId);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapIPC(String ipcChannel) {
|
||||
if(this.ipcChannel == null) {
|
||||
if(ipcChannel != null) {
|
||||
this.ipcChannel = ipcChannel;
|
||||
this.client.ipcMapList.put(ipcChannel, this);
|
||||
}
|
||||
}else {
|
||||
if(ipcChannel == null) {
|
||||
this.client.ipcMapList.remove(this.ipcChannel);
|
||||
this.ipcChannel = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class LANServer {
|
||||
public Set<Map<String, String>> iceServers = new HashSet<>();
|
||||
public Map<String, LANPeer> peerList = new HashMap<>();
|
||||
public Map<String, LANPeer> ipcMapList = new HashMap<>();
|
||||
public byte peerState = PEERSTATE_LOADING;
|
||||
public byte peerStateConnect = PEERSTATE_LOADING;
|
||||
public byte peerStateInitial = PEERSTATE_LOADING;
|
||||
@ -659,21 +686,23 @@ public class PlatformWebRTC {
|
||||
public void sendPacketToRemoteClient(String peerId, ArrayBuffer buffer) {
|
||||
LANPeer thePeer = this.peerList.get(peerId);
|
||||
if (thePeer != null) {
|
||||
boolean b = false;
|
||||
synchronized(fuckTeaVM) {
|
||||
if (fuckTeaVM.get(thePeer.peerId) != null && "open".equals(getReadyState(fuckTeaVM.get(thePeer.peerId)))) {
|
||||
try {
|
||||
sendIt(fuckTeaVM.get(thePeer.peerId), buffer);
|
||||
} catch (Throwable e) {
|
||||
b = true;
|
||||
}
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
if(b) {
|
||||
signalRemoteDisconnect(peerId);
|
||||
sendPacketToRemoteClient(thePeer, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPacketToRemoteClient(LANPeer thePeer, ArrayBuffer buffer) {
|
||||
boolean b = false;
|
||||
if (thePeer.dataChannel != null && "open".equals(getReadyState(thePeer.dataChannel))) {
|
||||
try {
|
||||
sendIt(thePeer.dataChannel, buffer);
|
||||
} catch (Throwable e) {
|
||||
b = true;
|
||||
}
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
if(b) {
|
||||
signalRemoteDisconnect(thePeer.peerId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -719,26 +748,29 @@ public class PlatformWebRTC {
|
||||
}
|
||||
}
|
||||
peerList.clear();
|
||||
synchronized(fuckTeaVM) {
|
||||
fuckTeaVM.clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
LANPeer thePeer = peerList.get(peerId);
|
||||
LANPeer thePeer = peerList.remove(peerId);
|
||||
if(thePeer != null) {
|
||||
peerList.remove(peerId);
|
||||
if(thePeer.ipcChannel != null) {
|
||||
ipcMapList.remove(thePeer.ipcChannel);
|
||||
}
|
||||
try {
|
||||
thePeer.disconnect();
|
||||
} catch (Throwable ignored) {}
|
||||
synchronized(fuckTeaVM) {
|
||||
fuckTeaVM.remove(peerId);
|
||||
}
|
||||
synchronized(serverLANEventBuffer) {
|
||||
serverLANEventBuffer.put(thePeer.peerId, new LANPeerEvent.LANPeerDisconnectEvent(peerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serverPeerMapIPC(String peer, String ipcChannel) {
|
||||
LANPeer peerr = peerList.get(peer);
|
||||
if(peerr != null) {
|
||||
peerr.mapIPC(ipcChannel);
|
||||
}
|
||||
}
|
||||
|
||||
public int countPeers() {
|
||||
return peerList.size();
|
||||
}
|
||||
@ -759,30 +791,6 @@ public class PlatformWebRTC {
|
||||
void call(JSError err);
|
||||
}
|
||||
|
||||
public static RelayQuery openRelayQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayWorldsQuery openRelayWorldsQuery(String addr) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayWorldsQueryRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayWorldsQueryImpl(addr);
|
||||
}
|
||||
|
||||
public static RelayServerSocket openRelayConnection(String addr, int timeout) {
|
||||
RelayQuery.RateLimit limit = RelayServerRateLimitTracker.isLimited(addr);
|
||||
if(limit == RelayQuery.RateLimit.LOCKED || limit == RelayQuery.RateLimit.BLOCKED) {
|
||||
return new RelayServerSocketRateLimitDummy(limit);
|
||||
}
|
||||
return new RelayServerSocketImpl(addr, timeout);
|
||||
}
|
||||
|
||||
private static LANClient rtcLANClient = null;
|
||||
|
||||
public static void startRTCLANClient() {
|
||||
@ -806,7 +814,6 @@ public class PlatformWebRTC {
|
||||
rtcLANClient.signalRemoteDisconnect(false);
|
||||
}
|
||||
|
||||
// todo: ArrayBuffer version
|
||||
public static void clientLANSendPacket(byte[] pkt) {
|
||||
rtcLANClient.sendPacketToServer(TeaVMUtils.unwrapArrayBuffer(pkt));
|
||||
}
|
||||
@ -949,6 +956,24 @@ public class PlatformWebRTC {
|
||||
rtcLANServer.signalRemoteDescription(peer, description);
|
||||
}
|
||||
|
||||
public static void serverLANPeerMapIPC(String peer, String ipcChannel) {
|
||||
rtcLANServer.serverPeerMapIPC(peer, ipcChannel);
|
||||
}
|
||||
|
||||
public static boolean serverLANPeerPassIPC(String channelName, ArrayBuffer data) {
|
||||
if(rtcLANServer != null) {
|
||||
LANPeer peer = rtcLANServer.ipcMapList.get(channelName);
|
||||
if(peer != null) {
|
||||
rtcLANServer.sendPacketToRemoteClient(peer, data);
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void serverLANDisconnectPeer(String peer) {
|
||||
rtcLANServer.signalRemoteDisconnect(peer);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
dataView.setInt8(position + l, src.get());
|
||||
dataView.setInt8(position + i, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class EaglerArrayFloatBuffer implements FloatBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
typedArray.set(position + l, src.get());
|
||||
typedArray.set(position + i, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class EaglerArrayIntBuffer implements IntBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
typedArray.set(position + l, src.get());
|
||||
typedArray.set(position + i, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class EaglerArrayShortBuffer implements ShortBuffer {
|
||||
int l = src.remaining();
|
||||
if(position + l > limit) throw Buffer.makeIOOBE(position + l - 1);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
typedArray.set(position + l, src.get());
|
||||
typedArray.set(position + i, src.get());
|
||||
}
|
||||
position += l;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public class TeaVMUtils {
|
||||
@GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBuffer.class)
|
||||
public static native short[] wrapShortArrayBuffer(ArrayBuffer buf);
|
||||
|
||||
@InjectedBy(TeaVMUtilsUnwrapGenerator.UnwrapArrayBuffer.class)
|
||||
@GeneratedBy(TeaVMUtilsUnwrapGenerator.WrapArrayBufferView.class)
|
||||
public static native short[] wrapShortArrayBuffer(ArrayBufferView buf);
|
||||
|
||||
@Async
|
||||
@ -140,12 +140,8 @@ public class TeaVMUtils {
|
||||
Window.setTimeout(() -> cb.complete(null), millis);
|
||||
}
|
||||
|
||||
public static final Comparator<Touch> touchSortingComparator = (t1, t2) -> {
|
||||
return t1.getIdentifier() - t2.getIdentifier();
|
||||
};
|
||||
|
||||
public static final Comparator<OffsetTouch> touchSortingComparator2 = (t1, t2) -> {
|
||||
return t1.touch.getIdentifier() - t2.touch.getIdentifier();
|
||||
return t1.eventUID - t2.eventUID;
|
||||
};
|
||||
|
||||
public static List<OffsetTouch> toSortedTouchList(TouchList touchList, SortedTouchEvent.ITouchUIDMapper mapper,
|
||||
|
@ -16,6 +16,7 @@ import org.teavm.jso.workers.Worker;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMBlobURLManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMClientConfigAdapter;
|
||||
@ -101,6 +102,10 @@ public class ClientPlatformSingleplayer {
|
||||
return;
|
||||
}
|
||||
|
||||
if(PlatformWebRTC.serverLANPeerPassIPC(channel, buf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized(messageQueue) {
|
||||
messageQueue.add(new IPCPacketData(channel, TeaVMUtils.wrapByteArrayBuffer(buf)));
|
||||
}
|
||||
|
Reference in New Issue
Block a user