Add files via upload
BIN
pre/ProductSans.ttf
Normal file
54
pre/assetoverrides/credits.txt
Normal file
@ -0,0 +1,54 @@
|
||||
§fPrecision Client is a custom eaglercraft client with QOL §ffeatures, custom texture packs, and more.§r
|
||||
|
||||
§9This was created by LAX1DUDE and forked by EtcherFX§r
|
||||
|
||||
§4Ingame voice chat service created by ayunami2000§r
|
||||
|
||||
§2Click the Github or Discord button on the main menu for §2more information§r
|
||||
|
||||
§fScroll down for the detailed license statements
|
||||
|
||||
§fAll graphical assets in this project were ripped from §fMojang's official Minecraft.jar for Minecraft version §f1.5.2 §fand they are Mojang's intellectual property. Assets ommitted §finclude the Minecraft soundtrack and music disks and all §fsoftware references to the Mojang/Minecraft api.
|
||||
|
||||
§f========================================
|
||||
|
||||
§fCopyright (c) 2022 Calder Young.
|
||||
|
||||
§fThis work is licensed under a Creative Commons
|
||||
§fAttribution-NonCommercial 4.0 International License
|
||||
§f§nhttp://creativecommons.org/licenses/by-nc/4.0/§r
|
||||
|
||||
§f========================================
|
||||
|
||||
§fTeaVM Copyright 2016 Alexey Andreev.
|
||||
|
||||
§fLicensed under the Apache License, Version 2.0 (the §f"License"); you may not use this file except in compliance §fwith the License. You may obtain a copy of the License at
|
||||
|
||||
§f§nhttp://www.apache.org/licenses/LICENSE-2.0§r
|
||||
|
||||
§fUnless required by applicable law or agreed to in writing, §fsoftware distributed under the License is distributed on an §f"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY §fKIND, either express or implied. See the License for the §fspecific language governing permissions and limitations §funder the License.
|
||||
|
||||
§f========================================
|
||||
|
||||
§fNVIDIA FXAA 3.11 by TIMOTHY LOTTES
|
||||
|
||||
§fCopyright (c) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS §fRESERVED.
|
||||
|
||||
§fTO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, §fTHIS SOFTWARE IS PROVIDED *AS IS* AND NVIDIA AND ITS §fSUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR §fIMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES §fOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. §fIN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR §fANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL §fDAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, §fDAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS §fINTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER §fPECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO §fUSE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE §fPOSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
§f========================================
|
||||
|
||||
§fJZlib Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights §freserved.
|
||||
|
||||
§fRedistribution and use in source and binary forms, with or §fwithout modification, are permitted provided that the following §fconditions are met:
|
||||
|
||||
§f1. Redistributions of source code must retain the above §fcopyright notice, this list of conditions and the following §fdisclaimer.
|
||||
|
||||
§f2. Redistributions in binary form must reproduce the §fabove copyright notice, this list of conditions and the §ffollowing disclaimer in the documentation and/or other §fmaterials provided with the distribution.
|
||||
|
||||
§f3. The names of the authors may not be used to endorse §for promote products derived from this software without §fspecific prior written permission.
|
||||
|
||||
§fTHIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR §fIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE §fIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A §fPARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL §fJCRAFT, INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE §fLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, §fEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT §fLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; §fLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) §fHOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER §fIN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING §fNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE §fUSE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY §fOF SUCH DAMAGE.
|
||||
|
||||
§f========================================
|
||||
|
BIN
pre/assetoverrides/gui/demo_bg.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
1487
pre/assetoverrides/lang/en_US.lang
Normal file
BIN
pre/assetoverrides/precision/gui.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
pre/assetoverrides/precision/gui2.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pre/assetoverrides/precision/guismall.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
pre/assetoverrides/precision/logo.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pre/assetoverrides/precision/precision.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
pre/assetoverrides/precision/precision2.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
pre/assetoverrides/title/bg/panorama0.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
pre/assetoverrides/title/bg/panorama1.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
pre/assetoverrides/title/bg/panorama2.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
pre/assetoverrides/title/bg/panorama3.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
pre/assetoverrides/title/bg/panorama4.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
pre/assetoverrides/title/bg/panorama5.png
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
pre/bg.png
Normal file
After Width: | Height: | Size: 427 KiB |
19499
pre/classes.js
Normal file
16300
pre/classes_server.js
Normal file
798
pre/eagswebrtc.js
Normal file
@ -0,0 +1,798 @@
|
||||
"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();
|
||||
};
|
77
pre/favicon.ico
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<!-- Google tag (gtag.js) -->
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-261780635-1"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-261780635-1');
|
||||
</script>
|
||||
|
||||
<title>Play Minecraft Online! | Online mc</title>
|
||||
|
||||
<link rel="icon" href="/icon.png">
|
||||
<meta name="description" content="Play Minecraft Online For Free!" />
|
||||
<meta name="keywords" content="free minecraft online, eaglercraft, minecraft, onlinemc, Onlinemc, ayuncraft, Ayuncraft, mc, eaglercraftx, eaglercraft shaders, eaglercraft download,eaglercraft, eaglercraftx, minecraft, 1.8, 1.8.8, eaglercraft, eaglercraft minecraft, eaglercraft 3kh0, eaglercraft github, eaglercraft singleplayer, eaglercraft hacks, eaglercraft 1.8, eaglercraft server, eaglecraft game, eaglercraft alternative, eaglercraft alt links, eaglercraft asspixel, eaglercraft anarchy server, eaglercraft aeon, eaglercraft asspixel server ip, eaglercraft all links, eaglercraft aeon server, eaglercraft beta, eaglecraft boats, eaglecraft boats for sale, eaglecraft boats for sale bc, eaglecraft bedwars server, eaglecraft boats inc, eaglercraft beta servers, eaglercraft blocked, eaglercraft client, eaglecraft custom boats, eaglecraft campbell river, eaglercraft creative, eaglercraft commands, eaglercraft code, eaglercraft controls, eaglercraft com, eaglercraft download, eaglercraft discord, eaglercraft dupe glitch, eaglercraft download file, eaglercraft download google drive, eaglercraft dmca, eaglercraft deleted, eaglercraft down, eaglercraft embed, eaglercraft epk file download, eaglercraft end of stream, eaglecraft apk download, eaglecraft eagtek, eaglercraft exploit, eaglecraft eggs, eaglercraft epk world file download, eaglercraft file, eaglercraft file download, eaglercraft free, eaglercraft forums, eaglercraft fork, eaglercraft faq, eaglercraft fps, eaglecraft free download, eaglercraft github servers, eaglercraft google drive, eaglercraft github lax1dude, eaglercraft github download, eaglercraft github.io, eaglercraft google sites, minecraft, applet, singleplayer, replit, html5, chromebook, lax1dude, games, eaglercraft singleplayer, eagler, minecraft for free, free minecraft">
|
||||
<meta property="og:title" content="Online mc" />
|
||||
<meta property="og:image" content="/icon.png" />
|
||||
<meta property="og:description" content="Online Minecraft" />
|
||||
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/css/bootstrap.min.css">
|
||||
<link href="/style.css" rel="stylesheet" />
|
||||
<link href="/darkmode.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
|
||||
<body class="diff-bg">
|
||||
<div id="loading"></div>
|
||||
<div class="container container-table">
|
||||
<div class="row vertical-center-row">
|
||||
<div class="col-12">
|
||||
</a>
|
||||
<div class="d-flex justify-content-center">
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="button-area d-block">
|
||||
<h1 class="dark-text">404 Not Found!</h1>
|
||||
<div class="splash-404">...</div>
|
||||
<h3> </h3>
|
||||
<a href="/">click here to go back to the main page!</a>
|
||||
<img class="creeper ms-auto d-block" src="creeper.webp" alt=""/>
|
||||
</div>
|
||||
<div class="mc-footer d-flex justify-content-between">
|
||||
<div class="footer-copyright text-end text-white">This website is not affiliated with Mojang.</div>
|
||||
<div class="mc-dd">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script defer src="/_vercel/insights/script.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.3/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
//display loader on page load
|
||||
$('#loading').fadeOut();
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
//display loader on page load
|
||||
$('#loading').fadeOut();
|
||||
}, 12 * 1000);
|
||||
</script>
|
||||
<script src="/darkmode.js"></script>
|
||||
<script src="/splash-404.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
160
pre/index.html
Normal file
@ -0,0 +1,160 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Precision Client (1.5.2-beta_0.2)</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta content="Precision Client is a custom eaglercraft client with QOL features, custom texture packs, and more."
|
||||
name="description" />
|
||||
<meta content="//precisionclient.vercel.app" name="url" />
|
||||
<meta content="EtcherFX" name="author" />
|
||||
<meta content="Precision Client" property="og:title" />
|
||||
<meta content="en-US" property="og:locale" />
|
||||
<meta content="website" property="og:type" />
|
||||
<meta content="//precisionclient.vercel.app" property="og:url" />
|
||||
<!--meta content="IMAGE" property="og:image"/>-->
|
||||
<meta content="Precision Client is a custom eaglercraft client with QOL features, custom texture packs, and more."
|
||||
property="og:description" />
|
||||
<script type="text/javascript" src="eagswebrtc.js"></script>
|
||||
<script type="text/javascript" src="classes.js"></script>
|
||||
<script async src="https://arc.io/widget.min.js#pchPqjfw"></script>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: "Product Sans";
|
||||
src: url(ProductSans.ttf);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body style="margin: 0; width: 100vw; height: 100vh; font-family:
|
||||
'Product Sans'" id="game_frame" class="gameframe">
|
||||
<div id="Selection"
|
||||
style="display: inline-block; position: absolute; top:50%; left: 50%; transform: translate(-50%, -50%)">
|
||||
<style>
|
||||
html {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.starter {
|
||||
border-radius: 5px;
|
||||
border: 1px solid #fff;
|
||||
background-color: #0d0c0c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #fff;
|
||||
background-color: #0d0c0c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.gameframe {
|
||||
background-image: url("bg.png");
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
</style>
|
||||
<h1>Precision Client</h1>
|
||||
<h3>Select a texture pack:</h3>
|
||||
<select id="Packs" class="dropdown">
|
||||
<option>-- Choose one --</option>
|
||||
<option value="defaultold">Default Old</option>
|
||||
<option value="defaultnew">Default 1.17+</option>
|
||||
<option value="bombies">Bombies 180k</option>
|
||||
<option value="bones">Bare Bones</option>
|
||||
<option value="modifiednew">Modified 1.17+</option>
|
||||
<option value="miamiprivate">Miami Private</option>
|
||||
<option value="nebula">Nebula</option>
|
||||
<option value="rhedd">Rhedd</option>
|
||||
<option value="ricefault">Ricefault</option>
|
||||
<option value="tightfault">Tightfault</option>
|
||||
<option value="walifault">Walifault</option>
|
||||
</select>
|
||||
<br /><br />
|
||||
<input class="starter" type="button" value="Launch" onclick="Start();" />
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
if (document.location.href.startsWith("file:")) {
|
||||
alert("You cannot 'open' this file in your browser, the code doesn't work. Upload this folder to your HTTP(s) server and access it via the internet to launch the stable-download game. This is not a bug, please read the documentation.");
|
||||
} else {
|
||||
var PackSelect = document.getElementById("Packs");
|
||||
function Start() {
|
||||
if (PackSelect.selectedIndex !== 0) {
|
||||
var Selected = PackSelect.options[PackSelect.selectedIndex].value;
|
||||
document.getElementById("Selection").style.display = "none";
|
||||
localStorage.LastPack = Selected;
|
||||
const relayId = Math.floor(Math.random() * 3);
|
||||
window.eaglercraftOpts = {
|
||||
container: "game_frame",
|
||||
assetsURI: `packs/${Selected}.epk`,
|
||||
serverWorkerURI: "worker_bootstrap.js",
|
||||
worldsFolder: "MAIN",
|
||||
assetOverrides: {
|
||||
"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",
|
||||
//"records/ward.mp3": wardUrl,
|
||||
"credits.txt": "assetoverrides/credits.txt",
|
||||
"precision/gui.png": "assetoverrides/precision/gui.png",
|
||||
"precision/gui2.png": "assetoverrides/precision/gui2.png",
|
||||
"precision/guismall.png": "assetoverrides/precision/guismall.png",
|
||||
"precision/logo.png": "assetoverrides/precision/logo.png",
|
||||
"precision/precision.png": "assetoverrides/precision/precision.png",
|
||||
"precision/precision2.png": "assetoverrides/precision/precision2.png",
|
||||
"lang/en_US.lang": "assetoverrides/lang/en_US.lang",
|
||||
"gui/demo_bg.png": "assetoverrides/gui/demo_bg.png",
|
||||
"title/bg/panorama0.png": "assetoverrides/title/bg/panorama0.png",
|
||||
"title/bg/panorama1.png": "assetoverrides/title/bg/panorama1.png",
|
||||
"title/bg/panorama2.png": "assetoverrides/title/bg/panorama2.png",
|
||||
"title/bg/panorama3.png": "assetoverrides/title/bg/panorama3.png",
|
||||
"title/bg/panorama4.png": "assetoverrides/title/bg/panorama4.png",
|
||||
"title/bg/panorama5.png": "assetoverrides/title/bg/panorama5.png"
|
||||
},
|
||||
servers: [
|
||||
{ serverName: "A*spixel", serverAddress: "wss://web.asspixel.net/CAPixel/", hideAddress: true },
|
||||
{ serverName: "VanillaCraft", serverAddress: "wss://play.vanillacraftsmp.org/", hideAddress: true },
|
||||
{ serverName: "ArchMC", serverAddress: "wss://web.arch.lol/join", hideAddress: true },
|
||||
{ serverName: "Ayunboom", serverAddress: "wss://sus.shhnowisnottheti.me", hideAddress: true },
|
||||
{ serverName: "Aeon Network", serverAddress: "wss://aeon-network.net/aeon", hideAddress: true },
|
||||
{ serverName: "Sealcraft", serverAddress: "wss://sealcraft.ddns.net:442/servers", hideAddress: true }
|
||||
],
|
||||
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: [], 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.minecraftOpts.push(s);
|
||||
}
|
||||
})();
|
||||
main();
|
||||
} else
|
||||
alert("You need to select a pack");
|
||||
}
|
||||
}
|
||||
if (localStorage.LastPack)
|
||||
for (Pack of PackSelect.children)
|
||||
if (Pack.value === localStorage.LastPack) {
|
||||
Pack.selected = "selected";
|
||||
break;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
pre/packs/defaultold.epk
Normal file
5
pre/worker_bootstrap.js
Normal file
@ -0,0 +1,5 @@
|
||||
onmessage = function (o) {
|
||||
importScripts("classes_server.js");
|
||||
eaglercraftServerOpts = o.data;
|
||||
main();
|
||||
};
|