save broken for future
This commit is contained in:
parent
00821ed2ae
commit
1637fc2998
24 changed files with 1835 additions and 287 deletions
|
@ -19,7 +19,7 @@ public class ServerIcon {
|
||||||
Graphics2D g = (Graphics2D) icon.getGraphics();
|
Graphics2D g = (Graphics2D) icon.getGraphics();
|
||||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ?
|
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ?
|
||||||
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR : RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||||
g.setBackground(Color.BLACK);
|
g.setBackground(new Color(0, true));
|
||||||
g.clearRect(0, 0, 64, 64);
|
g.clearRect(0, 0, 64, 64);
|
||||||
int ow = awtIcon.getWidth();
|
int ow = awtIcon.getWidth();
|
||||||
int oh = awtIcon.getHeight();
|
int oh = awtIcon.getHeight();
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package net.md_5.bungee.eaglercraft;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// note that there's a few things not implemented, but I don't care.
|
||||||
|
|
||||||
|
public class ExpiringSet<T> extends HashSet<T> {
|
||||||
|
private final long expiration;
|
||||||
|
|
||||||
|
private final Map<T, Long> timestamps = new HashMap<>();
|
||||||
|
|
||||||
|
public ExpiringSet(long expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkForExpirations() {
|
||||||
|
Iterator<T> iterator = this.timestamps.keySet().iterator();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
T element = iterator.next();
|
||||||
|
if (super.contains(element)) {
|
||||||
|
if (this.timestamps.get(element) + this.expiration < now) {
|
||||||
|
iterator.remove();
|
||||||
|
super.remove(element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iterator.remove();
|
||||||
|
super.remove(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(T o) {
|
||||||
|
checkForExpirations();
|
||||||
|
boolean success = super.add(o);
|
||||||
|
if (success) timestamps.put(o, System.currentTimeMillis());
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
checkForExpirations();
|
||||||
|
boolean success = super.remove(o);
|
||||||
|
if (success) timestamps.remove(o);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.timestamps.clear();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
checkForExpirations();
|
||||||
|
return super.contains(o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
package net.md_5.bungee.eaglercraft;
|
||||||
|
|
||||||
|
import net.md_5.bungee.UserConnection;
|
||||||
|
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||||
|
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||||
|
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||||
|
import net.md_5.bungee.api.plugin.Listener;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import net.md_5.bungee.api.plugin.PluginDescription;
|
||||||
|
import net.md_5.bungee.event.EventHandler;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public class PluginEaglerVoice extends Plugin implements Listener {
|
||||||
|
|
||||||
|
private final Map<String, UserConnection> voicePlayers = new HashMap<>();
|
||||||
|
private final Map<String, ExpiringSet<String>> voiceRequests = new HashMap<>();
|
||||||
|
private final Set<String[]> voicePairs = new HashSet<>();
|
||||||
|
|
||||||
|
public PluginEaglerVoice() {
|
||||||
|
super(new PluginDescription("EaglerVoice", PluginEaglerVoice.class.getName(), "1.0.0", "ayunami2000", Collections.emptySet(), null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onLoad() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEnable() {
|
||||||
|
getProxy().getPluginManager().registerListener(this, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPluginMessage(PluginMessageEvent event) {
|
||||||
|
if(event.getSender() instanceof UserConnection && event.getData().length > 0) {
|
||||||
|
UserConnection connection = (UserConnection) event.getSender();
|
||||||
|
String user = connection.getName();
|
||||||
|
byte[] msg = event.getData();
|
||||||
|
try {
|
||||||
|
if("EAG|VoiceJoin".equals(event.getTag())) {
|
||||||
|
if (voicePlayers.containsKey(user)) return; // user is already using voice chat
|
||||||
|
// send out packet for player joined voice
|
||||||
|
// notice: everyone on the server can see this packet!! however, it doesn't do anything but let clients know that the player has turned on voice chat
|
||||||
|
for (UserConnection conn : voicePlayers.values()) conn.sendData("EAG|VoiceJoin", user.getBytes(StandardCharsets.UTF_8));
|
||||||
|
voicePlayers.put(user, connection);
|
||||||
|
}else if("EAG|VoiceLeave".equals(event.getTag())) {
|
||||||
|
if (!voicePlayers.containsKey(user)) return; // user is not using voice chat
|
||||||
|
removeUser(user);
|
||||||
|
}else if("EAG|VoiceReq".equals(event.getTag())) {
|
||||||
|
if (!voicePlayers.containsKey(user)) return; // user is not using voice chat
|
||||||
|
String targetUser = new String(msg, StandardCharsets.UTF_8);
|
||||||
|
if (user.equals(targetUser)) return; // prevent duplicates
|
||||||
|
if (checkVoicePair(user, targetUser)) return; // already paired
|
||||||
|
if (!voicePlayers.containsKey(targetUser)) return; // target user is not using voice chat
|
||||||
|
if (!voiceRequests.containsKey(user)) voiceRequests.put(user, new ExpiringSet<>(2000));
|
||||||
|
if (voiceRequests.get(user).contains(targetUser)) return;
|
||||||
|
voiceRequests.get(user).add(targetUser);
|
||||||
|
|
||||||
|
// check if other has requested earlier
|
||||||
|
if (voiceRequests.containsKey(targetUser) && voiceRequests.get(targetUser).contains(user)) {
|
||||||
|
if (voiceRequests.containsKey(targetUser)) {
|
||||||
|
voiceRequests.get(targetUser).remove(user);
|
||||||
|
if (voiceRequests.get(targetUser).isEmpty()) voiceRequests.remove(targetUser);
|
||||||
|
}
|
||||||
|
if (voiceRequests.containsKey(user)) {
|
||||||
|
voiceRequests.get(user).remove(targetUser);
|
||||||
|
if (voiceRequests.get(user).isEmpty()) voiceRequests.remove(user);
|
||||||
|
}
|
||||||
|
// send each other add data
|
||||||
|
voicePairs.add(new String[] { user, targetUser });
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("username", user);
|
||||||
|
json.put("offer", false);
|
||||||
|
voicePlayers.get(targetUser).sendData("EAG|VoiceAdd", json.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
json.put("username", targetUser);
|
||||||
|
json.put("offer", true);
|
||||||
|
connection.sendData("EAG|VoiceAdd", json.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
} else if("EAG|VoiceRemove".equals(event.getTag())) {
|
||||||
|
if (!voicePlayers.containsKey(user)) return; // user is not using voice chat
|
||||||
|
String targetUser = new String(msg, StandardCharsets.UTF_8);
|
||||||
|
if (voicePairs.removeIf(pair -> (pair[0].equals(user) && pair[1].equals(targetUser)) || (pair[0].equals(targetUser) && pair[1].equals(user)))) voicePlayers.get(targetUser).sendData("EAG|VoiceRemove", user.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}else if("EAG|VoiceIce".equals(event.getTag())) {
|
||||||
|
if (!voicePlayers.containsKey(user)) return; // user is not using voice chat
|
||||||
|
JSONObject json = new JSONObject(new String(msg));
|
||||||
|
if (json.has("username") && json.get("username") instanceof String) {
|
||||||
|
String targetUser = json.getString("username");
|
||||||
|
if (checkVoicePair(user, targetUser)) {
|
||||||
|
if (json.has("ice_candidate")) {
|
||||||
|
// todo: limit ice_candidate data length or sanitize it fully
|
||||||
|
json.keySet().removeIf(s -> !s.equals("ice_candidate"));
|
||||||
|
json.put("username", user);
|
||||||
|
voicePlayers.get(targetUser).sendData("EAG|VoiceIce", json.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if("EAG|VoiceDesc".equals(event.getTag())) {
|
||||||
|
if (!voicePlayers.containsKey(user)) return; // user is not using voice chat
|
||||||
|
JSONObject json = new JSONObject(new String(msg));
|
||||||
|
if (json.has("username") && json.get("username") instanceof String) {
|
||||||
|
String targetUser = json.getString("username");
|
||||||
|
if (checkVoicePair(user, targetUser)) {
|
||||||
|
if (json.has("session_description")) {
|
||||||
|
// todo: limit session_description data length or sanitize it fully
|
||||||
|
json.keySet().removeIf(s -> !s.equals("session_description"));
|
||||||
|
json.put("username", user);
|
||||||
|
voicePlayers.get(targetUser).sendData("EAG|VoiceDesc", json.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(Throwable t) {
|
||||||
|
// hacker
|
||||||
|
t.printStackTrace(); // todo: remove in production
|
||||||
|
removeUser(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPostLogin(PostLoginEvent event) {
|
||||||
|
event.getPlayer().sendData("EAG|Voice", new byte[] { });
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
|
||||||
|
String nm = event.getPlayer().getName();
|
||||||
|
removeUser(nm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUser(String name) {
|
||||||
|
voicePlayers.remove(name);
|
||||||
|
for (String[] voicePair : voicePairs) {
|
||||||
|
String target = null;
|
||||||
|
if (voicePair[0].equals(name)) {
|
||||||
|
target = voicePair[1];
|
||||||
|
} else if(voicePair[1].equals(name)) {
|
||||||
|
target = voicePair[0];
|
||||||
|
}
|
||||||
|
if (target != null && voicePlayers.containsKey(target)) voicePlayers.get(target).sendData("EAG|VoiceRemove", name.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
voicePairs.removeIf(pair -> pair[0].equals(name) || pair[1].equals(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean checkVoicePair(String user1, String user2) {
|
||||||
|
return voicePairs.stream().anyMatch(pair -> (pair[0].equals(user1) && pair[1].equals(user2)) || (pair[0].equals(user2) && pair[1].equals(user1)));
|
||||||
|
}
|
||||||
|
}
|
227
javascript/eagswebrtc.js
Normal file
227
javascript/eagswebrtc.js
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
This is the backend for voice channels in eaglercraft, it links with TeaVM EaglerAdapter at runtime
|
||||||
|
|
||||||
|
Copyright 2022 Calder Young. All rights reserved.
|
||||||
|
|
||||||
|
Based on code written by ayunami2000
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
window.initializeVoiceClient = (() => {
|
||||||
|
|
||||||
|
const READYSTATE_NONE = 0;
|
||||||
|
const READYSTATE_ABORTED = -1;
|
||||||
|
const READYSTATE_DEVICE_INITIALIZED = 1;
|
||||||
|
|
||||||
|
const TASKSTATE_NONE = -1;
|
||||||
|
const TASKSTATE_LOADING = 0;
|
||||||
|
const TASKSTATE_COMPLETE = 1;
|
||||||
|
const TASKSTATE_FAILED = 2;
|
||||||
|
|
||||||
|
class EaglercraftVoicePeer {
|
||||||
|
|
||||||
|
constructor(client, peerId, peerConnection) {
|
||||||
|
this.client = client;
|
||||||
|
this.peerId = peerId;
|
||||||
|
this.peerConnection = peerConnection;
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
this.peerConnection.addEventListener("icecandidate", (evt) => {
|
||||||
|
if(evt.candidate) {
|
||||||
|
self.client.iceCandidateHandler(self.peerId, evt.candidate.sdpMLineIndex, evt.candidate.candidate.toJSON().stringify());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("track", (evt) => {
|
||||||
|
self.client.peerTrackHandler(self.peerId, evt.streams[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addStream(this.client.localMediaStream);
|
||||||
|
this.peerConnection.createOffer((desc) => {
|
||||||
|
const selfDesc = desc;
|
||||||
|
self.peerConnection.setLocalDescription(selfDesc, () => {
|
||||||
|
self.client.descriptionHandler(self.peerId, selfDesc.toJSON().stringify());
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description for \"" + self.peerId + "\"! " + err);
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set create offer for \"" + self.peerId + "\"! " + err);
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener("connectionstatechange", (evt) => {
|
||||||
|
if(evt.connectionState === 'disconnected') {
|
||||||
|
self.client.signalDisconnect(self.peerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
this.peerConnection.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRemoteDescription(descJSON) {
|
||||||
|
const self = this;
|
||||||
|
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, selfDesc.toJSON().stringify());
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set local description for \"" + self.peerId + "\"! " + err);
|
||||||
|
self.signalDisconnect(peerId);
|
||||||
|
});
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to create answer for \"" + self.peerId + "\"! " + err);
|
||||||
|
self.signalDisconnect(peerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, (err) => {
|
||||||
|
console.error("Failed to set remote description for \"" + self.peerId + "\"! " + err);
|
||||||
|
self.signalDisconnect(peerId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addICECandidate(candidate) {
|
||||||
|
this.peerConnection.addICECandidate(new RTCIceCandidate(JSON.parse(candidate)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class EaglercraftVoiceClient {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.ICEServers = [];
|
||||||
|
this.hasInit = false;
|
||||||
|
this.peerList = new Map();
|
||||||
|
this.readyState = READYSTATE_NONE;
|
||||||
|
this.taskState = TASKSTATE_NONE;
|
||||||
|
this.iceCandidateHandler = null;
|
||||||
|
this.descriptionHandler = null;
|
||||||
|
this.peerTrackHandler = null;
|
||||||
|
this.peerDisconnectHandler = null;
|
||||||
|
this.microphoneVolumeAudioContext = new AudioContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
this.ICEServers.push({ urls: urls[i] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setICECandidateHandler(cb) {
|
||||||
|
this.iceCandidateHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDescriptionHandler(cb) {
|
||||||
|
this.descriptionHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPeerTrackHandler(cb) {
|
||||||
|
this.peerTrackHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPeerDisconnectHandler(cb) {
|
||||||
|
this.peerDisconnectHandler = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateVoice(tk) {
|
||||||
|
this.localRawMediaStream.getAudioTracks()[0].enabled = tk;
|
||||||
|
}
|
||||||
|
|
||||||
|
intitializeDevices() {
|
||||||
|
if(!this.hasInit) {
|
||||||
|
this.taskState = TASKSTATE_LOADING;
|
||||||
|
const self = this;
|
||||||
|
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then((stream) => {
|
||||||
|
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 = 1.0;
|
||||||
|
self.readyState = READYSTATE_DEVICE_INITIALIZED;
|
||||||
|
self.taskState = TASKSTATE_COMPLETE;
|
||||||
|
this.hasInit = true;
|
||||||
|
}).catch(() => {
|
||||||
|
self.readyState = READYSTATE_ABORTED;
|
||||||
|
self.taskState = TASKSTATE_FAILED;
|
||||||
|
});
|
||||||
|
}else {
|
||||||
|
self.readyState = READYSTATE_DEVICE_INITIALIZED;
|
||||||
|
self.taskState = TASKSTATE_COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMicVolume(val) {
|
||||||
|
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;
|
||||||
|
self.localMediaStreamGain.gain = val * 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTaskState() {
|
||||||
|
return this.taskState;
|
||||||
|
}
|
||||||
|
|
||||||
|
getReadyState() {
|
||||||
|
return this.readyState;
|
||||||
|
}
|
||||||
|
|
||||||
|
signalConnect(peerId) {
|
||||||
|
const peerConnection = new RTCPeerConnection({ iceServers: this.ICEServers, optional: [ { DtlsSrtpKeyAgreement: true } ] });
|
||||||
|
const peerInstance = new EaglercraftVoicePeer(this, peerId, peerConnection);
|
||||||
|
this.peerList.set(peerId, peerInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
signalDescription(peerId, descJSON) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
thePeer.setRemoteDescription(descJSON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalDisconnect(peerId) {
|
||||||
|
var thePeer = this.peerList.get(peerId);
|
||||||
|
if((typeof thePeer !== "undefined") && thePeer !== null) {
|
||||||
|
this.peerList.delete(thePeer);
|
||||||
|
try {
|
||||||
|
thePeer.disconnect();
|
||||||
|
}catch(e) {}
|
||||||
|
this.peerDisconnectHandler(peerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
};
|
|
@ -3,6 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<title>eagler</title>
|
<title>eagler</title>
|
||||||
<script type="text/javascript" src="classes.js"></script>
|
<script type="text/javascript" src="classes.js"></script>
|
||||||
|
<script type="text/javascript" src="eagswebrtc.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
if(document.location.href.startsWith("file:")) {
|
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");
|
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");
|
||||||
|
|
BIN
lwjgl-rundir/resources/gui/voice.png
Normal file
BIN
lwjgl-rundir/resources/gui/voice.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
|
@ -62,10 +62,33 @@ profile.clearSkin=Clear List
|
||||||
fancyGraphicsNote=go to -> Options -> Video Settings on the pause menu to enable fancy graphics and smooth lighting
|
fancyGraphicsNote=go to -> Options -> Video Settings on the pause menu to enable fancy graphics and smooth lighting
|
||||||
|
|
||||||
voice.title=Voice Channel
|
voice.title=Voice Channel
|
||||||
voice.addr=Channel Address
|
voice.titleNoVoice=Voice is disabled on this server
|
||||||
voice.connect=Connect
|
voice.titleVoiceUnavailable=Voice is unavailable
|
||||||
voice.disconnect=Disconnect
|
voice.titleVoiceBrowserError=(fix your browser)
|
||||||
voice.volume=Channel Volume
|
voice.ptt=Press '$key$' to speak
|
||||||
|
voice.pttChangeDesc=(Press Any Key)
|
||||||
|
voice.changeKey=Change
|
||||||
|
voice.off=OFF
|
||||||
|
voice.radius=NEARBY
|
||||||
|
voice.global=GLOBAL
|
||||||
|
voice.volumeTitle=Change Volume
|
||||||
|
voice.volumeListen=Speakers Volume:
|
||||||
|
voice.volumeSpeak=Microphone Volume:
|
||||||
|
voice.radiusTitle=Change Listener Radius
|
||||||
|
voice.radiusLabel=Players Within:
|
||||||
|
voice.radiusChange=change
|
||||||
|
voice.notConnected=Not Connected
|
||||||
|
voice.connecting=Connecting...
|
||||||
|
voice.unavailable=Could not connect!
|
||||||
|
voice.connectedGlobal=Connected - Global
|
||||||
|
voice.connectedRadius=Connected - $f$Within $radius$m
|
||||||
|
voice.playersListening=Players Listening:
|
||||||
|
voice.muted=Players Muted:
|
||||||
|
voice.unmute=unmute
|
||||||
|
voice.mute=mute
|
||||||
|
voice.apply=Apply
|
||||||
|
voice.volumeSpeakerLabel=Speakers:
|
||||||
|
voice.volumeMicrophoneLabel=Microphone:
|
||||||
voice.warning1=§cWarning:§r your network does not support the STUN
|
voice.warning1=§cWarning:§r your network does not support the STUN
|
||||||
voice.warning2=connection procedure, a TURN relay will be used as
|
voice.warning2=connection procedure, a TURN relay will be used as
|
||||||
voice.warning3=fallback, which will greatly impact the audio quality
|
voice.warning3=fallback, which will greatly impact the audio quality
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
public class AbortedException extends RuntimeException {
|
||||||
|
|
||||||
|
}
|
59
src/main/java/net/lax1dude/eaglercraft/ExpiringSet.java
Normal file
59
src/main/java/net/lax1dude/eaglercraft/ExpiringSet.java
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// note that there's a few things not implemented, but I don't care.
|
||||||
|
|
||||||
|
public class ExpiringSet<T> extends HashSet<T> {
|
||||||
|
private final long expiration;
|
||||||
|
|
||||||
|
private final Map<T, Long> timestamps = new HashMap<>();
|
||||||
|
|
||||||
|
public ExpiringSet(long expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkForExpirations() {
|
||||||
|
Iterator<T> iterator = this.timestamps.keySet().iterator();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
T element = iterator.next();
|
||||||
|
if (super.contains(element)) {
|
||||||
|
if (this.timestamps.get(element) + this.expiration < now) {
|
||||||
|
iterator.remove();
|
||||||
|
super.remove(element);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iterator.remove();
|
||||||
|
super.remove(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(T o) {
|
||||||
|
checkForExpirations();
|
||||||
|
boolean success = super.add(o);
|
||||||
|
if (success) timestamps.put(o, System.currentTimeMillis());
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean remove(Object o) {
|
||||||
|
checkForExpirations();
|
||||||
|
boolean success = super.remove(o);
|
||||||
|
if (success) timestamps.remove(o);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.timestamps.clear();
|
||||||
|
super.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains(Object o) {
|
||||||
|
checkForExpirations();
|
||||||
|
return super.contains(o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,243 +0,0 @@
|
||||||
package net.lax1dude.eaglercraft;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.src.GuiButton;
|
|
||||||
import net.minecraft.src.GuiIngameMenu;
|
|
||||||
import net.minecraft.src.GuiMainMenu;
|
|
||||||
import net.minecraft.src.GuiScreen;
|
|
||||||
import net.minecraft.src.GuiSlider2;
|
|
||||||
import net.minecraft.src.GuiTextField;
|
|
||||||
import net.minecraft.src.ScaledResolution;
|
|
||||||
import net.minecraft.src.StringTranslate;
|
|
||||||
|
|
||||||
public class GuiScreenVoiceChannel extends GuiScreen {
|
|
||||||
|
|
||||||
public GuiScreenVoiceChannel(GuiScreen parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String screenTitle = "Voice Channel";
|
|
||||||
private GuiScreen parent;
|
|
||||||
private GuiTextField channel;
|
|
||||||
|
|
||||||
private GuiButton done;
|
|
||||||
private GuiButton connect;
|
|
||||||
private GuiButton disconnect;
|
|
||||||
private GuiSlider2 slider;
|
|
||||||
|
|
||||||
public void initGui() {
|
|
||||||
StringTranslate var1 = StringTranslate.getInstance();
|
|
||||||
this.screenTitle = var1.translateKey("voice.title");
|
|
||||||
this.channel = new GuiTextField(this.fontRenderer, this.width / 2 - 98, this.height / 6 + 24, 195, 20);
|
|
||||||
this.channel.setText(EaglerProfile.myChannel);
|
|
||||||
EaglerAdapter.enableRepeatEvents(true);
|
|
||||||
this.buttonList.add(done = new GuiButton(200, this.width / 2 - 100, this.height / 6 + 148, var1.translateKey("gui.done")));
|
|
||||||
this.buttonList.add(connect = new GuiButton(1, this.width / 2 - 100, this.height / 6 + 52, 99, 20, var1.translateKey("voice.connect")));
|
|
||||||
this.buttonList.add(disconnect = new GuiButton(2, this.width / 2 + 1, this.height / 6 + 52, 99, 20, var1.translateKey("voice.disconnect")));
|
|
||||||
this.buttonList.add(slider = new GuiSlider2(3, this.width / 2 - 100, this.height / 6 + 103, 200, 20, 0.5f, 2.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onGuiClosed() {
|
|
||||||
EaglerAdapter.enableRepeatEvents(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void drawScreen(int mx, int my, float par3) {
|
|
||||||
this.drawDefaultBackground();
|
|
||||||
StringTranslate var1 = StringTranslate.getInstance();
|
|
||||||
this.drawCenteredString(this.fontRenderer, this.screenTitle, this.width / 2, 15, 16777215);
|
|
||||||
this.drawString(this.fontRenderer, var1.translateKey("voice.addr"), this.width / 2 - 98, this.height / 6 + 8, 10526880);
|
|
||||||
if(voiceRelayed) {
|
|
||||||
this.drawCenteredString(this.fontRenderer, var1.translateKey("voice.warning1"), this.width / 2, this.height / 6 + 125, 0xffcccc);
|
|
||||||
this.drawCenteredString(this.fontRenderer, var1.translateKey("voice.warning2"), this.width / 2, this.height / 6 + 136, 0xffcccc);
|
|
||||||
this.drawCenteredString(this.fontRenderer, var1.translateKey("voice.warning3"), this.width / 2, this.height / 6 + 147, 0xffcccc);
|
|
||||||
this.drawString(this.fontRenderer, var1.translateKey("voice.volume"), this.width / 2 - 98, this.height / 6 + 81, 10526880);
|
|
||||||
slider.yPosition = this.height / 6 + 95;
|
|
||||||
done.yPosition = this.height / 6 + 168;
|
|
||||||
}else {
|
|
||||||
this.drawString(this.fontRenderer, var1.translateKey("voice.volume"), this.width / 2 - 98, this.height / 6 + 89, 10526880);
|
|
||||||
slider.yPosition = this.height / 6 + 103;
|
|
||||||
done.yPosition = this.height / 6 + 148;
|
|
||||||
}
|
|
||||||
super.drawScreen(mx, my, par3);
|
|
||||||
this.channel.drawTextBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
|
||||||
if(par1GuiButton.id == 200) {
|
|
||||||
this.mc.displayGuiScreen(parent);
|
|
||||||
}else if(par1GuiButton.id == 1) {
|
|
||||||
EaglerAdapter.voiceConnect(channel.getText());
|
|
||||||
}else if(par1GuiButton.id == 2) {
|
|
||||||
EaglerAdapter.voiceEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateScreen() {
|
|
||||||
this.channel.updateCursorCounter();
|
|
||||||
this.connect.enabled = !voiceActive;
|
|
||||||
this.disconnect.enabled = voiceActive;
|
|
||||||
this.channel.setEnabled(!voiceActive);
|
|
||||||
this.slider.enabled = voiceActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void keyTyped(char par1, int par2) {
|
|
||||||
this.channel.textboxKeyTyped(par1, par2);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void mouseClicked(int par1, int par2, int par3) {
|
|
||||||
super.mouseClicked(par1, par2, par3);
|
|
||||||
this.channel.mouseClicked(par1, par2, par3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean doesGuiPauseGame() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final TextureLocation tex_gui = new TextureLocation("/gui/gui.png");
|
|
||||||
|
|
||||||
private static String[] connectedUsers = new String[0];
|
|
||||||
private static String[] talkingUsers = new String[0];
|
|
||||||
private static boolean voiceActive = false;
|
|
||||||
private static boolean voiceRelayed = false;
|
|
||||||
|
|
||||||
public static void tickVoiceConnection() {
|
|
||||||
voiceActive = EaglerAdapter.voiceActive();
|
|
||||||
if(voiceActive) {
|
|
||||||
voiceRelayed = EaglerAdapter.voiceRelayed();
|
|
||||||
connectedUsers = EaglerAdapter.voiceUsers();
|
|
||||||
talkingUsers = EaglerAdapter.voiceUsersTalking();
|
|
||||||
Arrays.sort(talkingUsers);
|
|
||||||
Arrays.sort(connectedUsers);
|
|
||||||
}else {
|
|
||||||
voiceRelayed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long fadeInTimer = 0l;
|
|
||||||
|
|
||||||
public static void drawOverlay() {
|
|
||||||
Minecraft mc = Minecraft.getMinecraft();
|
|
||||||
if(System.currentTimeMillis() - fadeInTimer < 1500l) {
|
|
||||||
ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight);
|
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D);
|
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_ALPHA_TEST);
|
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_DEPTH_TEST);
|
|
||||||
EaglerAdapter.glDepthMask(false);
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
|
||||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
float i = (float)(System.currentTimeMillis() - fadeInTimer) / 600f;
|
|
||||||
i = 1.0f / (i + 1.0f);
|
|
||||||
i = i * i * 1.08f - 0.08f;
|
|
||||||
if(i < 0.0f) i = 0.0f;
|
|
||||||
drawRect(0, 0, res.getScaledWidth(), res.getScaledHeight(), ((int)(i * 255f) << 24) | 0xffffff);
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
|
||||||
if(System.currentTimeMillis() - fadeInTimer < 130l) {
|
|
||||||
mc.showWarningText();
|
|
||||||
}
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_DEPTH_TEST);
|
|
||||||
EaglerAdapter.glDepthMask(true);
|
|
||||||
}
|
|
||||||
boolean titleScreen = (mc.currentScreen != null && (mc.currentScreen instanceof GuiMainMenu));
|
|
||||||
if(voiceActive && !(titleScreen && ((GuiMainMenu)mc.currentScreen).showAck) && !mc.gameSettings.showDebugInfo) {
|
|
||||||
ScaledResolution res = new ScaledResolution(mc.gameSettings, mc.displayWidth, mc.displayHeight);
|
|
||||||
int width = res.getScaledWidth(); int height = res.getScaledHeight();
|
|
||||||
if(titleScreen) {
|
|
||||||
EaglerAdapter.glPushMatrix();
|
|
||||||
EaglerAdapter.glTranslatef(0f, 12f, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_LIGHTING);
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
|
||||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
|
|
||||||
String line1 = "voice connected";
|
|
||||||
String line2 = "" + connectedUsers.length + " users listening";
|
|
||||||
int ll1 = mc.fontRenderer.getStringWidth(line1);
|
|
||||||
int ll2 = mc.fontRenderer.getStringWidth(line2);
|
|
||||||
drawRect(width - 17 - ll1 - 6, 0, width, 20, 0x33000000);
|
|
||||||
|
|
||||||
if(mc.gameSettings.keyBindPlayerList.pressed || (mc.currentScreen != null && ((mc.currentScreen instanceof GuiIngameMenu) || (mc.currentScreen instanceof GuiScreenVoiceChannel)))) {
|
|
||||||
if(connectedUsers.length > 0) {
|
|
||||||
int wid = 0;
|
|
||||||
for(int i = 0; i < connectedUsers.length; ++i) {
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
int sw = mc.fontRenderer.getStringWidth(connectedUsers[i]);
|
|
||||||
mc.fontRenderer.drawStringWithShadow(connectedUsers[i], width - 12 - sw, 26 + i*11, 0xffeeeeee);
|
|
||||||
if(wid < sw) {
|
|
||||||
wid = sw;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isTalking = false;
|
|
||||||
for(int j = 0; j < talkingUsers.length; ++j) {
|
|
||||||
if(talkingUsers[j].equals(connectedUsers[i])) {
|
|
||||||
isTalking = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_gui.bindTexture();
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
|
||||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 0.65f);
|
|
||||||
EaglerAdapter.glPushMatrix();
|
|
||||||
EaglerAdapter.glTranslatef(width - 9, 27 + i*11, 0f);
|
|
||||||
EaglerAdapter.glScalef(0.5f, 0.5f, 0.5f);
|
|
||||||
static_drawTexturedModalRect(0, 0, isTalking ? 208 : 224, 0, 15, 15);
|
|
||||||
EaglerAdapter.glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
drawRect(width - wid - 15, 24, width, 26 + connectedUsers.length*11, 0x33000000);
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
if(talkingUsers.length > 0) {
|
|
||||||
int wid = 0;
|
|
||||||
for(int i = 0; i < talkingUsers.length; ++i) {
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
||||||
int sw = mc.fontRenderer.getStringWidth(talkingUsers[i]);
|
|
||||||
mc.fontRenderer.drawStringWithShadow(talkingUsers[i], width - 12 - sw, 26 + i*11, 0xffeeeeee);
|
|
||||||
if(wid < sw) {
|
|
||||||
wid = sw;
|
|
||||||
}
|
|
||||||
|
|
||||||
tex_gui.bindTexture();
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
|
||||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 0.65f);
|
|
||||||
EaglerAdapter.glPushMatrix();
|
|
||||||
EaglerAdapter.glTranslatef(width - 9, 27 + i*11, 0f);
|
|
||||||
EaglerAdapter.glScalef(0.5f, 0.5f, 0.5f);
|
|
||||||
static_drawTexturedModalRect(0, 0, 208, 0, 15, 15);
|
|
||||||
EaglerAdapter.glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
drawRect(width - wid - 15, 24, width, 26 + talkingUsers.length*11, 0x33000000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mc.fontRenderer.drawStringWithShadow(line1, width - 16 - ll1 - 4, 2, 0xffffffff);
|
|
||||||
|
|
||||||
EaglerAdapter.glPushMatrix();
|
|
||||||
EaglerAdapter.glTranslatef(width - 20, 11f, 0f);
|
|
||||||
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
|
||||||
mc.fontRenderer.drawStringWithShadow(line2, -ll2, 0, 0xffffffff);
|
|
||||||
EaglerAdapter.glPopMatrix();
|
|
||||||
|
|
||||||
boolean b = ((System.currentTimeMillis() / 800l) % 2l) == 1l;
|
|
||||||
|
|
||||||
tex_gui.bindTexture();
|
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
|
||||||
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 0.65f);
|
|
||||||
static_drawTexturedModalRect(width - 17, 2, b ? 192 : 224, 0, 15, 15);
|
|
||||||
|
|
||||||
if(titleScreen) {
|
|
||||||
EaglerAdapter.glPopMatrix();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
595
src/main/java/net/lax1dude/eaglercraft/GuiVoiceMenu.java
Normal file
595
src/main/java/net/lax1dude/eaglercraft/GuiVoiceMenu.java
Normal file
|
@ -0,0 +1,595 @@
|
||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.src.EnumChatFormatting;
|
||||||
|
import net.minecraft.src.GuiButton;
|
||||||
|
import net.minecraft.src.GuiScreen;
|
||||||
|
import net.minecraft.src.GuiSlider2;
|
||||||
|
import net.minecraft.src.MathHelper;
|
||||||
|
import net.minecraft.src.StringTranslate;
|
||||||
|
|
||||||
|
public class GuiVoiceMenu extends GuiScreen {
|
||||||
|
|
||||||
|
protected final GuiScreen parent;
|
||||||
|
|
||||||
|
protected int voiceButtonOFFposX;
|
||||||
|
protected int voiceButtonOFFposY;
|
||||||
|
protected int voiceButtonOFFposW;
|
||||||
|
protected int voiceButtonOFFposH;
|
||||||
|
|
||||||
|
protected int voiceButtonRADIUSposX;
|
||||||
|
protected int voiceButtonRADIUSposY;
|
||||||
|
protected int voiceButtonRADIUSposW;
|
||||||
|
protected int voiceButtonRADIUSposH;
|
||||||
|
|
||||||
|
protected int voiceButtonGLOBALposX;
|
||||||
|
protected int voiceButtonGLOBALposY;
|
||||||
|
protected int voiceButtonGLOBALposW;
|
||||||
|
protected int voiceButtonGLOBALposH;
|
||||||
|
|
||||||
|
protected int voiceScreenButtonOFFposX;
|
||||||
|
protected int voiceScreenButtonOFFposY;
|
||||||
|
protected int voiceScreenButtonOFFposW;
|
||||||
|
protected int voiceScreenButtonOFFposH;
|
||||||
|
|
||||||
|
protected int voiceScreenButtonRADIUSposX;
|
||||||
|
protected int voiceScreenButtonRADIUSposY;
|
||||||
|
protected int voiceScreenButtonRADIUSposW;
|
||||||
|
protected int voiceScreenButtonRADIUSposH;
|
||||||
|
|
||||||
|
protected int voiceScreenButtonGLOBALposX;
|
||||||
|
protected int voiceScreenButtonGLOBALposY;
|
||||||
|
protected int voiceScreenButtonGLOBALposW;
|
||||||
|
protected int voiceScreenButtonGLOBALposH;
|
||||||
|
|
||||||
|
protected int voiceScreenButtonChangeRadiusposX;
|
||||||
|
protected int voiceScreenButtonChangeRadiusposY;
|
||||||
|
protected int voiceScreenButtonChangeRadiusposW;
|
||||||
|
protected int voiceScreenButtonChangeRadiusposH;
|
||||||
|
|
||||||
|
protected int voiceScreenVolumeIndicatorX;
|
||||||
|
protected int voiceScreenVolumeIndicatorY;
|
||||||
|
protected int voiceScreenVolumeIndicatorW;
|
||||||
|
protected int voiceScreenVolumeIndicatorH;
|
||||||
|
|
||||||
|
protected boolean showSliderBlocks = false;
|
||||||
|
protected boolean showSliderVolume = false;
|
||||||
|
protected boolean showPTTKeyConfig = false;
|
||||||
|
protected int showNewPTTKey = 0;
|
||||||
|
protected GuiSlider2 sliderBlocks = null;
|
||||||
|
protected GuiSlider2 sliderListenVolume = null;
|
||||||
|
protected GuiSlider2 sliderSpeakVolume = null;
|
||||||
|
|
||||||
|
protected GuiButton applyRadiusButton = null;
|
||||||
|
protected GuiButton applyVolumeButton = null;
|
||||||
|
|
||||||
|
public GuiVoiceMenu(GuiScreen parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initGui() {
|
||||||
|
this.sliderBlocks = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 20, 150, 20, (EaglerAdapter.getVoiceProximity() - 5) / 17.0f, 1.0f) {
|
||||||
|
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
|
||||||
|
if(super.mousePressed(par1Minecraft, par2, par3)) {
|
||||||
|
this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks";
|
||||||
|
return true;
|
||||||
|
}else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
|
||||||
|
super.mouseDragged(par1Minecraft, par2, par3);
|
||||||
|
this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sliderBlocks.displayString = "" + EaglerAdapter.getVoiceProximity() + " Blocks";
|
||||||
|
this.sliderListenVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 10, 150, 20, EaglerAdapter.getVoiceListenVolume(), 1.0f);
|
||||||
|
this.sliderSpeakVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 56, 150, 20, EaglerAdapter.getVoiceSpeakVolume(), 1.0f);
|
||||||
|
|
||||||
|
StringTranslate ts = StringTranslate.getInstance();
|
||||||
|
this.buttonList.clear();
|
||||||
|
this.buttonList.add(applyRadiusButton = new GuiButton(2, (width - 150) / 2, height / 3 + 49, 150, 20, ts.translateKey("voice.apply")));
|
||||||
|
this.buttonList.add(applyVolumeButton = new GuiButton(3, (width - 150) / 2, height / 3 + 90, 150, 20, ts.translateKey("voice.apply")));
|
||||||
|
applyRadiusButton.drawButton = applyVolumeButton.drawButton = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TextureLocation voiceGuiIcons = new TextureLocation("/gui/voice.png");
|
||||||
|
|
||||||
|
public void drawScreen(int mx, int my, float partialTicks) {
|
||||||
|
|
||||||
|
StringTranslate ts = StringTranslate.getInstance();
|
||||||
|
|
||||||
|
String txt = ts.translateKey("voice.title");
|
||||||
|
drawString(fontRenderer, txt, width - 5 - fontRenderer.getStringWidth(txt), 5, 0xFFCC22);
|
||||||
|
|
||||||
|
applyRadiusButton.drawButton = showSliderBlocks;
|
||||||
|
applyVolumeButton.drawButton = showSliderVolume;
|
||||||
|
|
||||||
|
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) {
|
||||||
|
|
||||||
|
drawRect(0, 0, this.width, this.height, 0xB0101010);
|
||||||
|
|
||||||
|
if(showSliderBlocks) {
|
||||||
|
|
||||||
|
drawRect(width / 2 - 86, height / 4 - 1, this.width / 2 + 86, height / 3 + 64 + height / 16, 0xFFDDDDDD);
|
||||||
|
drawRect(width / 2 - 85, height / 4 + 0, this.width / 2 + 85, height / 3 + 63 + height / 16, 0xFF333333);
|
||||||
|
|
||||||
|
drawCenteredString(this.fontRenderer, ts.translateKey("voice.radiusTitle"), this.width / 2, height / 4 + 9, 16777215);
|
||||||
|
drawString(this.fontRenderer, ts.translateKey("voice.radiusLabel"), (this.width - 150) / 2 + 3, height / 3 + 6, 0xCCCCCC);
|
||||||
|
sliderBlocks.drawButton(mc, mx, my);
|
||||||
|
|
||||||
|
}else if(showSliderVolume) {
|
||||||
|
|
||||||
|
drawRect(width / 2 - 86, height / 4 - 11, this.width / 2 + 86, height / 3 + 104 + height / 16, 0xFFDDDDDD);
|
||||||
|
drawRect(width / 2 - 85, height / 4 - 10, this.width / 2 + 85, height / 3 + 103 + height / 16, 0xFF333333);
|
||||||
|
|
||||||
|
drawCenteredString(this.fontRenderer, ts.translateKey("voice.volumeTitle"), this.width / 2, height / 4 - 1, 16777215);
|
||||||
|
drawString(this.fontRenderer, ts.translateKey("voice.volumeListen"), (this.width - 150) / 2 + 3, height / 3 - 4, 0xCCCCCC);
|
||||||
|
sliderListenVolume.drawButton(mc, mx, my);
|
||||||
|
|
||||||
|
drawString(this.fontRenderer, ts.translateKey("voice.volumeSpeak"), (this.width - 150) / 2 + 3, height / 3 + 42, 0xCCCCCC);
|
||||||
|
sliderSpeakVolume.drawButton(mc, mx, my);
|
||||||
|
|
||||||
|
}else if(showPTTKeyConfig) {
|
||||||
|
|
||||||
|
drawRect(width / 2 - 86, height / 3 - 10, this.width / 2 + 86, height / 3 + 35, 0xFFDDDDDD);
|
||||||
|
drawRect(width / 2 - 85, height / 3 - 9, this.width / 2 + 85, height / 3 + 34, 0xFF333333);
|
||||||
|
|
||||||
|
if(showNewPTTKey > 0) {
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(this.width / 2, height / 3 + 5, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(2.0f, 2.0f, 2.0f);
|
||||||
|
drawCenteredString(this.fontRenderer, EaglerAdapter.getKeyName(mc.gameSettings.voicePTTKey), 0, 0, 0xFFCC11);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
}else {
|
||||||
|
drawCenteredString(this.fontRenderer, ts.translateKey("voice.pttChangeDesc"), this.width / 2, height / 3 + 8, 16777215);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.drawScreen(mx, my, partialTicks);
|
||||||
|
|
||||||
|
throw new AbortedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
|
||||||
|
EaglerAdapter.glTranslatef(width - 6, 15, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
|
||||||
|
if(!EaglerAdapter.voiceAvailable()) {
|
||||||
|
txt = ts.translateKey("voice.titleVoiceUnavailable");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 6, 0xFF7777);
|
||||||
|
txt = ts.translateKey("voice.titleVoiceBrowserError");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 19, 0xAA4444);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!EaglerAdapter.voiceAllowed()) {
|
||||||
|
txt = ts.translateKey("voice.titleNoVoice");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 5, 0xFF7777);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xo = 0;
|
||||||
|
if(EaglerAdapter.voiceRelayed()) {
|
||||||
|
txt = ts.translateKey("voice.warning1");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 8, 0xBB9999);
|
||||||
|
txt = ts.translateKey("voice.warning2");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 18, 0xBB9999);
|
||||||
|
txt = ts.translateKey("voice.warning3");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 28, 0xBB9999);
|
||||||
|
xo = 43;
|
||||||
|
EaglerAdapter.glTranslatef(0.0f, xo, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
Voice.VoiceStatus status = EaglerAdapter.getVoiceStatus();
|
||||||
|
Voice.VoiceChannel channel = EaglerAdapter.getVoiceChannel();
|
||||||
|
|
||||||
|
boolean flag = false;
|
||||||
|
|
||||||
|
if(channel == Voice.VoiceChannel.NONE) {
|
||||||
|
flag = true;
|
||||||
|
}else {
|
||||||
|
if(status == Voice.VoiceStatus.CONNECTED) {
|
||||||
|
|
||||||
|
if(channel == Voice.VoiceChannel.PROXIMITY) {
|
||||||
|
txt = ts.translateKey("voice.connectedRadius").replace("$radius$", "" + EaglerAdapter.getVoiceProximity()).replace("$f$", "");
|
||||||
|
int w = fontRenderer.getStringWidth(txt);
|
||||||
|
int xx = width - 5 - (w * 3 / 4);
|
||||||
|
int yy = 15 + (xo * 3 / 4);
|
||||||
|
voiceScreenButtonChangeRadiusposX = xx;
|
||||||
|
voiceScreenButtonChangeRadiusposY = yy;
|
||||||
|
voiceScreenButtonChangeRadiusposW = width - 3 - xx;
|
||||||
|
voiceScreenButtonChangeRadiusposH = 12;
|
||||||
|
if(mx >= xx && my >= yy && mx < xx + voiceScreenButtonChangeRadiusposW && my < yy + 12) {
|
||||||
|
txt = ts.translateKey("voice.connectedRadius").replace("$radius$", "" + EaglerAdapter.getVoiceProximity())
|
||||||
|
.replace("$f$", "" + EnumChatFormatting.UNDERLINE) + EnumChatFormatting.RESET;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
txt = ts.translateKey("voice.connectedGlobal");
|
||||||
|
}
|
||||||
|
|
||||||
|
voiceScreenVolumeIndicatorX = width - 15 - (104 * 3 / 4);
|
||||||
|
voiceScreenVolumeIndicatorY = 15 + (xo * 3 / 4) + 30;
|
||||||
|
voiceScreenVolumeIndicatorW = width - voiceScreenVolumeIndicatorX - 4;
|
||||||
|
voiceScreenVolumeIndicatorH = 23;
|
||||||
|
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 5, 0x66DD66);
|
||||||
|
|
||||||
|
drawRect(-90, 42, 2, 52, 0xFFAAAAAA);
|
||||||
|
drawRect(-89, 43, 1, 51, 0xFF222222);
|
||||||
|
|
||||||
|
float vol = EaglerAdapter.getVoiceListenVolume();
|
||||||
|
drawRect(-89, 43, -89 + (int)(vol * 90), 51, 0xFF993322);
|
||||||
|
|
||||||
|
for(float f = 0.07f; f < vol; f += 0.08f) {
|
||||||
|
int ww = (int)(f * 90);
|
||||||
|
drawRect(-89 + ww, 43, -89 + ww + 1, 51, 0xFF999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawRect(-90, 57, 2, 67, 0xFFAAAAAA);
|
||||||
|
drawRect(-89, 58, 1, 66, 0xFF222222);
|
||||||
|
|
||||||
|
vol = EaglerAdapter.getVoiceSpeakVolume();
|
||||||
|
drawRect(-89, 58, -89 + (int)(vol * 90), 66, 0xFF993322);
|
||||||
|
|
||||||
|
for(float f = 0.07f; f < vol; f += 0.08f) {
|
||||||
|
int ww = (int)(f * 90);
|
||||||
|
drawRect(-89 + ww, 58, -89 + ww + 1, 66, 0xFF999999);
|
||||||
|
}
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
EaglerAdapter.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(-104.0f, 41.5f, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(0.7f, 0.7f, 0.7f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 112, 16, 16);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(-104.0f, 56.5f, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(0.7f, 0.7f, 0.7f);
|
||||||
|
if(EaglerAdapter.isKeyDown(mc.gameSettings.voicePTTKey)) {
|
||||||
|
EaglerAdapter.glColor4f(0.9f, 0.4f, 0.4f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 32, 16, 16);
|
||||||
|
}else {
|
||||||
|
drawTexturedModalRect(0, 0, 64, 0, 16, 16);
|
||||||
|
}
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
txt = ts.translateKey("voice.ptt").replace("$key$", EaglerAdapter.getKeyName(mc.gameSettings.voicePTTKey));
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt) - 10, 76, 0x66DD66);
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
EaglerAdapter.glColor4f(0.4f, 0.9f, 0.4f, 1.0f);
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(-7.0f, 74.5f, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(0.35f, 0.35f, 0.35f);
|
||||||
|
drawTexturedModalRect(0, 0, 32, 192, 32, 32);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
txt = ts.translateKey("voice.playersListening");
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(0.0f, 98.0f, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(1.2f, 1.2f, 1.2f);
|
||||||
|
drawString(fontRenderer, txt, -fontRenderer.getStringWidth(txt), 0, 0xFF7777);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
List<String> playersToRender = EaglerAdapter.getVoiceRecent();
|
||||||
|
|
||||||
|
if(playersToRender.size() > 0) {
|
||||||
|
Set<String> playersSpeaking = EaglerAdapter.getVoiceSpeaking();
|
||||||
|
Set<String> playersMuted = EaglerAdapter.getVoiceMuted();
|
||||||
|
for(int i = 0, l = playersToRender.size(); i < l; ++i) {
|
||||||
|
txt = playersToRender.get(i);
|
||||||
|
|
||||||
|
boolean muted = playersMuted.contains(txt);
|
||||||
|
boolean speaking = !muted && playersSpeaking.contains(txt);
|
||||||
|
|
||||||
|
int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9;
|
||||||
|
boolean hovered = mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9;
|
||||||
|
float cm = hovered ? 1.5f : 1.0f;
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(-100.0f, 115.0f + i * 12.0f, 0.0f);
|
||||||
|
EaglerAdapter.glScalef(0.78f, 0.78f, 0.78f);
|
||||||
|
|
||||||
|
if(muted) {
|
||||||
|
EaglerAdapter.glColor4f(1.0f * cm, 0.2f * cm, 0.2f * cm, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 176, 16, 16);
|
||||||
|
}else if(speaking) {
|
||||||
|
EaglerAdapter.glColor4f(1.0f * cm, 1.0f * cm, 1.0f * cm, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glColor4f(0.65f * cm, 0.65f * cm, 0.65f * cm, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 112, 16, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
if(muted) {
|
||||||
|
drawString(fontRenderer, txt, -84, 117 + i * 12, attenuate(0xCC4444, cm));
|
||||||
|
}else if(speaking) {
|
||||||
|
drawString(fontRenderer, txt, -84, 117 + i * 12, attenuate(0xCCCCCC, cm));
|
||||||
|
}else {
|
||||||
|
drawString(fontRenderer, txt, -84, 117 + i * 12, attenuate(0x999999, cm));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
txt = "(none)";
|
||||||
|
drawString(fontRenderer, txt, -fontRenderer.getStringWidth(txt), 112, 0xAAAAAA);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else if(status == Voice.VoiceStatus.CONNECTING) {
|
||||||
|
float fadeTimer = MathHelper.sin((float)((System.currentTimeMillis() % 700l) * 0.0014d) * 3.14159f) * 0.35f + 0.3f;
|
||||||
|
txt = ts.translateKey("voice.connecting");
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
||||||
|
EaglerAdapter.glBlendFunc(EaglerAdapter.GL_SRC_ALPHA, EaglerAdapter.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 5, (0xFFDD77 | ((int)(Math.pow(fadeTimer, 1.0d / 2.2d) * 255.0f) << 24)));
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||||
|
}else if(status == Voice.VoiceStatus.UNAVAILABLE) {
|
||||||
|
txt = ts.translateKey("voice.unavailable");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 5, 0xFF3333);
|
||||||
|
}else {
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flag) {
|
||||||
|
txt = ts.translateKey("voice.notConnected");
|
||||||
|
drawString(fontRenderer, txt, 1 - fontRenderer.getStringWidth(txt), 5, 0xBB9999);
|
||||||
|
}
|
||||||
|
|
||||||
|
String OFFstring = ts.translateKey("voice.off");
|
||||||
|
String RADIUSstring = ts.translateKey("voice.radius");
|
||||||
|
String GLOBALstring = ts.translateKey("voice.global");
|
||||||
|
|
||||||
|
int OFFwidth = fontRenderer.getStringWidth(OFFstring);
|
||||||
|
int RADIUSwidth = fontRenderer.getStringWidth(RADIUSstring);
|
||||||
|
int GLOBALwidth = fontRenderer.getStringWidth(GLOBALstring);
|
||||||
|
|
||||||
|
voiceButtonOFFposX = 0 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth;
|
||||||
|
voiceButtonOFFposY = 20;
|
||||||
|
voiceButtonOFFposW = OFFwidth + 5;
|
||||||
|
voiceButtonOFFposH = 15;
|
||||||
|
|
||||||
|
voiceScreenButtonOFFposX = voiceButtonOFFposX * 3 / 4 + width - 6;
|
||||||
|
voiceScreenButtonOFFposY = 15 + (voiceButtonOFFposY + xo) * 3 / 4;
|
||||||
|
voiceScreenButtonOFFposW = voiceButtonOFFposW * 3 / 4;
|
||||||
|
voiceScreenButtonOFFposH = voiceButtonOFFposH * 3 / 4;
|
||||||
|
|
||||||
|
voiceButtonRADIUSposX = 0 - RADIUSwidth - 8 - GLOBALwidth;
|
||||||
|
voiceButtonRADIUSposY = 20;
|
||||||
|
voiceButtonRADIUSposW = RADIUSwidth + 5;
|
||||||
|
voiceButtonRADIUSposH = 15;
|
||||||
|
|
||||||
|
voiceScreenButtonRADIUSposX = voiceButtonRADIUSposX * 3 / 4 + width - 6;
|
||||||
|
voiceScreenButtonRADIUSposY = 15 + (voiceButtonRADIUSposY + xo) * 3 / 4;
|
||||||
|
voiceScreenButtonRADIUSposW = voiceButtonRADIUSposW * 3 / 4;
|
||||||
|
voiceScreenButtonRADIUSposH = voiceButtonRADIUSposH * 3 / 4;
|
||||||
|
|
||||||
|
voiceButtonGLOBALposX = 0 - GLOBALwidth;
|
||||||
|
voiceButtonGLOBALposY = 20;
|
||||||
|
voiceButtonGLOBALposW = GLOBALwidth + 5;
|
||||||
|
voiceButtonGLOBALposH = 15;
|
||||||
|
|
||||||
|
voiceScreenButtonGLOBALposX = voiceButtonGLOBALposX * 3 / 4 + width - 6;
|
||||||
|
voiceScreenButtonGLOBALposY = 15 + (voiceButtonGLOBALposY + xo) * 3 / 4;
|
||||||
|
voiceScreenButtonGLOBALposW = voiceButtonGLOBALposW * 3 / 4;
|
||||||
|
voiceScreenButtonGLOBALposH = voiceButtonGLOBALposH * 3 / 4;
|
||||||
|
|
||||||
|
if(channel == Voice.VoiceChannel.NONE) {
|
||||||
|
drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFFCCCCCC);
|
||||||
|
drawRect(voiceButtonOFFposX + 1, voiceButtonOFFposY + 1, voiceButtonOFFposX + voiceButtonOFFposW - 2,
|
||||||
|
voiceButtonOFFposY + voiceButtonOFFposH - 1, 0xFF222222);
|
||||||
|
}else if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX +
|
||||||
|
voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) {
|
||||||
|
drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFF777777);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(channel == Voice.VoiceChannel.PROXIMITY) {
|
||||||
|
drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFFCCCCCC);
|
||||||
|
drawRect(voiceButtonRADIUSposX + 1, voiceButtonRADIUSposY + 1, voiceButtonRADIUSposX + voiceButtonRADIUSposW - 2,
|
||||||
|
voiceButtonRADIUSposY + voiceButtonRADIUSposH - 1, 0xFF222222);
|
||||||
|
}else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX +
|
||||||
|
voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) {
|
||||||
|
drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFF777777);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(channel == Voice.VoiceChannel.GLOBAL) {
|
||||||
|
drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFFCCCCCC);
|
||||||
|
drawRect(voiceButtonGLOBALposX + 1, voiceButtonGLOBALposY + 1, voiceButtonGLOBALposX + voiceButtonGLOBALposW - 2,
|
||||||
|
voiceButtonGLOBALposY + voiceButtonGLOBALposH - 1, 0xFF222222);
|
||||||
|
}else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX +
|
||||||
|
voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) {
|
||||||
|
drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFF777777);
|
||||||
|
}
|
||||||
|
|
||||||
|
int enabledColor = (status == Voice.VoiceStatus.CONNECTED || channel == Voice.VoiceChannel.NONE) ? 0x66DD66 : 0xDDCC66;
|
||||||
|
int disabledColor = 0xDD4444;
|
||||||
|
|
||||||
|
if(status == Voice.VoiceStatus.UNAVAILABLE) {
|
||||||
|
enabledColor = disabledColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawString(fontRenderer, OFFstring, 3 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == Voice.VoiceChannel.NONE ? enabledColor : disabledColor);
|
||||||
|
drawString(fontRenderer, RADIUSstring, 3 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == Voice.VoiceChannel.PROXIMITY ? enabledColor : disabledColor);
|
||||||
|
drawString(fontRenderer, GLOBALstring, 3 - GLOBALwidth, 24, channel == Voice.VoiceChannel.GLOBAL ? enabledColor : disabledColor);
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
super.drawScreen(mx, my, partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int attenuate(int cin, float f) {
|
||||||
|
return attenuate(cin, f, f, f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int attenuate(int cin, float r, float g, float b, float a) {
|
||||||
|
float var10 = (float) (cin >> 24 & 255) / 255.0F;
|
||||||
|
float var6 = (float) (cin >> 16 & 255) / 255.0F;
|
||||||
|
float var7 = (float) (cin >> 8 & 255) / 255.0F;
|
||||||
|
float var8 = (float) (cin & 255) / 255.0F;
|
||||||
|
var10 *= a;
|
||||||
|
var6 *= r;
|
||||||
|
var7 *= g;
|
||||||
|
var8 *= b;
|
||||||
|
if(var10 > 1.0f) {
|
||||||
|
var10 = 1.0f;
|
||||||
|
}
|
||||||
|
if(var6 > 1.0f) {
|
||||||
|
var6 = 1.0f;
|
||||||
|
}
|
||||||
|
if(var7 > 1.0f) {
|
||||||
|
var7 = 1.0f;
|
||||||
|
}
|
||||||
|
if(var8 > 1.0f) {
|
||||||
|
var8 = 1.0f;
|
||||||
|
}
|
||||||
|
return (((int)(var10 * 255.0f) << 24) | ((int)(var6 * 255.0f) << 16) | ((int)(var7 * 255.0f) << 8) | (int)(var8 * 255.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawOutline(int x, int y, int w, int h, int color) {
|
||||||
|
drawRect(x, y, x + w, y + 1, color);
|
||||||
|
drawRect(x + w - 1, y + 1, x + w, y + h - 1, color);
|
||||||
|
drawRect(x, y + h - 1, x + w, y + h, color);
|
||||||
|
drawRect(x, y + 1, x + 1, y + h - 1, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseMovedOrUp(int par1, int par2, int par3) {
|
||||||
|
super.mouseMovedOrUp(par1, par2, par3);
|
||||||
|
if(showSliderBlocks || showSliderVolume) {
|
||||||
|
if(showSliderBlocks) {
|
||||||
|
if(par3 == 0) {
|
||||||
|
sliderBlocks.mouseReleased(par1, par2);
|
||||||
|
}
|
||||||
|
}else if(showSliderVolume) {
|
||||||
|
if(par3 == 0) {
|
||||||
|
sliderListenVolume.mouseReleased(par1, par2);
|
||||||
|
sliderSpeakVolume.mouseReleased(par1, par2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new AbortedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyTyped(char par1, int par2) {
|
||||||
|
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) {
|
||||||
|
if(showPTTKeyConfig) {
|
||||||
|
if(par2 == 1) {
|
||||||
|
showPTTKeyConfig = false;
|
||||||
|
}else {
|
||||||
|
mc.gameSettings.voicePTTKey = par2;
|
||||||
|
showNewPTTKey = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new AbortedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseClicked(int mx, int my, int button) {
|
||||||
|
if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) {
|
||||||
|
if(showSliderBlocks) {
|
||||||
|
sliderBlocks.mousePressed(mc, mx, my);
|
||||||
|
}else if(showSliderVolume) {
|
||||||
|
sliderListenVolume.mousePressed(mc, mx, my);
|
||||||
|
sliderSpeakVolume.mousePressed(mc, mx, my);
|
||||||
|
}
|
||||||
|
super.mouseClicked(mx, my, button);
|
||||||
|
throw new AbortedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
Voice.VoiceStatus status = EaglerAdapter.getVoiceStatus();
|
||||||
|
Voice.VoiceChannel channel = EaglerAdapter.getVoiceChannel();
|
||||||
|
|
||||||
|
if(button == 0) {
|
||||||
|
if(EaglerAdapter.voiceAvailable() && EaglerAdapter.voiceAllowed()) {
|
||||||
|
if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX +
|
||||||
|
voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) {
|
||||||
|
EaglerAdapter.enableVoice(Voice.VoiceChannel.NONE);
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX +
|
||||||
|
voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) {
|
||||||
|
EaglerAdapter.enableVoice(Voice.VoiceChannel.PROXIMITY);
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX +
|
||||||
|
voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) {
|
||||||
|
EaglerAdapter.enableVoice(Voice.VoiceChannel.GLOBAL);
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(channel == Voice.VoiceChannel.PROXIMITY && status == Voice.VoiceStatus.CONNECTED && mx >= voiceScreenButtonChangeRadiusposX &&
|
||||||
|
my >= voiceScreenButtonChangeRadiusposY && mx < voiceScreenButtonChangeRadiusposX + voiceScreenButtonChangeRadiusposW &&
|
||||||
|
my < voiceScreenButtonChangeRadiusposY + voiceScreenButtonChangeRadiusposH) {
|
||||||
|
showSliderBlocks = true;
|
||||||
|
sliderBlocks.sliderValue = (EaglerAdapter.getVoiceProximity() - 5) / 17.0f;
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(status == Voice.VoiceStatus.CONNECTED && channel != Voice.VoiceChannel.NONE && mx >= voiceScreenVolumeIndicatorX &&
|
||||||
|
my >= voiceScreenVolumeIndicatorY && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW &&
|
||||||
|
my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH) {
|
||||||
|
showSliderVolume = true;
|
||||||
|
sliderListenVolume.sliderValue = EaglerAdapter.getVoiceListenVolume();
|
||||||
|
sliderSpeakVolume.sliderValue = EaglerAdapter.getVoiceSpeakVolume();
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(status == Voice.VoiceStatus.CONNECTED && channel != Voice.VoiceChannel.NONE && mx >= voiceScreenVolumeIndicatorX - 1 &&
|
||||||
|
my >= voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 2 && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 &&
|
||||||
|
my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 12) {
|
||||||
|
showPTTKeyConfig = true;
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
}else if(status == Voice.VoiceStatus.CONNECTED) {
|
||||||
|
List<String> playersToRender = EaglerAdapter.getVoiceRecent();
|
||||||
|
if(playersToRender.size() > 0) {
|
||||||
|
Set<String> playersMuted = EaglerAdapter.getVoiceMuted();
|
||||||
|
for(int i = 0, l = playersToRender.size(); i < l; ++i) {
|
||||||
|
String txt = playersToRender.get(i);
|
||||||
|
boolean muted = playersMuted.contains(txt);
|
||||||
|
int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9;
|
||||||
|
if(mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9) {
|
||||||
|
EaglerAdapter.setVoiceMuted(txt, !muted);
|
||||||
|
this.mc.sndManager.playSoundFX("random.click", 1.0F, 1.0F);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(GuiButton btn) {
|
||||||
|
if(btn.id == 2) {
|
||||||
|
showSliderBlocks = false;
|
||||||
|
EaglerAdapter.setVoiceProximity(mc.gameSettings.voiceListenRadius = (int)((sliderBlocks.sliderValue * 17.0f) + 5.0f));
|
||||||
|
mc.gameSettings.saveOptions();
|
||||||
|
}else if(btn.id == 3) {
|
||||||
|
showSliderVolume = false;
|
||||||
|
EaglerAdapter.setVoiceListenVolume(mc.gameSettings.voiceListenVolume = sliderListenVolume.sliderValue);
|
||||||
|
EaglerAdapter.setVoiceSpeakVolume(mc.gameSettings.voiceSpeakVolume = sliderSpeakVolume.sliderValue);
|
||||||
|
mc.gameSettings.saveOptions();
|
||||||
|
}else if(btn.id == 4) {
|
||||||
|
showPTTKeyConfig = false;
|
||||||
|
mc.gameSettings.saveOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateScreen() {
|
||||||
|
if(showNewPTTKey > 0) {
|
||||||
|
--showNewPTTKey;
|
||||||
|
if(showNewPTTKey == 0) {
|
||||||
|
showPTTKeyConfig = false;
|
||||||
|
mc.gameSettings.saveOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBlockingInput() {
|
||||||
|
return showSliderBlocks || showSliderVolume || showPTTKeyConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
229
src/main/java/net/lax1dude/eaglercraft/GuiVoiceOverlay.java
Normal file
229
src/main/java/net/lax1dude/eaglercraft/GuiVoiceOverlay.java
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.src.Gui;
|
||||||
|
import net.minecraft.src.GuiChat;
|
||||||
|
import net.minecraft.src.GuiIngameMenu;
|
||||||
|
|
||||||
|
public class GuiVoiceOverlay extends Gui {
|
||||||
|
|
||||||
|
public final Minecraft mc;
|
||||||
|
public int width;
|
||||||
|
public int height;
|
||||||
|
|
||||||
|
private long pttTimer = 0l;
|
||||||
|
|
||||||
|
public GuiVoiceOverlay(Minecraft mc) {
|
||||||
|
this.mc = mc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResolution(int w, int h) {
|
||||||
|
this.width = w;
|
||||||
|
this.height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TextureLocation voiceGuiIcons = new TextureLocation("/gui/voice.png");
|
||||||
|
|
||||||
|
public void drawOverlay() {
|
||||||
|
if(mc.theWorld != null && EaglerAdapter.getVoiceStatus() == Voice.VoiceStatus.CONNECTED && EaglerAdapter.getVoiceChannel() != Voice.VoiceChannel.NONE &&
|
||||||
|
!(mc.currentScreen != null && (mc.currentScreen instanceof GuiIngameMenu))) {
|
||||||
|
|
||||||
|
if(mc.currentScreen != null && mc.currentScreen.doesGuiPauseGame()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
|
||||||
|
if(mc.currentScreen == null || (mc.currentScreen instanceof GuiChat)) {
|
||||||
|
EaglerAdapter.glTranslatef(width / 2 + 77, height - 56, 0.0f);
|
||||||
|
if(mc.thePlayer == null || mc.thePlayer.capabilities.isCreativeMode) {
|
||||||
|
EaglerAdapter.glTranslatef(0.0f, 16.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glTranslatef(width / 2 + 10, 4, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
|
||||||
|
String txxt = "press '" + EaglerAdapter.getKeyName(mc.gameSettings.voicePTTKey) + "'";
|
||||||
|
drawString(mc.fontRenderer, txxt, -3 - mc.fontRenderer.getStringWidth(txxt), 9, 0xDDDDDD);
|
||||||
|
|
||||||
|
EaglerAdapter.glScalef(0.66f, 0.66f, 0.66f);
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
|
||||||
|
if(EaglerAdapter.isKeyDown(mc.gameSettings.voicePTTKey)) {
|
||||||
|
long millis = System.currentTimeMillis();
|
||||||
|
if(pttTimer == 0l) {
|
||||||
|
pttTimer = millis;
|
||||||
|
}
|
||||||
|
EaglerAdapter.glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 0, 32, 32, 32);
|
||||||
|
EaglerAdapter.glTranslatef(-1.5f, -1.5f, 0.0f);
|
||||||
|
if(millis - pttTimer < 1050l) {
|
||||||
|
if((millis - pttTimer) % 300l < 150l) {
|
||||||
|
EaglerAdapter.glColor4f(0.9f, 0.2f, 0.2f, 1.0f);
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glColor4f(0.9f, 0.7f, 0.7f, 1.0f);
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glColor4f(0.9f, 0.3f, 0.3f, 1.0f);
|
||||||
|
}
|
||||||
|
drawTexturedModalRect(0, 0, 0, 32, 32, 32);
|
||||||
|
}else {
|
||||||
|
pttTimer = 0l;
|
||||||
|
EaglerAdapter.glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 0, 0, 32, 32);
|
||||||
|
EaglerAdapter.glTranslatef(-1.5f, -1.5f, 0.0f);
|
||||||
|
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 0, 0, 32, 32);
|
||||||
|
EaglerAdapter.glTranslatef(-0.5f, -0.5f, 0.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 0, 0, 32, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
if(EaglerAdapter.getVoiceChannel() == Voice.VoiceChannel.PROXIMITY) {
|
||||||
|
Set<String> listeners = EaglerAdapter.getVoiceListening();
|
||||||
|
if(listeners.size() > 0) {
|
||||||
|
Set<String> speakers = EaglerAdapter.getVoiceSpeaking();
|
||||||
|
Set<String> muted = EaglerAdapter.getVoiceMuted();
|
||||||
|
|
||||||
|
List<String> listenerList = new ArrayList();
|
||||||
|
listenerList.addAll(listeners);
|
||||||
|
listenerList.removeAll(muted);
|
||||||
|
|
||||||
|
while(listenerList.size() > 5) {
|
||||||
|
boolean flag = false;
|
||||||
|
for(int i = 0, l = listenerList.size(); i < l; ++i) {
|
||||||
|
if(!speakers.contains(listenerList.get(i))) {
|
||||||
|
listenerList.remove(i);
|
||||||
|
flag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!flag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int more = listenerList.size() - 5;
|
||||||
|
|
||||||
|
int ww = width;
|
||||||
|
int hh = height;
|
||||||
|
|
||||||
|
if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) {
|
||||||
|
hh -= 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
int left = 50;
|
||||||
|
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
|
||||||
|
int j = mc.fontRenderer.getStringWidth(listenerList.get(i)) + 4;
|
||||||
|
if(j > left) {
|
||||||
|
left = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(more > 0) {
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(ww - left + 3, hh - 10, left);
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
drawString(mc.fontRenderer, "(" + more + " more)", 0, 0, 0xBBBBBB);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
hh -= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
|
||||||
|
|
||||||
|
String txt = listenerList.get(i);
|
||||||
|
boolean speaking = speakers.contains(txt);
|
||||||
|
float speakf = speaking ? 1.0f : 0.75f;
|
||||||
|
|
||||||
|
drawString(mc.fontRenderer, txt, ww - left, hh - 13 - i * 11, speaking ? 0xEEEEEE : 0xBBBBBB);
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(ww - left - 14, hh - 14 - i * 11, 0.0f);
|
||||||
|
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
EaglerAdapter.glColor4f(speakf * 0.2f, speakf * 0.2f, speakf * 0.2f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, speaking ? 144 : 176, 16, 16);
|
||||||
|
EaglerAdapter.glTranslatef(0.25f, 0.25f, 0.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, speaking ? 144 : 176, 16, 16);
|
||||||
|
|
||||||
|
EaglerAdapter.glTranslatef(-1.25f, -1.25f, 0.0f);
|
||||||
|
EaglerAdapter.glColor4f(speakf, speakf, speakf, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, speaking ? 144 : 176, 16, 16);
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}else if(EaglerAdapter.getVoiceChannel() == Voice.VoiceChannel.GLOBAL) {
|
||||||
|
Set<String> speakers = EaglerAdapter.getVoiceSpeaking();
|
||||||
|
Set<String> muted = EaglerAdapter.getVoiceMuted();
|
||||||
|
|
||||||
|
List<String> listenerList = new ArrayList();
|
||||||
|
listenerList.addAll(speakers);
|
||||||
|
listenerList.removeAll(muted);
|
||||||
|
|
||||||
|
int more = listenerList.size() - 5;
|
||||||
|
|
||||||
|
int ww = width;
|
||||||
|
int hh = height;
|
||||||
|
|
||||||
|
if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) {
|
||||||
|
hh -= 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
int left = 50;
|
||||||
|
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
|
||||||
|
int j = mc.fontRenderer.getStringWidth(listenerList.get(i)) + 4;
|
||||||
|
if(j > left) {
|
||||||
|
left = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(more > 0) {
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(ww - left + 3, hh - 10, left);
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
drawString(mc.fontRenderer, "(" + more + " more)", 0, 0, 0xBBBBBB);
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
hh -= 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) {
|
||||||
|
String txt = listenerList.get(i);
|
||||||
|
|
||||||
|
drawString(mc.fontRenderer, txt, ww - left, hh - 13 - i * 11, 0xEEEEEE);
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(ww - left - 14, hh - 14 - i * 11, 0.0f);
|
||||||
|
|
||||||
|
EaglerAdapter.glScalef(0.75f, 0.75f, 0.75f);
|
||||||
|
EaglerAdapter.glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
|
||||||
|
EaglerAdapter.glTranslatef(0.25f, 0.25f, 0.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
|
||||||
|
|
||||||
|
EaglerAdapter.glTranslatef(-1.25f, -1.25f, 0.0f);
|
||||||
|
EaglerAdapter.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
drawTexturedModalRect(0, 0, 64, 144, 16, 16);
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
13
src/main/java/net/lax1dude/eaglercraft/Voice.java
Normal file
13
src/main/java/net/lax1dude/eaglercraft/Voice.java
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package net.lax1dude.eaglercraft;
|
||||||
|
|
||||||
|
public class Voice {
|
||||||
|
|
||||||
|
public static enum VoiceChannel {
|
||||||
|
NONE, GLOBAL, PROXIMITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum VoiceStatus {
|
||||||
|
DISCONNECTED, CONNECTING, CONNECTED, UNAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -117,6 +117,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void serverShutdown() {
|
public void serverShutdown() {
|
||||||
|
EaglerAdapter.setVoiceStatus(Voice.VoiceStatus.DISCONNECTED);
|
||||||
if(EaglerAdapter.connectionOpen()) {
|
if(EaglerAdapter.connectionOpen()) {
|
||||||
EaglerAdapter.endConnection();
|
EaglerAdapter.endConnection();
|
||||||
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
||||||
|
@ -132,6 +133,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeConnections() {
|
public void closeConnections() {
|
||||||
|
EaglerAdapter.setVoiceStatus(Voice.VoiceStatus.DISCONNECTED);
|
||||||
if(EaglerAdapter.connectionOpen()) {
|
if(EaglerAdapter.connectionOpen()) {
|
||||||
EaglerAdapter.endConnection();
|
EaglerAdapter.endConnection();
|
||||||
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
||||||
|
|
|
@ -11,7 +11,7 @@ import net.lax1dude.eaglercraft.EaglerProfile;
|
||||||
|
|
||||||
import net.lax1dude.eaglercraft.GuiScreenEditProfile;
|
import net.lax1dude.eaglercraft.GuiScreenEditProfile;
|
||||||
import net.lax1dude.eaglercraft.GuiScreenLicense;
|
import net.lax1dude.eaglercraft.GuiScreenLicense;
|
||||||
import net.lax1dude.eaglercraft.GuiScreenVoiceChannel;
|
import net.lax1dude.eaglercraft.GuiVoiceOverlay;
|
||||||
import net.lax1dude.eaglercraft.LocalStorageManager;
|
import net.lax1dude.eaglercraft.LocalStorageManager;
|
||||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||||
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
||||||
|
@ -165,6 +165,8 @@ public class Minecraft implements Runnable {
|
||||||
|
|
||||||
/** Profiler currently displayed in the debug screen pie chart */
|
/** Profiler currently displayed in the debug screen pie chart */
|
||||||
private String debugProfilerName = "root";
|
private String debugProfilerName = "root";
|
||||||
|
|
||||||
|
public GuiVoiceOverlay voiceOverlay;
|
||||||
|
|
||||||
public Minecraft() {
|
public Minecraft() {
|
||||||
this.tempDisplayHeight = 480;
|
this.tempDisplayHeight = 480;
|
||||||
|
@ -240,6 +242,7 @@ public class Minecraft implements Runnable {
|
||||||
this.checkGLError("Post startup");
|
this.checkGLError("Post startup");
|
||||||
this.guiAchievement = new GuiAchievement(this);
|
this.guiAchievement = new GuiAchievement(this);
|
||||||
this.ingameGUI = new GuiIngame(this);
|
this.ingameGUI = new GuiIngame(this);
|
||||||
|
this.voiceOverlay = new GuiVoiceOverlay(this);
|
||||||
|
|
||||||
//if (this.serverName != null) {
|
//if (this.serverName != null) {
|
||||||
// this.displayGuiScreen(new GuiConnecting(new GuiMainMenu(), this, this.serverName, this.serverPort));
|
// this.displayGuiScreen(new GuiConnecting(new GuiMainMenu(), this, this.serverName, this.serverPort));
|
||||||
|
@ -443,7 +446,6 @@ public class Minecraft implements Runnable {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiScreenVoiceChannel.fadeInTimer = System.currentTimeMillis();
|
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
||||||
EaglerAdapter.glAlphaFunc(EaglerAdapter.GL_GREATER, 0.1F);
|
EaglerAdapter.glAlphaFunc(EaglerAdapter.GL_GREATER, 0.1F);
|
||||||
|
@ -1039,12 +1041,15 @@ public class Minecraft implements Runnable {
|
||||||
this.displayWidth = par1 <= 0 ? 1 : par1;
|
this.displayWidth = par1 <= 0 ? 1 : par1;
|
||||||
this.displayHeight = par2 <= 0 ? 1 : par2;
|
this.displayHeight = par2 <= 0 ? 1 : par2;
|
||||||
|
|
||||||
|
ScaledResolution var3 = new ScaledResolution(this.gameSettings, par1, par2);
|
||||||
|
int var4 = var3.getScaledWidth();
|
||||||
|
int var5 = var3.getScaledHeight();
|
||||||
|
|
||||||
if (this.currentScreen != null) {
|
if (this.currentScreen != null) {
|
||||||
ScaledResolution var3 = new ScaledResolution(this.gameSettings, par1, par2);
|
|
||||||
int var4 = var3.getScaledWidth();
|
|
||||||
int var5 = var3.getScaledHeight();
|
|
||||||
this.currentScreen.setWorldAndResolution(this, var4, var5);
|
this.currentScreen.setWorldAndResolution(this, var4, var5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.voiceOverlay.setResolution(var4, var5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1104,7 +1109,7 @@ public class Minecraft implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiMultiplayer.tickRefreshCooldown();
|
GuiMultiplayer.tickRefreshCooldown();
|
||||||
GuiScreenVoiceChannel.tickVoiceConnection();
|
EaglerAdapter.tickVoice();
|
||||||
|
|
||||||
if (this.currentScreen == null || this.currentScreen.allowUserInput) {
|
if (this.currentScreen == null || this.currentScreen.allowUserInput) {
|
||||||
this.mcProfiler.endStartSection("mouse");
|
this.mcProfiler.endStartSection("mouse");
|
||||||
|
|
|
@ -7,7 +7,6 @@ import net.minecraft.client.Minecraft;
|
||||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||||
import net.lax1dude.eaglercraft.EaglerImage;
|
import net.lax1dude.eaglercraft.EaglerImage;
|
||||||
import net.lax1dude.eaglercraft.EaglercraftRandom;
|
import net.lax1dude.eaglercraft.EaglercraftRandom;
|
||||||
import net.lax1dude.eaglercraft.GuiScreenVoiceChannel;
|
|
||||||
import net.lax1dude.eaglercraft.TextureLocation;
|
import net.lax1dude.eaglercraft.TextureLocation;
|
||||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||||
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
||||||
|
@ -876,7 +875,7 @@ public class EntityRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiScreenVoiceChannel.drawOverlay();
|
mc.voiceOverlay.drawOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,9 +134,14 @@ public class GameSettings {
|
||||||
|
|
||||||
public boolean allowFNAWSkins = true;
|
public boolean allowFNAWSkins = true;
|
||||||
public boolean showOtherCapes = true;
|
public boolean showOtherCapes = true;
|
||||||
|
|
||||||
public int chunkUpdatePerFrame = 0;
|
public int chunkUpdatePerFrame = 0;
|
||||||
|
|
||||||
|
public int voiceListenRadius = 16;
|
||||||
|
public float voiceListenVolume = 0.5f;
|
||||||
|
public float voiceSpeakVolume = 0.5f;
|
||||||
|
public int voicePTTKey = 47;
|
||||||
|
|
||||||
public GameSettings(Minecraft par1Minecraft) {
|
public GameSettings(Minecraft par1Minecraft) {
|
||||||
this.keyBindings = new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, this.keyBindForward, this.keyBindLeft, this.keyBindBack, this.keyBindRight, this.keyBindJump, this.keyBindSneak, this.keyBindDrop, this.keyBindInventory,
|
this.keyBindings = new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, this.keyBindForward, this.keyBindLeft, this.keyBindBack, this.keyBindRight, this.keyBindJump, this.keyBindSneak, this.keyBindDrop, this.keyBindInventory,
|
||||||
this.keyBindChat, this.keyBindPlayerList, this.keyBindPickBlock, this.keyBindSprint, this.keyBindZoom, this.keyBindFunction };
|
this.keyBindChat, this.keyBindPlayerList, this.keyBindPickBlock, this.keyBindSprint, this.keyBindZoom, this.keyBindFunction };
|
||||||
|
@ -526,6 +531,17 @@ public class GameSettings {
|
||||||
if(yee.hasKey("allowFNAWSkins")) allowFNAWSkins = yee.getBoolean("allowFNAWSkins");
|
if(yee.hasKey("allowFNAWSkins")) allowFNAWSkins = yee.getBoolean("allowFNAWSkins");
|
||||||
if(yee.hasKey("showOtherCapes")) showOtherCapes = yee.getBoolean("showOtherCapes");
|
if(yee.hasKey("showOtherCapes")) showOtherCapes = yee.getBoolean("showOtherCapes");
|
||||||
if(yee.hasKey("chunkUpdates")) chunkUpdatePerFrame = yee.getInteger("chunkUpdates");
|
if(yee.hasKey("chunkUpdates")) chunkUpdatePerFrame = yee.getInteger("chunkUpdates");
|
||||||
|
if(yee.hasKey("voiceListenVolume")) voiceListenVolume = yee.getFloat("voiceListenVolume");
|
||||||
|
if(yee.hasKey("voiceSpeakVolume")) voiceSpeakVolume = yee.getFloat("voiceSpeakVolume");
|
||||||
|
if(yee.hasKey("voicePTTKey")) voicePTTKey = yee.getInteger("voicePTTKey");
|
||||||
|
if(yee.hasKey("voiceListenRadius")) voiceListenRadius = yee.getInteger("voiceListenRadius");
|
||||||
|
|
||||||
|
if(voiceListenRadius < 5) voiceListenRadius = 5;
|
||||||
|
else if(voiceListenRadius > 22) voiceListenRadius = 22;
|
||||||
|
|
||||||
|
EaglerAdapter.setVoiceListenVolume(voiceListenVolume);
|
||||||
|
EaglerAdapter.setVoiceSpeakVolume(voiceSpeakVolume);
|
||||||
|
EaglerAdapter.setVoiceProximity(voiceListenRadius);
|
||||||
|
|
||||||
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
||||||
if(yee.hasKey(keyBindings[var4].keyDescription)) this.keyBindings[var4].keyCode = yee.getInteger(keyBindings[var4].keyDescription);
|
if(yee.hasKey(keyBindings[var4].keyDescription)) this.keyBindings[var4].keyCode = yee.getInteger(keyBindings[var4].keyDescription);
|
||||||
|
@ -589,6 +605,10 @@ public class GameSettings {
|
||||||
yee.setBoolean("allowFNAWSkins", allowFNAWSkins);
|
yee.setBoolean("allowFNAWSkins", allowFNAWSkins);
|
||||||
yee.setBoolean("showOtherCapes", showOtherCapes);
|
yee.setBoolean("showOtherCapes", showOtherCapes);
|
||||||
yee.setInteger("chunkUpdates", chunkUpdatePerFrame);
|
yee.setInteger("chunkUpdates", chunkUpdatePerFrame);
|
||||||
|
yee.setFloat("voiceListenVolume", voiceListenVolume);
|
||||||
|
yee.setFloat("voiceSpeakVolume", voiceSpeakVolume);
|
||||||
|
yee.setInteger("voicePTTKey", voicePTTKey);
|
||||||
|
yee.setInteger("voiceListenRadius", voiceListenRadius);
|
||||||
|
|
||||||
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
for (int var4 = 0; var4 < this.keyBindings.length; ++var4) {
|
||||||
yee.setInteger(keyBindings[var4].keyDescription, keyBindings[var4].keyCode);
|
yee.setInteger(keyBindings[var4].keyDescription, keyBindings[var4].keyCode);
|
||||||
|
@ -626,4 +646,4 @@ public class GameSettings {
|
||||||
public boolean shouldRenderClouds() {
|
public boolean shouldRenderClouds() {
|
||||||
return this.renderDistance < 2 && this.clouds;
|
return this.renderDistance < 2 && this.clouds;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -464,12 +464,15 @@ public class GuiIngame extends Gui {
|
||||||
var8.drawStringWithShadow("x: "+MathHelper.floor_double(this.mc.thePlayer.posX)+", y: "+MathHelper.floor_double(this.mc.thePlayer.posY)+", z: "+MathHelper.floor_double(this.mc.thePlayer.posZ), 2, 12, 16777215);
|
var8.drawStringWithShadow("x: "+MathHelper.floor_double(this.mc.thePlayer.posX)+", y: "+MathHelper.floor_double(this.mc.thePlayer.posY)+", z: "+MathHelper.floor_double(this.mc.thePlayer.posZ), 2, 12, 16777215);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = this.mc.isChatOpen() ? 135 : 0;
|
if(mc.currentScreen == null || !(mc.currentScreen instanceof GuiIngameMenu)) {
|
||||||
int offset2 = this.mc.isChatOpen() ? 4 : 0;
|
int offset = this.mc.isChatOpen() ? 135 : 0;
|
||||||
String str = "not using an xbox live account";
|
int offset2 = this.mc.isChatOpen() ? 4 : 0;
|
||||||
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 2 + offset2, 0xFFDDDD);
|
String str = "not using an xbox live account";
|
||||||
str = "eaglercraft: " + ConfigConstants.version;
|
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 2 + offset2, 0xFFDDDD);
|
||||||
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 12 + offset2, 14737632);
|
str = "eaglercraft: " + ConfigConstants.version;
|
||||||
|
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 12 + offset2, 14737632);
|
||||||
|
}
|
||||||
|
|
||||||
EaglerAdapter.glPopMatrix();
|
EaglerAdapter.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
package net.minecraft.src;
|
package net.minecraft.src;
|
||||||
|
|
||||||
|
import net.lax1dude.eaglercraft.AbortedException;
|
||||||
|
import net.lax1dude.eaglercraft.ConfigConstants;
|
||||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||||
import net.lax1dude.eaglercraft.GuiScreenSkinCapeSettings;
|
import net.lax1dude.eaglercraft.GuiScreenSkinCapeSettings;
|
||||||
import net.lax1dude.eaglercraft.GuiScreenVoiceChannel;
|
import net.lax1dude.eaglercraft.GuiVoiceMenu;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
public class GuiIngameMenu extends GuiScreen {
|
public class GuiIngameMenu extends GuiScreen {
|
||||||
|
|
||||||
|
private GuiVoiceMenu voiceMenu;
|
||||||
|
|
||||||
|
public GuiIngameMenu() {
|
||||||
|
voiceMenu = new GuiVoiceMenu(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the buttons (and other controls) to the screen in question.
|
* Adds the buttons (and other controls) to the screen in question.
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +28,6 @@ public class GuiIngameMenu extends GuiScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.buttonList.add(new GuiButton(4, this.width / 2 - 100, this.height / 4 + 24 + var1, StatCollector.translateToLocal("menu.returnToGame")));
|
this.buttonList.add(new GuiButton(4, this.width / 2 - 100, this.height / 4 + 24 + var1, StatCollector.translateToLocal("menu.returnToGame")));
|
||||||
//this.buttonList.add(new GuiButton(5, this.width / 2 - 100, this.height / 4 + 48 + var1, StatCollector.translateToLocal("menu.voicechannel")));
|
|
||||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal("menu.options")));
|
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal("menu.options")));
|
||||||
GuiButton var3;
|
GuiButton var3;
|
||||||
this.buttonList.add(var3 = new GuiButton(7, this.width / 2 + 2, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal("menu.shareToLan")));
|
this.buttonList.add(var3 = new GuiButton(7, this.width / 2 + 2, this.height / 4 + 96 + var1, 98, 20, StatCollector.translateToLocal("menu.shareToLan")));
|
||||||
|
@ -54,10 +62,6 @@ public class GuiIngameMenu extends GuiScreen {
|
||||||
this.mc.sndManager.resumeAllSounds();
|
this.mc.sndManager.resumeAllSounds();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
|
||||||
this.mc.displayGuiScreen(new GuiScreenVoiceChannel(this));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 8:
|
case 8:
|
||||||
this.mc.displayGuiScreen(new GuiScreenSkinCapeSettings(this));
|
this.mc.displayGuiScreen(new GuiScreenSkinCapeSettings(this));
|
||||||
break;
|
break;
|
||||||
|
@ -69,6 +73,7 @@ public class GuiIngameMenu extends GuiScreen {
|
||||||
*/
|
*/
|
||||||
public void updateScreen() {
|
public void updateScreen() {
|
||||||
super.updateScreen();
|
super.updateScreen();
|
||||||
|
voiceMenu.updateScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,5 +93,55 @@ public class GuiIngameMenu extends GuiScreen {
|
||||||
this.drawString(fontRenderer, var1.translateKey("menu.skinCapeSettingsNote1"), 0, 9, c);
|
this.drawString(fontRenderer, var1.translateKey("menu.skinCapeSettingsNote1"), 0, 9, c);
|
||||||
EaglerAdapter.glPopMatrix();
|
EaglerAdapter.glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawString(fontRenderer, "Eaglercraft: " + ConfigConstants.version, 6, 27, 0x999999);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(voiceMenu.isBlockingInput()) {
|
||||||
|
super.drawScreen(0, 0, par3);
|
||||||
|
}else {
|
||||||
|
super.drawScreen(par1, par2, par3);
|
||||||
|
}
|
||||||
|
voiceMenu.drawScreen(par1, par2, par3);
|
||||||
|
}catch(AbortedException ex) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when a key is typed. This is the equivalent of
|
||||||
|
* KeyListener.keyTyped(KeyEvent e).
|
||||||
|
*/
|
||||||
|
protected void keyTyped(char par1, int par2) {
|
||||||
|
try {
|
||||||
|
voiceMenu.keyTyped(par1, par2);
|
||||||
|
super.keyTyped(par1, par2);
|
||||||
|
}catch(AbortedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the mouse is clicked.
|
||||||
|
*/
|
||||||
|
protected void mouseClicked(int par1, int par2, int par3) {
|
||||||
|
try {
|
||||||
|
voiceMenu.mouseClicked(par1, par2, par3);
|
||||||
|
super.mouseClicked(par1, par2, par3);
|
||||||
|
}catch(AbortedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWorldAndResolution(Minecraft par1Minecraft, int par2, int par3) {
|
||||||
|
super.setWorldAndResolution(par1Minecraft, par2, par3);
|
||||||
|
voiceMenu.setWorldAndResolution(par1Minecraft, par2, par3);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void mouseMovedOrUp(int par1, int par2, int par3) {
|
||||||
|
try {
|
||||||
|
voiceMenu.mouseMovedOrUp(par1, par2, par3);
|
||||||
|
super.mouseMovedOrUp(par1, par2, par3);
|
||||||
|
}catch(AbortedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class GuiVideoSettings extends GuiScreen {
|
||||||
int var4 = var3.getScaledWidth();
|
int var4 = var3.getScaledWidth();
|
||||||
int var5 = var3.getScaledHeight();
|
int var5 = var3.getScaledHeight();
|
||||||
this.setWorldAndResolution(this.mc, var4, var5);
|
this.setWorldAndResolution(this.mc, var4, var5);
|
||||||
|
this.mc.voiceOverlay.setResolution(var4, var5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.minecraft.src;
|
||||||
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.lax1dude.eaglercraft.TextureLocation;
|
import net.lax1dude.eaglercraft.TextureLocation;
|
||||||
|
import net.lax1dude.eaglercraft.Voice;
|
||||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||||
import net.lax1dude.eaglercraft.DefaultSkinRenderer;
|
import net.lax1dude.eaglercraft.DefaultSkinRenderer;
|
||||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||||
|
@ -431,6 +432,8 @@ public abstract class RenderLiving extends Render {
|
||||||
this.renderLivingLabel(par1EntityLiving, par8Str, par2, par4, par6, 64);
|
this.renderLivingLabel(par1EntityLiving, par8Str, par2, par4, par6, 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final TextureLocation voiceGuiIcons = new TextureLocation("/gui/voice.png");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the debug or playername text above a living
|
* Draws the debug or playername text above a living
|
||||||
|
@ -494,6 +497,86 @@ public abstract class RenderLiving extends Render {
|
||||||
EaglerAdapter.glEnable(EaglerAdapter.GL_LIGHTING);
|
EaglerAdapter.glEnable(EaglerAdapter.GL_LIGHTING);
|
||||||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||||
EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
|
||||||
|
if(par1EntityLiving instanceof EntityOtherPlayerMP) {
|
||||||
|
if(EaglerAdapter.getVoiceStatus() == Voice.VoiceStatus.CONNECTED) {
|
||||||
|
|
||||||
|
String nm = ((EntityOtherPlayerMP) par1EntityLiving).username;
|
||||||
|
boolean mute = EaglerAdapter.getVoiceMuted().contains(nm);
|
||||||
|
if(mute || EaglerAdapter.getVoiceSpeaking().contains(nm)) {
|
||||||
|
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_LIGHTING);
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_TEXTURE_2D);
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_ALPHA_TEST);
|
||||||
|
EaglerAdapter.glDepthMask(false);
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_DEPTH_TEST);
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_BLEND);
|
||||||
|
|
||||||
|
EaglerAdapter.glPushMatrix();
|
||||||
|
EaglerAdapter.glTranslatef(-8.0f, -18.0f, 0.0f);
|
||||||
|
|
||||||
|
EaglerAdapter.glScalef(16.0f, 16.0f, 16.0f);
|
||||||
|
|
||||||
|
var15.startDrawingQuads();
|
||||||
|
var15.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
|
||||||
|
var15.addVertex(-0.02, -0.02, 0.0);
|
||||||
|
var15.addVertex(-0.02, 1.02, 0.0);
|
||||||
|
var15.addVertex(1.02, 1.02, 0.0);
|
||||||
|
var15.addVertex(1.02, -0.02, 0.0);
|
||||||
|
var15.draw();
|
||||||
|
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_TEXTURE_2D);
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
||||||
|
EaglerAdapter.glAlphaFunc(EaglerAdapter.GL_GREATER, 0.02f);
|
||||||
|
|
||||||
|
voiceGuiIcons.bindTexture();
|
||||||
|
|
||||||
|
int u = 0;
|
||||||
|
int v = mute ? 160 : 128;
|
||||||
|
|
||||||
|
float var7 = 0.00390625F;
|
||||||
|
float var8 = 0.00390625F;
|
||||||
|
|
||||||
|
if(mute) {
|
||||||
|
EaglerAdapter.glColor4f(0.9F, 0.3F, 0.3F, 0.125F);
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 0.125F);
|
||||||
|
}
|
||||||
|
|
||||||
|
var15.startDrawingQuads();
|
||||||
|
var15.addVertexWithUV(0, 1.0, 0, (double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(1.0, 1.0, 0, (double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(1.0, 0, 0, (double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(0, 0, 0, (double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8));
|
||||||
|
var15.draw();
|
||||||
|
|
||||||
|
EaglerAdapter.glAlphaFunc(EaglerAdapter.GL_GREATER, 0.1f);
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_DEPTH_TEST);
|
||||||
|
EaglerAdapter.glDepthMask(true);
|
||||||
|
|
||||||
|
if(mute) {
|
||||||
|
EaglerAdapter.glColor4f(0.9F, 0.3F, 0.3F, 1.0F);
|
||||||
|
}else {
|
||||||
|
EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
var15.startDrawingQuads();
|
||||||
|
var15.addVertexWithUV(0, 1.0, 0, (double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(1.0, 1.0, 0, (double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(1.0, 0, 0, (double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8));
|
||||||
|
var15.addVertexWithUV(0, 0, 0, (double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8));
|
||||||
|
var15.draw();
|
||||||
|
|
||||||
|
EaglerAdapter.glEnable(EaglerAdapter.GL_LIGHTING);
|
||||||
|
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||||
|
EaglerAdapter.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
|
||||||
|
EaglerAdapter.glPopMatrix();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EaglerAdapter.glPopMatrix();
|
EaglerAdapter.glPopMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ public class Client {
|
||||||
public static HTMLElement rootElement = null;
|
public static HTMLElement rootElement = null;
|
||||||
public static Minecraft instance = null;
|
public static Minecraft instance = null;
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
registerErrorHandler();
|
|
||||||
//try {
|
//try {
|
||||||
String[] e = getOpts();
|
String[] e = getOpts();
|
||||||
try {
|
try {
|
||||||
|
@ -30,6 +29,7 @@ public class Client {
|
||||||
showCrashScreen(s.toString());
|
showCrashScreen(s.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
registerErrorHandler();
|
||||||
LocalStorageManager.loadStorage();
|
LocalStorageManager.loadStorage();
|
||||||
if(e.length > 2 && e[2].length() > 0) {
|
if(e.length > 2 && e[2].length() > 0) {
|
||||||
ServerList.loadDefaultServers(e[2]);
|
ServerList.loadDefaultServers(e[2]);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package net.lax1dude.eaglercraft.adapter;
|
package net.lax1dude.eaglercraft.adapter;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -8,12 +11,15 @@ import java.nio.IntBuffer;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.teavm.interop.Async;
|
import org.teavm.interop.Async;
|
||||||
|
@ -72,9 +78,11 @@ import net.lax1dude.eaglercraft.EaglerImage;
|
||||||
import net.lax1dude.eaglercraft.EarlyLoadScreen;
|
import net.lax1dude.eaglercraft.EarlyLoadScreen;
|
||||||
import net.lax1dude.eaglercraft.LocalStorageManager;
|
import net.lax1dude.eaglercraft.LocalStorageManager;
|
||||||
import net.lax1dude.eaglercraft.ServerQuery;
|
import net.lax1dude.eaglercraft.ServerQuery;
|
||||||
|
import net.lax1dude.eaglercraft.Voice;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray;
|
||||||
import net.minecraft.src.MathHelper;
|
import net.minecraft.src.MathHelper;
|
||||||
|
import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftVoiceClient;
|
||||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;
|
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;
|
||||||
import static net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext.*;
|
import static net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext.*;
|
||||||
|
|
||||||
|
@ -345,6 +353,8 @@ public class EaglerAdapterImpl2 {
|
||||||
|
|
||||||
EarlyLoadScreen.paintScreen();
|
EarlyLoadScreen.paintScreen();
|
||||||
|
|
||||||
|
voiceClient = startVoiceClient();
|
||||||
|
|
||||||
downloadAssetPack(assetPackageURI);
|
downloadAssetPack(assetPackageURI);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -385,6 +395,9 @@ public class EaglerAdapterImpl2 {
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JSBody(params = { }, script = "return window.startVoiceClient();")
|
||||||
|
private static native EaglercraftVoiceClient startVoiceClient();
|
||||||
|
|
||||||
public static final void destroyContext() {
|
public static final void destroyContext() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1546,7 +1559,7 @@ public class EaglerAdapterImpl2 {
|
||||||
return (p1 >= 0 && p1 < 256) ? LWJGLKeyNames[p1] : "null";
|
return (p1 >= 0 && p1 < 256) ? LWJGLKeyNames[p1] : "null";
|
||||||
}
|
}
|
||||||
public static final void setFullscreen(boolean p1) {
|
public static final void setFullscreen(boolean p1) {
|
||||||
win.alert("use F11 to enter fullscreen");
|
Window.alert("use F11 to enter fullscreen");
|
||||||
}
|
}
|
||||||
public static final boolean shouldShutdown() {
|
public static final boolean shouldShutdown() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1997,29 +2010,198 @@ public class EaglerAdapterImpl2 {
|
||||||
public static final void openConsole() {
|
public static final void openConsole() {
|
||||||
|
|
||||||
}
|
}
|
||||||
private static boolean connected = false;
|
|
||||||
public static final void voiceConnect(String channel) {
|
|
||||||
win.alert("voice channels are not implemented yet");
|
//TODO: voice start =======================================================================
|
||||||
connected = true;
|
|
||||||
|
// implementation notes - DO NOT access any net.minecraft.* classes from EaglerAdapterImpl2 this time
|
||||||
|
// implementation notes - Tick all the "for (Object playerObject : Minecraft.getMinecraft().theWorld.playerEntities)" in net.minecraft.client.Minecraft.runTick() or similar
|
||||||
|
|
||||||
|
// implementation notes - try to only connect to client in GLOBAL or LOCAL not both
|
||||||
|
// implementation notes - try to only connect to nearby clients, and disconnect once they've been out of range for more then 5-10 seconds
|
||||||
|
|
||||||
|
// implementation notes - AGAIN, don't access net.minecraft.* classes from this file
|
||||||
|
|
||||||
|
// to ayunami - this is initialized at startup, right before downloadAssetPack
|
||||||
|
private static EaglercraftVoiceClient voiceClient = null;
|
||||||
|
|
||||||
|
private static boolean voiceAvailableStat = false;
|
||||||
|
private static boolean voiceSignalHandlersInitialized = false;
|
||||||
|
|
||||||
|
// to ayunami - use this as a callback to send packets on the voice signal channel
|
||||||
|
private static Consumer<byte[]> returnSignalHandler = null;
|
||||||
|
|
||||||
|
// to ayunami - call this before joining a new server
|
||||||
|
public static void clearVoiceAvailableStatus() {
|
||||||
|
voiceAvailableStat = false;
|
||||||
}
|
}
|
||||||
public static final void voiceVolume(float volume) {
|
|
||||||
|
// to ayunami - use this to set returnSignalHandler when a new NetworkManager is created
|
||||||
|
public static void setVoiceSignalHandler(Consumer<byte[]> signalHandler) {
|
||||||
|
returnSignalHandler = signalHandler;
|
||||||
}
|
}
|
||||||
public static final boolean voiceActive() {
|
|
||||||
return connected;
|
public static final int VOICE_SIGNAL_ALLOWED_CLIENTBOUND = 0;
|
||||||
|
public static final int VOICE_SIGNAL_ICE_SERVERBOUND = 1;
|
||||||
|
public static final int VOICE_SIGNAL_DESC_SERVERBOUND = 2;
|
||||||
|
|
||||||
|
// to ayunami - use this to pass voice signal packets
|
||||||
|
public static void handleVoiceSignal(byte[] data) {
|
||||||
|
try {
|
||||||
|
DataInputStream streamIn = new DataInputStream(new ByteArrayInputStream(data));
|
||||||
|
int sig = streamIn.read();
|
||||||
|
switch(sig) {
|
||||||
|
case VOICE_SIGNAL_ALLOWED_CLIENTBOUND:
|
||||||
|
voiceAvailableStat = streamIn.readBoolean();
|
||||||
|
String[] servs = new String[streamIn.read()];
|
||||||
|
for(int i = 0; i < servs.length; ++i) {
|
||||||
|
servs[i] = streamIn.readUTF();
|
||||||
|
}
|
||||||
|
voiceClient.setICEServers(servs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.println("Unknown voice signal packet '" + sig + "'!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}catch(IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final boolean voiceAvailable() {
|
||||||
|
return voiceClient.voiceClientSupported() && voiceClient.getReadyState() != EaglercraftVoiceClient.READYSTATE_ABORTED;
|
||||||
|
}
|
||||||
|
public static final boolean voiceAllowed() {
|
||||||
|
return voiceAvailableStat;
|
||||||
}
|
}
|
||||||
public static final boolean voiceRelayed() {
|
public static final boolean voiceRelayed() {
|
||||||
return connected;
|
return false;
|
||||||
}
|
}
|
||||||
public static final String[] voiceUsers() {
|
private static Voice.VoiceChannel enabledChannel = Voice.VoiceChannel.NONE;
|
||||||
return new String[0];
|
|
||||||
|
// to ayunami - use this to switch channel modes or disable voice
|
||||||
|
public static final void enableVoice(Voice.VoiceChannel enable) {
|
||||||
|
enabledChannel = enable;
|
||||||
|
if(enable == Voice.VoiceChannel.NONE) {
|
||||||
|
talkStatus = false;
|
||||||
|
}else {
|
||||||
|
if(!voiceSignalHandlersInitialized) {
|
||||||
|
voiceSignalHandlersInitialized = true;
|
||||||
|
voiceClient.setICECandidateHandler(new EaglercraftVoiceClient.ICECandidateHandler() {
|
||||||
|
@Override
|
||||||
|
public void call(String peerId, String sdpMLineIndex, String candidate) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
DataOutputStream dat = new DataOutputStream(bos);
|
||||||
|
dat.write(VOICE_SIGNAL_ICE_SERVERBOUND);
|
||||||
|
dat.writeUTF(peerId);
|
||||||
|
dat.writeUTF(sdpMLineIndex);
|
||||||
|
dat.writeUTF(candidate);
|
||||||
|
returnSignalHandler.accept(bos.toByteArray());
|
||||||
|
}catch(IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
voiceClient.setDescriptionHandler(new EaglercraftVoiceClient.DescriptionHandler() {
|
||||||
|
@Override
|
||||||
|
public void call(String peerId, String candidate) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
DataOutputStream dat = new DataOutputStream(bos);
|
||||||
|
dat.write(VOICE_SIGNAL_DESC_SERVERBOUND);
|
||||||
|
dat.writeUTF(peerId);
|
||||||
|
dat.writeUTF(candidate);
|
||||||
|
returnSignalHandler.accept(bos.toByteArray());
|
||||||
|
}catch(IOException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
voiceClient.initializeDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public static final String[] voiceUsersTalking() {
|
public static final Voice.VoiceChannel getVoiceChannel() {
|
||||||
return new String[0];
|
return enabledChannel;
|
||||||
}
|
}
|
||||||
public static final void voiceEnd() {
|
public static final Voice.VoiceStatus getVoiceStatus() {
|
||||||
connected = false;
|
return (!voiceAvailable() || !voiceAllowed()) ? Voice.VoiceStatus.UNAVAILABLE :
|
||||||
|
(voiceClient.getReadyState() != EaglercraftVoiceClient.READYSTATE_DEVICE_INITIALIZED ?
|
||||||
|
Voice.VoiceStatus.CONNECTING : Voice.VoiceStatus.CONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to ayunami - push to talk in the JS works afaik
|
||||||
|
private static boolean talkStatus = false;
|
||||||
|
public static final void activateVoice(boolean talk) {
|
||||||
|
if(talkStatus != talk) {
|
||||||
|
voiceClient.activateVoice(talk);
|
||||||
|
}
|
||||||
|
talkStatus = talk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to ayunami - not currently used in the javascript but is used by GUI and gameSettings
|
||||||
|
private static int proximity = 16;
|
||||||
|
public static final void setVoiceProximity(int prox) {
|
||||||
|
proximity = prox;
|
||||||
|
}
|
||||||
|
public static final int getVoiceProximity() {
|
||||||
|
return proximity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to ayunami - iterate all AudioNodes from PeerTrackHandler players and adjust their gain here
|
||||||
|
private static float volumeListen = 0.5f;
|
||||||
|
public static final void setVoiceListenVolume(float f) {
|
||||||
|
volumeListen = f;
|
||||||
|
}
|
||||||
|
public static final float getVoiceListenVolume() {
|
||||||
|
return volumeListen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to ayunami - this is already implemented
|
||||||
|
private static float volumeSpeak = 0.5f;
|
||||||
|
public static final void setVoiceSpeakVolume(float f) {
|
||||||
|
if(volumeSpeak != f) {
|
||||||
|
voiceClient.setMicVolume(f);
|
||||||
|
}
|
||||||
|
volumeSpeak = f;
|
||||||
|
}
|
||||||
|
public static final float getVoiceSpeakVolume() {
|
||||||
|
return volumeSpeak;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to ayunami - this is used to make the ingame GUI display who is speaking
|
||||||
|
// I also already programmed a speaker icon above player name tags of players in "getVoiceSpeaking()"
|
||||||
|
|
||||||
|
private static final Set<String> mutedSet = new HashSet();
|
||||||
|
private static final Set<String> emptySet = new HashSet();
|
||||||
|
private static final List<String> emptyLst = new ArrayList();
|
||||||
|
public static final Set<String> getVoiceListening() {
|
||||||
|
return emptySet;
|
||||||
|
}
|
||||||
|
public static final Set<String> getVoiceSpeaking() {
|
||||||
|
return emptySet;
|
||||||
|
}
|
||||||
|
public static final void setVoiceMuted(String username, boolean mute) {
|
||||||
|
if(mute) {
|
||||||
|
mutedSet.add(username);
|
||||||
|
}else {
|
||||||
|
mutedSet.remove(username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static final Set<String> getVoiceMuted() {
|
||||||
|
return mutedSet;
|
||||||
|
}
|
||||||
|
public static final List<String> getVoiceRecent() {
|
||||||
|
return emptyLst;
|
||||||
|
}
|
||||||
|
|
||||||
|
// to ayunami - use this to clean up that ExpiringSet class you made
|
||||||
|
public static final void tickVoice() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: voice end ========================================================
|
||||||
|
|
||||||
|
|
||||||
public static final void doJavascriptCoroutines() {
|
public static final void doJavascriptCoroutines() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package net.lax1dude.eaglercraft.adapter.teavm;
|
||||||
|
|
||||||
|
import org.teavm.jso.JSFunctor;
|
||||||
|
import org.teavm.jso.JSObject;
|
||||||
|
import org.teavm.jso.webaudio.MediaStreamAudioSourceNode;
|
||||||
|
|
||||||
|
public interface EaglercraftVoiceClient extends JSObject {
|
||||||
|
|
||||||
|
int READYSTATE_NONE = 0;
|
||||||
|
int READYSTATE_ABORTED = -1;
|
||||||
|
int READYSTATE_DEVICE_INITIALIZED = 1;
|
||||||
|
|
||||||
|
int TASKSTATE_NONE = -1;
|
||||||
|
int TASKSTATE_LOADING = 0;
|
||||||
|
int TASKSTATE_COMPLETE = 1;
|
||||||
|
int TASKSTATE_FAILED = 2;
|
||||||
|
|
||||||
|
boolean voiceClientSupported();
|
||||||
|
|
||||||
|
void initializeDevices();
|
||||||
|
|
||||||
|
// to ayunami - allow the server to tell the client what to put here
|
||||||
|
void setICEServers(String[] urls);
|
||||||
|
|
||||||
|
// to ayunami - this is the equivalent of your "EAG|VoiceIce" callback
|
||||||
|
void setICECandidateHandler(ICECandidateHandler callback);
|
||||||
|
|
||||||
|
// to ayunami - this is the equivalent of your "EAG|VoiceDesc" callback
|
||||||
|
void setDescriptionHandler(DescriptionHandler callback);
|
||||||
|
|
||||||
|
// to ayunami - this returns a "MediaStreamAudioSourceNode" for new peers
|
||||||
|
void setPeerTrackHandler(PeerTrackHandler callback);
|
||||||
|
|
||||||
|
// to ayunami - this is called when a peer disconnects (so you can remove their MediaStreamAudioSourceNode and stuff)
|
||||||
|
void setPeerDisconnectHandler(PeerDisconnectHandler callback);
|
||||||
|
|
||||||
|
void activateVoice(boolean active);
|
||||||
|
|
||||||
|
void setMicVolume(float volume);
|
||||||
|
|
||||||
|
int getTaskState();
|
||||||
|
|
||||||
|
int getReadyState();
|
||||||
|
|
||||||
|
int signalConnect(String peerId);
|
||||||
|
|
||||||
|
int signalDescription(String peerId, String description);
|
||||||
|
|
||||||
|
int signalDisconnect(String peerId);
|
||||||
|
|
||||||
|
int signalICECandidate(String peerId, String candidate);
|
||||||
|
|
||||||
|
@JSFunctor
|
||||||
|
public static interface ICECandidateHandler extends JSObject {
|
||||||
|
void call(String peerId, String sdpMLineIndex, String candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSFunctor
|
||||||
|
public static interface DescriptionHandler extends JSObject {
|
||||||
|
void call(String peerId, String candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSFunctor
|
||||||
|
public static interface PeerTrackHandler extends JSObject {
|
||||||
|
void call(String peerId, MediaStreamAudioSourceNode candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JSFunctor
|
||||||
|
public static interface PeerDisconnectHandler extends JSObject {
|
||||||
|
void call(String peerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue