mirror of
https://github.com/darverdevs/BetterMultiPort.git
synced 2024-12-21 22:54:11 -08:00
Update to Latest Eaglercraft (As of 10/7/22)
This commit is contained in:
parent
7365f29c38
commit
9ff5e6b042
BIN
www/assets.epk
Normal file
BIN
www/assets.epk
Normal file
Binary file not shown.
19432
www/classes.js
Normal file
19432
www/classes.js
Normal file
File diff suppressed because it is too large
Load Diff
1
www/classes.js.map
Normal file
1
www/classes.js.map
Normal file
File diff suppressed because one or more lines are too long
16268
www/classes_server.js
Normal file
16268
www/classes_server.js
Normal file
File diff suppressed because it is too large
Load Diff
1
www/classes_server.js.map
Normal file
1
www/classes_server.js.map
Normal file
File diff suppressed because one or more lines are too long
779
www/eagswebrtc.js
Normal file
779
www/eagswebrtc.js
Normal file
|
@ -0,0 +1,779 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is the backend for voice channels and LAN servers in eaglercraft
|
||||||
|
|
||||||
|
it links with TeaVM EaglerAdapter at runtime
|
||||||
|
|
||||||
|
Copyright 2022 ayunami2000 & lax1dude. All rights reserved.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%% VOICE CODE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
window.initializeVoiceClient = (() => {
|
||||||
|
|
||||||
|
const READYSTATE_NONE = 0;
|
||||||
|
const READYSTATE_ABORTED = -1;
|
||||||
|
const READYSTATE_DEVICE_INITIALIZED = 1;
|
||||||
|
|
||||||
|
const PEERSTATE_FAILED = 0;
|
||||||
|
const PEERSTATE_SUCCESS = 1;
|
||||||
|
const PEERSTATE_LOADING = 2;
|
||||||
|
|
||||||
|
class EaglercraftVoicePeer {
|
||||||
|
|
||||||
|
constructor(client, peerId, peerConnection, offer) {
|
||||||
|
this.client = client;
|
||||||
|
this.peerId = peerId;
|
||||||
|
this.peerConnection = peerConnection;
|
||||||
|
this.stream = null;
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
this.peerConnection.addEventListener("icecandidate", (evt) => {
|
||||||
|
if(evt.candidate) {
|
||||||
|
self.client.iceCandidateHandler(self.peerId, JSON.stringify({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("track", (evt) => {
|
||||||
|
self.rawStream = evt.streams[0];
|
||||||
|
const aud = new Audio();
|
||||||
|
aud.autoplay = true;
|
||||||
|
aud.muted = true;
|
||||||
|
aud.onended = function() {
|
||||||
|
aud.remove();
|
||||||
|
};
|
||||||
|
aud.srcObject = self.rawStream;
|
||||||
|
self.client.peerTrackHandler(self.peerId, self.rawStream);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addStream(this.client.localMediaStream.stream);
|
||||||
|
if (offer) {
|
||||||
|
this.peerConnection.createOffer((desc) => {
|
||||||
|
const selfDesc = desc;
|
||||||
|
self.peerConnection.setLocalDescription(selfDesc, () => {
|
||||||
|
self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc));
|
||||||
|
if (self.client.peerStateInitial != PEERSTATE_SUCCESS) self.client.peerStateInitial = PEERSTATE_SUCCESS;
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateInitial == PEERSTATE_LOADING) self.client.peerStateInitial = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set create offer for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateInitial == PEERSTATE_LOADING) self.client.peerStateInitial = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("connectionstatechange", (evt) => {
|
||||||
|
if(self.peerConnection.connectionState === 'disconnected') {
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
} else if (self.peerConnection.connectionState === 'connected') {
|
||||||
|
if (self.client.peerState != PEERSTATE_SUCCESS) self.client.peerState = PEERSTATE_SUCCESS;
|
||||||
|
} else if (self.peerConnection.connectionState === 'failed') {
|
||||||
|
if (self.client.peerState == PEERSTATE_LOADING) self.client.peerState = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.peerConnection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
mute(muted) {
|
||||||
|
this.rawStream.getAudioTracks()[0].enabled = !muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteDescription(descJSON) {
|
||||||
|
const self = this;
|
||||||
|
try {
|
||||||
|
const remoteDesc = JSON.parse(descJSON);
|
||||||
|
this.peerConnection.setRemoteDescription(remoteDesc, () => {
|
||||||
|
if(remoteDesc.type == 'offer') {
|
||||||
|
self.peerConnection.createAnswer((desc) => {
|
||||||
|
const selfDesc = desc;
|
||||||
|
self.peerConnection.setLocalDescription(selfDesc, () => {
|
||||||
|
self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc));
|
||||||
|
if (self.client.peerStateDesc != PEERSTATE_SUCCESS) self.client.peerStateDesc = PEERSTATE_SUCCESS;
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to create answer for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set remote description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to parse remote description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addICECandidate(candidate) {
|
||||||
|
try {
|
||||||
|
this.peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(candidate)));
|
||||||
|
if (this.client.peerStateIce != PEERSTATE_SUCCESS) this.client.peerStateIce = PEERSTATE_SUCCESS;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to parse ice candidate for \"" + this.peerId + "\"! " + err);
|
||||||
|
if (this.client.peerStateIce == PEERSTATE_LOADING) this.client.peerStateIce = PEERSTATE_FAILED;
|
||||||
|
this.client.signalDisconnect(this.peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class EaglercraftVoiceClient {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.ICEServers = [];
|
||||||
|
this.hasInit = false;
|
||||||
|
this.peerList = new Map();
|
||||||
|
this.readyState = READYSTATE_NONE;
|
||||||
|
this.peerState = PEERSTATE_LOADING;
|
||||||
|
this.peerStateConnect = PEERSTATE_LOADING;
|
||||||
|
this.peerStateInitial = PEERSTATE_LOADING;
|
||||||
|
this.peerStateDesc = PEERSTATE_LOADING;
|
||||||
|
this.peerStateIce = PEERSTATE_LOADING;
|
||||||
|
this.iceCandidateHandler = null;
|
||||||
|
this.descriptionHandler = null;
|
||||||
|
this.peerTrackHandler = null;
|
||||||
|
this.peerDisconnectHandler = null;
|
||||||
|
this.microphoneVolumeAudioContext = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
voiceClientSupported() {
|
||||||
|
return typeof window.RTCPeerConnection !== "undefined" && typeof navigator.mediaDevices !== "undefined" &&
|
||||||
|
typeof navigator.mediaDevices.getUserMedia !== "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
|
setICEServers(urls) {
|
||||||
|
this.ICEServers.length = 0;
|
||||||
|
for(var i = 0; i < urls.length; ++i) {
|
||||||
|
var etr = urls[i].split(";");
|
||||||
|
if(etr.length == 1) {
|
||||||
|
this.ICEServers.push({ urls: etr[0] });
|
||||||
|
}else if(etr.length == 3) {
|
||||||
|
this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setICECandidateHandler(cb) {
|
||||||
|
this.iceCandidateHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDescriptionHandler(cb) {
|
||||||
|
this.descriptionHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPeerTrackHandler(cb) {
|
||||||
|
this.peerTrackHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPeerDisconnectHandler(cb) {
|
||||||
|
this.peerDisconnectHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateVoice(tk) {
|
||||||
|
if(this.hasInit) this.localRawMediaStream.getAudioTracks()[0].enabled = tk;
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeDevices() {
|
||||||
|
if(!this.hasInit) {
|
||||||
|
const self = this;
|
||||||
|
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => {
|
||||||
|
self.microphoneVolumeAudioContext = new AudioContext();
|
||||||
|
self.localRawMediaStream = stream;
|
||||||
|
self.localRawMediaStream.getAudioTracks()[0].enabled = false;
|
||||||
|
self.localMediaStream = self.microphoneVolumeAudioContext.createMediaStreamDestination();
|
||||||
|
self.localMediaStreamGain = self.microphoneVolumeAudioContext.createGain();
|
||||||
|
var localStreamIn = self.microphoneVolumeAudioContext.createMediaStreamSource(stream);
|
||||||
|
localStreamIn.connect(self.localMediaStreamGain);
|
||||||
|
self.localMediaStreamGain.connect(self.localMediaStream);
|
||||||
|
self.localMediaStreamGain.gain.value = 1.0;
|
||||||
|
self.readyState = READYSTATE_DEVICE_INITIALIZED;
|
||||||
|
this.hasInit = true;
|
||||||
|
}).catch((err) => {
|
||||||
|
self.readyState = READYSTATE_ABORTED;
|
||||||
|
});
|
||||||
|
}else {
|
||||||
|
this.readyState = READYSTATE_DEVICE_INITIALIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMicVolume(val) {
|
||||||
|
if(this.hasInit) {
|
||||||
|
if(val > 0.5) val = 0.5 + (val - 0.5) * 2.0;
|
||||||
|
if(val > 1.5) val = 1.5;
|
||||||
|
if(val < 0.0) val = 0.0;
|
||||||
|
this.localMediaStreamGain.gain.value = val * 2.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPeerStates() {
|
||||||
|
this.peerState = this.peerStateConnect = this.peerStateInitial = this.peerStateDesc = this.peerStateIce = PEERSTATE_LOADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerState() {
|
||||||
|
return this.peerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateConnect() {
|
||||||
|
return this.peerStateConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateInitial() {
|
||||||
|
return this.peerStateInitial;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateDesc() {
|
||||||
|
return this.peerStateDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateIce() {
|
||||||
|
return this.peerStateIce;
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadyState() {
|
||||||
|
return this.readyState;
|
||||||
|
}
|
||||||
|
|
||||||
|
signalConnect(peerId, offer) {
|
||||||
|
if (!this.hasInit) this.initializeDevices();
|
||||||
|
try {
|
||||||
|
const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] });
|
||||||
|
const peerInstance = new EaglercraftVoicePeer(this, peerId, peerConnection, offer);
|
||||||
|
this.peerList.set(peerId, peerInstance);
|
||||||
|
if (this.peerStateConnect != PEERSTATE_SUCCESS) this.peerStateConnect = PEERSTATE_SUCCESS;
|
||||||
|
} catch (e) {
|
||||||
|
if (this.peerStateConnect == PEERSTATE_LOADING) this.peerStateConnect = PEERSTATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalDescription(peerId, descJSON) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.setRemoteDescription(descJSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalDisconnect(peerId, quiet) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
this.peerList.delete(thePeer);
|
||||||
|
try {
|
||||||
|
thePeer.disconnect();
|
||||||
|
}catch(e) {}
|
||||||
|
this.peerDisconnectHandler(peerId, quiet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutePeer(peerId, muted) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.mute(muted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalICECandidate(peerId, candidate) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.addICECandidate(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.constructVoiceClient = () => new EaglercraftVoiceClient();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.startVoiceClient = () => {
|
||||||
|
if(typeof window.constructVoiceClient !== "function") {
|
||||||
|
window.initializeVoiceClient();
|
||||||
|
}
|
||||||
|
return window.constructVoiceClient();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%% LAN CLIENT CODE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
window.initializeLANClient = (() => {
|
||||||
|
|
||||||
|
const READYSTATE_INIT_FAILED = -2;
|
||||||
|
const READYSTATE_FAILED = -1;
|
||||||
|
const READYSTATE_DISCONNECTED = 0;
|
||||||
|
const READYSTATE_CONNECTING = 1;
|
||||||
|
const READYSTATE_CONNECTED = 2;
|
||||||
|
|
||||||
|
class EaglercraftLANClient {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.ICEServers = [];
|
||||||
|
this.peerConnection = null;
|
||||||
|
this.dataChannel = null;
|
||||||
|
this.readyState = READYSTATE_CONNECTING;
|
||||||
|
this.iceCandidateHandler = null;
|
||||||
|
this.descriptionHandler = null;
|
||||||
|
this.remoteDataChannelHandler = null;
|
||||||
|
this.remoteDisconnectHandler = null;
|
||||||
|
this.remotePacketHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LANClientSupported() {
|
||||||
|
return typeof window.RTCPeerConnection !== "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeClient() {
|
||||||
|
try {
|
||||||
|
if(this.dataChannel != null) {
|
||||||
|
this.dataChannel.close();
|
||||||
|
this.dataChannel = null;
|
||||||
|
}
|
||||||
|
if(this.peerConnection != null) {
|
||||||
|
this.peerConnection.close();
|
||||||
|
}
|
||||||
|
this.peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] });
|
||||||
|
this.readyState = READYSTATE_CONNECTING;
|
||||||
|
} catch (e) {
|
||||||
|
this.readyState = READYSTATE_INIT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setICEServers(urls) {
|
||||||
|
this.ICEServers.length = 0;
|
||||||
|
for(var i = 0; i < urls.length; ++i) {
|
||||||
|
var etr = urls[i].split(";");
|
||||||
|
if(etr.length == 1) {
|
||||||
|
this.ICEServers.push({ urls: etr[0] });
|
||||||
|
}else if(etr.length == 3) {
|
||||||
|
this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setICECandidateHandler(cb) {
|
||||||
|
this.iceCandidateHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDescriptionHandler(cb) {
|
||||||
|
this.descriptionHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteDataChannelHandler(cb) {
|
||||||
|
this.remoteDataChannelHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteDisconnectHandler(cb) {
|
||||||
|
this.remoteDisconnectHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemotePacketHandler(cb) {
|
||||||
|
this.remotePacketHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadyState() {
|
||||||
|
return this.readyState;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendPacketToServer(buffer) {
|
||||||
|
if(this.dataChannel != null && this.dataChannel.readyState == "open") {
|
||||||
|
this.dataChannel.send(buffer);
|
||||||
|
}else {
|
||||||
|
this.signalRemoteDisconnect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteConnect() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
const iceCandidates = [];
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("icecandidate", (evt) => {
|
||||||
|
if(evt.candidate) {
|
||||||
|
if(iceCandidates.length == 0) setTimeout(() => {
|
||||||
|
if(self.peerConnection != null && self.peerConnection.connectionState != "disconnected") {
|
||||||
|
self.iceCandidateHandler(JSON.stringify(iceCandidates));
|
||||||
|
iceCandidates.length = 0;
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
iceCandidates.push({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dataChannel = this.peerConnection.createDataChannel("lan");
|
||||||
|
this.dataChannel.binaryType = "arraybuffer";
|
||||||
|
|
||||||
|
this.dataChannel.addEventListener("open", async (evt) => {
|
||||||
|
while(iceCandidates.length > 0) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
|
}
|
||||||
|
self.remoteDataChannelHandler(self.dataChannel);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dataChannel.addEventListener("message", (evt) => {
|
||||||
|
self.remotePacketHandler(evt.data);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
this.peerConnection.createOffer((desc) => {
|
||||||
|
const selfDesc = desc;
|
||||||
|
self.peerConnection.setLocalDescription(selfDesc, () => {
|
||||||
|
self.descriptionHandler(JSON.stringify(selfDesc));
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description! " + err);
|
||||||
|
self.readyState = READYSTATE_FAILED;
|
||||||
|
self.signalRemoteDisconnect(false);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set create offer! " + err);
|
||||||
|
self.readyState = READYSTATE_FAILED;
|
||||||
|
self.signalRemoteDisconnect(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("connectionstatechange", (evt) => {
|
||||||
|
if(self.peerConnection.connectionState === 'disconnected') {
|
||||||
|
self.signalRemoteDisconnect(false);
|
||||||
|
} else if (self.peerConnection.connectionState === 'connected') {
|
||||||
|
self.readyState = READYSTATE_CONNECTED;
|
||||||
|
} else if (self.peerConnection.connectionState === 'failed') {
|
||||||
|
self.readyState = READYSTATE_FAILED;
|
||||||
|
self.signalRemoteDisconnect(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteDescription(descJSON) {
|
||||||
|
try {
|
||||||
|
this.peerConnection.setRemoteDescription(JSON.parse(descJSON));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.readyState = READYSTATE_FAILED;
|
||||||
|
this.signalRemoteDisconnect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteICECandidate(candidates) {
|
||||||
|
try {
|
||||||
|
const candidateList = JSON.parse(candidates);
|
||||||
|
for (let candidate of candidateList) {
|
||||||
|
this.peerConnection.addIceCandidate(candidate);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.readyState = READYSTATE_FAILED;
|
||||||
|
this.signalRemoteDisconnect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteDisconnect(quiet) {
|
||||||
|
if(this.dataChannel != null) {
|
||||||
|
this.dataChannel.close();
|
||||||
|
this.dataChannel = null;
|
||||||
|
}
|
||||||
|
if(this.peerConnection != null) {
|
||||||
|
this.peerConnection.close();
|
||||||
|
}
|
||||||
|
if(!quiet) this.remoteDisconnectHandler();
|
||||||
|
this.readyState = READYSTATE_DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
window.constructLANClient = () => new EaglercraftLANClient();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.startLANClient = () => {
|
||||||
|
if(typeof window.constructLANClient !== "function") {
|
||||||
|
window.initializeLANClient();
|
||||||
|
}
|
||||||
|
return window.constructLANClient();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%% LAN SERVER CODE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
window.initializeLANServer = (() => {
|
||||||
|
|
||||||
|
const PEERSTATE_FAILED = 0;
|
||||||
|
const PEERSTATE_SUCCESS = 1;
|
||||||
|
const PEERSTATE_LOADING = 2;
|
||||||
|
|
||||||
|
class EaglercraftLANPeer {
|
||||||
|
|
||||||
|
constructor(client, peerId, peerConnection) {
|
||||||
|
this.client = client;
|
||||||
|
this.peerId = peerId;
|
||||||
|
this.peerConnection = peerConnection;
|
||||||
|
this.dataChannel = null;
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
const iceCandidates = [];
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("icecandidate", (evt) => {
|
||||||
|
if(evt.candidate) {
|
||||||
|
if(iceCandidates.length == 0) setTimeout(() => {
|
||||||
|
if(self.peerConnection != null && self.peerConnection.connectionState != "disconnected") {
|
||||||
|
self.client.iceCandidateHandler(self.peerId, JSON.stringify(iceCandidates));
|
||||||
|
iceCandidates.length = 0;
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
iceCandidates.push({ sdpMLineIndex: evt.candidate.sdpMLineIndex, candidate: evt.candidate.candidate });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("datachannel", async (evt) => {
|
||||||
|
while(iceCandidates.length > 0) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 0));
|
||||||
|
}
|
||||||
|
self.dataChannel = evt.channel;
|
||||||
|
self.client.remoteClientDataChannelHandler(self.peerId, self.dataChannel);
|
||||||
|
self.dataChannel.addEventListener("message", (evt) => {
|
||||||
|
self.client.remoteClientPacketHandler(self.peerId, evt.data);
|
||||||
|
}, false);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("connectionstatechange", (evt) => {
|
||||||
|
if(self.peerConnection.connectionState === 'disconnected') {
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
} else if (self.peerConnection.connectionState === 'connected') {
|
||||||
|
if (self.client.peerState != PEERSTATE_SUCCESS) self.client.peerState = PEERSTATE_SUCCESS;
|
||||||
|
} else if (self.peerConnection.connectionState === 'failed') {
|
||||||
|
if (self.client.peerState == PEERSTATE_LOADING) self.client.peerState = PEERSTATE_FAILED;
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
if(this.dataChannel != null) {
|
||||||
|
this.dataChannel.close();
|
||||||
|
this.dataChannel = null;
|
||||||
|
}
|
||||||
|
this.peerConnection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteDescription(descJSON) {
|
||||||
|
const self = this;
|
||||||
|
try {
|
||||||
|
const remoteDesc = JSON.parse(descJSON);
|
||||||
|
this.peerConnection.setRemoteDescription(remoteDesc, () => {
|
||||||
|
if(remoteDesc.type == 'offer') {
|
||||||
|
self.peerConnection.createAnswer((desc) => {
|
||||||
|
const selfDesc = desc;
|
||||||
|
self.peerConnection.setLocalDescription(selfDesc, () => {
|
||||||
|
self.client.descriptionHandler(self.peerId, JSON.stringify(selfDesc));
|
||||||
|
if (self.client.peerStateDesc != PEERSTATE_SUCCESS) self.client.peerStateDesc = PEERSTATE_SUCCESS;
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to create answer for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set remote description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to parse remote description for \"" + self.peerId + "\"! " + err);
|
||||||
|
if (self.client.peerStateDesc == PEERSTATE_LOADING) self.client.peerStateDesc = PEERSTATE_FAILED;
|
||||||
|
self.client.signalRemoteDisconnect(self.peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addICECandidate(candidates) {
|
||||||
|
try {
|
||||||
|
const candidateList = JSON.parse(candidates);
|
||||||
|
for (let candidate of candidateList) {
|
||||||
|
this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
|
||||||
|
}
|
||||||
|
if (this.client.peerStateIce != PEERSTATE_SUCCESS) this.client.peerStateIce = PEERSTATE_SUCCESS;
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to parse ice candidate for \"" + this.peerId + "\"! " + err);
|
||||||
|
if (this.client.peerStateIce == PEERSTATE_LOADING) this.client.peerStateIce = PEERSTATE_FAILED;
|
||||||
|
this.client.signalRemoteDisconnect(this.peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class EaglercraftLANServer {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.ICEServers = [];
|
||||||
|
this.hasInit = false;
|
||||||
|
this.peerList = new Map();
|
||||||
|
this.peerState = PEERSTATE_LOADING;
|
||||||
|
this.peerStateConnect = PEERSTATE_LOADING;
|
||||||
|
this.peerStateInitial = PEERSTATE_LOADING;
|
||||||
|
this.peerStateDesc = PEERSTATE_LOADING;
|
||||||
|
this.peerStateIce = PEERSTATE_LOADING;
|
||||||
|
this.iceCandidateHandler = null;
|
||||||
|
this.descriptionHandler = null;
|
||||||
|
this.remoteClientDataChannelHandler = null;
|
||||||
|
this.remoteClientDisconnectHandler = null;
|
||||||
|
this.remoteClientPacketHandler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LANServerSupported() {
|
||||||
|
return typeof window.RTCPeerConnection !== "undefined";
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeServer() {
|
||||||
|
// nothing to do!
|
||||||
|
}
|
||||||
|
|
||||||
|
setICEServers(urls) {
|
||||||
|
this.ICEServers.length = 0;
|
||||||
|
for(var i = 0; i < urls.length; ++i) {
|
||||||
|
var etr = urls[i].split(";");
|
||||||
|
if(etr.length == 1) {
|
||||||
|
this.ICEServers.push({ urls: etr[0] });
|
||||||
|
}else if(etr.length == 3) {
|
||||||
|
this.ICEServers.push({ urls: etr[0], username: etr[1], credential: etr[2] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setICECandidateHandler(cb) {
|
||||||
|
this.iceCandidateHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDescriptionHandler(cb) {
|
||||||
|
this.descriptionHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteClientDataChannelHandler(cb) {
|
||||||
|
this.remoteClientDataChannelHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteClientDisconnectHandler(cb) {
|
||||||
|
this.remoteClientDisconnectHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteClientPacketHandler(cb) {
|
||||||
|
this.remoteClientPacketHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendPacketToRemoteClient(peerId, buffer) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
if(thePeer.dataChannel != null && thePeer.dataChannel.readyState == "open") {
|
||||||
|
thePeer.dataChannel.send(buffer);
|
||||||
|
}else {
|
||||||
|
this.signalRemoteDisconnect(peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPeerStates() {
|
||||||
|
this.peerState = this.peerStateConnect = this.peerStateInitial = this.peerStateDesc = this.peerStateIce = PEERSTATE_LOADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerState() {
|
||||||
|
return this.peerState;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateConnect() {
|
||||||
|
return this.peerStateConnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateInitial() {
|
||||||
|
return this.peerStateInitial;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateDesc() {
|
||||||
|
return this.peerStateDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeerStateIce() {
|
||||||
|
return this.peerStateIce;
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteConnect(peerId) {
|
||||||
|
try {
|
||||||
|
const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] });
|
||||||
|
const peerInstance = new EaglercraftLANPeer(this, peerId, peerConnection);
|
||||||
|
this.peerList.set(peerId, peerInstance);
|
||||||
|
if (this.peerStateConnect != PEERSTATE_SUCCESS) this.peerStateConnect = PEERSTATE_SUCCESS;
|
||||||
|
} catch (e) {
|
||||||
|
if (this.peerStateConnect == PEERSTATE_LOADING) this.peerStateConnect = PEERSTATE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteDescription(peerId, descJSON) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.setRemoteDescription(descJSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteICECandidate(peerId, candidate) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.addICECandidate(candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRemoteDisconnect(peerId) {
|
||||||
|
if(peerId.length == 0) {
|
||||||
|
for(const thePeer of this.peerList.values()) {
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
this.peerList.delete(peerId);
|
||||||
|
try {
|
||||||
|
thePeer.disconnect();
|
||||||
|
}catch(e) {}
|
||||||
|
this.remoteClientDisconnectHandler(peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.peerList.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
this.peerList.delete(peerId);
|
||||||
|
try {
|
||||||
|
thePeer.disconnect();
|
||||||
|
}catch(e) {}
|
||||||
|
this.remoteClientDisconnectHandler(peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
countPeers() {
|
||||||
|
return this.peerList.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
window.constructLANServer = () => new EaglercraftLANServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.startLANServer = () => {
|
||||||
|
if(typeof window.constructLANServer !== "function") {
|
||||||
|
window.initializeLANServer();
|
||||||
|
}
|
||||||
|
return window.constructLANServer();
|
||||||
|
};
|
63
www/index.html
Normal file
63
www/index.html
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>eagler</title>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<script type="text/javascript" src="eagswebrtc.js"></script>
|
||||||
|
<!--script type="text/javascript" src="music.js"></script-->
|
||||||
|
<script type="text/javascript" src="classes.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
if(document.location.href.startsWith("file:")) {
|
||||||
|
alert("You're not supposed to 'open' this file in your browser. Please upload this folder to your HTTP(s) server and access it via the internet. This is not a bug, please read the documentation");
|
||||||
|
}else {
|
||||||
|
window.addEventListener("load", async function(){
|
||||||
|
/*
|
||||||
|
let wardUrl = "";
|
||||||
|
try {
|
||||||
|
wardUrl = (await (await fetch("https://pipedapi.tokhmi.xyz/streams/5VuDwU4bW8Q")).json()).audioStreams[0].url;
|
||||||
|
} catch (e) {}
|
||||||
|
*/
|
||||||
|
const relayId = Math.floor(Math.random() * 3);
|
||||||
|
window.eaglercraftOpts = {
|
||||||
|
container: "game_frame", assetsURI: "assets.epk", serverWorkerURI: "worker_bootstrap.js", worldsFolder: "TEST",
|
||||||
|
assetOverrides: {
|
||||||
|
// "title/no-pano-blur.flag": "",
|
||||||
|
"records/wait.mp3": "wait.mp3",
|
||||||
|
"records/mellohi.mp3": "https://stream.nightride.fm/chillsynth.m4a",
|
||||||
|
"records/far.mp3": "https://stream.nightride.fm/nightride.m4a",
|
||||||
|
"records/cat.mp3": "http://usa9.fastcast4u.com/proxy/jamz?mp=/1",
|
||||||
|
"records/ward.mp3": "http://fr4.1mix.co.uk:8000/192h",
|
||||||
|
"records/strad.mp3": "http://listen.011fm.com:8028/stream15",
|
||||||
|
"records/blocks.mp3": "https://www.ophanim.net:8444/s/9780",
|
||||||
|
"records/13.mp3": "https://s2.radio.co/s2b2b68744/listen"
|
||||||
|
// "sounds/gta.mp3": "https://invidious.zapashcanon.fr/latest_version?itag=251&id=YRlIl6K6S88"
|
||||||
|
// "records/ward.mp3": wardUrl
|
||||||
|
// "sounds/gta.mp3": ""
|
||||||
|
},
|
||||||
|
servers: [
|
||||||
|
{ serverName: "Local Test Server", serverAddress: "localhost:25565", hideAddress: false }
|
||||||
|
],
|
||||||
|
relays: [
|
||||||
|
{ addr: "wss://relay.deev.is/", name: "lax1dude relay #1", primary: relayId == 0 },
|
||||||
|
{ addr: "wss://relay.lax1dude.net/", name: "lax1dude relay #2", primary: relayId == 1 },
|
||||||
|
{ addr: "wss://relay.shhnowisnottheti.me/", name: "ayunami relay #1", primary: relayId == 2 }
|
||||||
|
],
|
||||||
|
mainMenu: { splashes: [
|
||||||
|
"Darviglet!", "eaglerenophile!", "You Eagler!", "Yeeeeeee!", "yeee",
|
||||||
|
"EEEEEEEEE!", "You Darvig!", "You Vigg!", ":>", "|>", "You Yumpster!"
|
||||||
|
], eaglerLogo: false }};
|
||||||
|
(function(){
|
||||||
|
var q = window.location.search;
|
||||||
|
if(typeof q === 'string' && q.startsWith("?")) {
|
||||||
|
q = new URLSearchParams(q);
|
||||||
|
var s = q.get("server");
|
||||||
|
if(s) window.eaglercraftOpts.joinServer = s;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
main();
|
||||||
|
});}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="margin:0px;width:100vw;height:100vh;" id="game_frame">
|
||||||
|
</body>
|
||||||
|
</html>
|
122
www/music.js
Normal file
122
www/music.js
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
window.music = (function () {
|
||||||
|
let audio = new Audio();
|
||||||
|
let songs = [ "CW6CMFPAsF4", "gz1xq2qJnHs", "RUEWIG8zoa0", "n02zTn2d3rY", "FoFqBB0r9OI", "Ugb7GUtiyZ0", "3UFyc7zN9KY", "V6N_rL4fh6I", "iBZS6ad3Tlk", "Mnb2RhXL-nM", "lidx_2d4YOA", "ETQJZHYlc3g", "kRpRoTaNni0", "ACy5tHoNUoA", "OKoA2ppQMkw", "-jcOtAuGZC4", "-cJFVNZC4h8", "yLFX_7SH2tY", "oP6wOte3wZU", "MT7ssDlcN_c", "dOu3APclRkU", "CElWZz_oCsA", "8wr8eqro_OI", "OlLUtndzw7A", "HBYS5mBHie4", "5HxGK3DTUBQ", "_9qUu8IeabE", "QaRbalghKl4", "PtjgNhXWr2U", "OqJi_n3AcV4", "WFFF-jMyFaQ", "FD56t_0B9ig", "x6EATApss4k", "vLv3r1jtnmc", "VLbMXG8lvjI", "-5h9Q5PMHkw", "M0opHPn2bSQ", "XbuqB3uB6DI", "ZCJo8CDyqlQ", "A1-fM0s1Yt0", "zfKvnd-f4fA", "zsLT3JqfTn0", "YZlclPLX1Hw", "AYdyRPIo4ZA", "loeGmoYr3s4", "0qhoqXTUQlY", "7KtwWWJqDrM", "uIk_jGypR24", "G9z_DmhSKjM", "IFWYSOsAuL8", "DhUieLpc16A", "b9W22zhQdkA", "lpm7-aEXD7I", "YIp1S0VfJVI", "BSC6d81pvwE", "aZlOBCXgIVg", "sG2yDNSSwaY", "RiVZCDq--m4", "-NXEcmszXzQ", "N2SW_MWBa6w", "2k5dqgNT37g", "T0cGZD15UaA", "6qTBIAkd8ns", "2_GUQC4nCl8", "9LlH78J_3bc", "9Ty-qFZZPZk", "6EDS01Ipaow", "R3rzdj_aP3U", "3Ax6jTZlu_g", "8GW6sLrK40k", "mfegGiVUk58", "mLmFpLivDRE", "GOQEOkPsdcM", "a4LZg9vIGT0", "720HcvEvEC8", "2GBsmmzm2j0", "YbdcrJZBtu8", "x0qKH1hJePs", "Ub7y69hg4do", "hFal0LKZwnM", "PzJtShkAkwA", "rYHNB_lPSNc", "Mr-wV17WFZU", "sVnRScxzPlA", "MATIBHTbLkw", "8DrtpB5Me6s", "EdFyQOngYJs", "3RyqONKuRzk", "jBPqr_IsWvY", "f6dnBVhH8AY", "dAalyaoVGfE", "DYRvdzUJMr0", "qFjaDnnPbA4", "RM9O1HO4FLE", "NrlhbIzjO04", "F6NNMAoBMS4", "UqVW7-q7fTA", "eDBAdAzCqr4", "EPT3dIWBbDA", "FuMtDXkuxVw", "PkmKM_OXNZM", "KbC46oJmLh4", "8HW9fyQdib4", "mRJSIYmHuNI", "GmLsIivtcIM", "rDBbaGCCIhk", "EyicJOlYOm4", "BDIG46sPKCs", "Ig5v4jhLLWI", "XZcG2esvW7I", "TTJBevUIp0s", "agIayif-oi0", "plm3DVsX7Jg", "yP7dvyK5OiY", "HA0Mk5BXX44", "HbtwR1REaFk", "-tUJJXWXdXk", "h-b8Xs7sNI0", "eyp-YuzhTN4", "xrawoRF4lN0", "6xVHpgJbuc8", "IdeMjEYeH_M", "mLFfI13jfeE", "fYSUV33ZPfw", "qnSHJlRJ2cM", "Ytt1_ErIV34", "_DBfb0-A6T0", "05TnpE0x4wI", "px-UnYP1smo", "dRAKbbYlTcI", "MYC5k-EvYyI", "GCkyGVsIcF0", "Qg83cniiYEY", "F7gwcgmoREg", "3I-WJ6UgmOA", "RakcYpzOI8A", "Tx0dUDrh_hE", "uRdnCC5kACY", "phrpiLpaiLs", "sLwHrqW-x4w", "wf93JAZR3gU", "7tBQFpFyZiI", "zz3F5j8qWNw", "Q7miO-Q-4bU", "j5FcOo48HpE", "CQLvggJFxuM", "_Ci0Kgdpgsw", "XYXUi4bn1pQ", "iBjZshhpipg", "-yXzE7undI4", "zEf46ulVSL0", "UBIsi3xWa64", "GWYkh1IX4PE", "n1hChZS9Hew", "YYjDFXJ6Wdo", "qOVxQ_yEYks", "9zibDnOOj3w", "rQMd3b1BF50", "xeM40-FkRLI", "wVOFnTrSOOA", "msUarvc4Sx8", "GB9kBLre96M", "p_wcC1l1cLk", "zKavYMyPveI", "YZ3no2EK58Y", "SLFMiEAjSoA", "K5F-RLzLH6Q", "A09BhpgfGKQ", "ziAK1OLeeEE", "7Vj-xVb0DWI", "33zGN7vENog", "zD8TxUBkjGA", "m0zPkt5BZ9I", "xktxgo7b8HQ", "jMSiM6iZpwk", "zeTIG5lwDyM", "CUHYQ-FN3P8", "GLGjqtgCKY8", "bLagC2wX3Ak", "fW128GHFJIE", "B5L0AMO2HA8", "oFFFzMkGNrk", "1RQQLwnaw80", "byUipqLQ_Hc", "_Rjh6zVEPH4", "R9z5CoO7Qxo", "neEq14x7mTU", "pkkIqT9LpDY", "BLRk8D7ovDY", "gMGEyl5TRa4" ];
|
||||||
|
let insturl = "https://invidious.zapashcanon.fr";
|
||||||
|
let loading = false;
|
||||||
|
let usealt = 0;
|
||||||
|
|
||||||
|
function shuffle (array) {
|
||||||
|
for (let i = 0; i < array.length; i++) {
|
||||||
|
let j = Math.floor(Math.random() * (array.length-i)) + i;
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixfard (url) {
|
||||||
|
if (!url) return insturl;
|
||||||
|
return url.endsWith("/") ? url.slice(0, url.length - 1) : url;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updinsturl = async () => {
|
||||||
|
try {
|
||||||
|
const json = await (await fetch("https://api.invidious.io/instances.json?sort_by=health")).json();
|
||||||
|
const out = shuffle(json).map(entry => {
|
||||||
|
const healthKnown = !!entry[1].monitor
|
||||||
|
return {
|
||||||
|
name: entry[0],
|
||||||
|
details: entry[1],
|
||||||
|
health: +(healthKnown ? entry[1].monitor.dailyRatios[0].ratio : 95),
|
||||||
|
healthKnown
|
||||||
|
}
|
||||||
|
}).filter(entry => {
|
||||||
|
return entry.details.type === "https" && entry.health > 0
|
||||||
|
}).sort((a, b) => {
|
||||||
|
return b.health - a.health
|
||||||
|
});
|
||||||
|
insturl = fixfard(out.find(e => e.details.cors).details.uri);
|
||||||
|
} catch (e) { aud.onerror(); }
|
||||||
|
};
|
||||||
|
const updint = setInterval(updinsturl, 3600000);
|
||||||
|
updinsturl();
|
||||||
|
|
||||||
|
audio.onended = function (e) {
|
||||||
|
loading = true;
|
||||||
|
start();
|
||||||
|
};
|
||||||
|
|
||||||
|
audio.oncanplay = function (e) {
|
||||||
|
if (loading) audio.play();
|
||||||
|
};
|
||||||
|
|
||||||
|
audio.onplay = function (e) {
|
||||||
|
loading = false;
|
||||||
|
if (usealt == 1) usealt = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
audio.onerror = function (e) {
|
||||||
|
if (usealt == 3) {
|
||||||
|
audio = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usealt == 0 || usealt == 1) {
|
||||||
|
usealt++;
|
||||||
|
} else if (usealt == 2) {
|
||||||
|
loading = true;
|
||||||
|
usealt = 3;
|
||||||
|
}
|
||||||
|
stop();
|
||||||
|
if (usealt == 1) {
|
||||||
|
updinsturl();
|
||||||
|
} else {
|
||||||
|
clearInterval(updint);
|
||||||
|
}
|
||||||
|
if (usealt == 1 || usealt == 2) start();
|
||||||
|
};
|
||||||
|
|
||||||
|
const playing = function () {
|
||||||
|
return usealt == 3 || (!audio.paused) || loading;
|
||||||
|
};
|
||||||
|
|
||||||
|
const start = function() {
|
||||||
|
loading = true;
|
||||||
|
let url = "";
|
||||||
|
if (usealt == 0 || usealt == 1) {
|
||||||
|
songs = shuffle(songs);
|
||||||
|
url = insturl + "/latest_version?id=" + songs[0] + "&itag=251";
|
||||||
|
} else if (usealt == 2) {
|
||||||
|
url = "https://nightride.fm/stream/chillsynth.m4a";
|
||||||
|
} else if (usealt == 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
audio.src = url;
|
||||||
|
audio.currentTime = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const stop = function() {
|
||||||
|
if (usealt == 3) return;
|
||||||
|
audio.pause();
|
||||||
|
loading = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const volume = function(vol) {
|
||||||
|
audio.volume = vol;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
stop: stop,
|
||||||
|
playing: playing,
|
||||||
|
volume: volume
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
window.addEventListener("eagTitleMusic", function(e) {
|
||||||
|
if (e.detail.playing) {
|
||||||
|
if (!window.music.playing()) window.music.start();
|
||||||
|
} else {
|
||||||
|
if (window.music.playing()) window.music.stop();
|
||||||
|
}
|
||||||
|
window.music.volume(e.detail.volume);
|
||||||
|
});
|
33
www/queryTest.html
Normal file
33
www/queryTest.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>query test</title>
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.addEventListener("load", () => {
|
||||||
|
const output = document.getElementById("out");
|
||||||
|
document.getElementById("testButton").addEventListener("click", () => {
|
||||||
|
const ws = new WebSocket(document.getElementById("uriField").value);
|
||||||
|
ws.onopen = (e) => {
|
||||||
|
output.innerText = "please wait";
|
||||||
|
ws.send(document.getElementById("acceptField").value);
|
||||||
|
};
|
||||||
|
ws.onmessage = (e) => {
|
||||||
|
try {
|
||||||
|
output.innerText += JSON.stringify(JSON.parse(e.data), null, 4);
|
||||||
|
}catch(ee) {
|
||||||
|
output.innerText += e.data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onclose = (e) => {
|
||||||
|
output.innerText = output.innerText + "\n\nSocket Closed.";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body style="font-family:sans-serif;">
|
||||||
|
<input type="text" id="uriField" value="ws://127.0.0.1:25565/" /><br />
|
||||||
|
<input type="text" id="acceptField" value="accept: motd" /><br />
|
||||||
|
<button id="testButton">send</button>
|
||||||
|
<pre id="out" style="font-family:sans-serif;"></pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
www/testvideo.mp4
Normal file
BIN
www/testvideo.mp4
Normal file
Binary file not shown.
BIN
www/wait.mp3
Normal file
BIN
www/wait.mp3
Normal file
Binary file not shown.
5
www/worker_bootstrap.js
Normal file
5
www/worker_bootstrap.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
onmessage = function(o) {
|
||||||
|
importScripts("classes_server.js");
|
||||||
|
eaglercraftServerOpts = o.data;
|
||||||
|
main();
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user