save broken for future
This commit is contained in:
parent
00821ed2ae
commit
1637fc2998
|
@ -19,7 +19,7 @@ public class ServerIcon {
|
|||
Graphics2D g = (Graphics2D) icon.getGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, (awtIcon.getWidth() < 64 || awtIcon.getHeight() < 64) ?
|
||||
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);
|
||||
int ow = awtIcon.getWidth();
|
||||
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>
|
||||
<title>eagler</title>
|
||||
<script type="text/javascript" src="classes.js"></script>
|
||||
<script type="text/javascript" src="eagswebrtc.js"></script>
|
||||
<script type="text/javascript">
|
||||
if(document.location.href.startsWith("file:")) {
|
||||
alert("You're not supposed to 'open' this file in your browser. Please upload this folder to your HTTP(s) server and access it via the internet. This is not a bug, please read the documentation");
|
||||
|
|
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
|
||||
|
||||
voice.title=Voice Channel
|
||||
voice.addr=Channel Address
|
||||
voice.connect=Connect
|
||||
voice.disconnect=Disconnect
|
||||
voice.volume=Channel Volume
|
||||
voice.titleNoVoice=Voice is disabled on this server
|
||||
voice.titleVoiceUnavailable=Voice is unavailable
|
||||
voice.titleVoiceBrowserError=(fix your browser)
|
||||
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.warning2=connection procedure, a TURN relay will be used as
|
||||
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() {
|
||||
EaglerAdapter.setVoiceStatus(Voice.VoiceStatus.DISCONNECTED);
|
||||
if(EaglerAdapter.connectionOpen()) {
|
||||
EaglerAdapter.endConnection();
|
||||
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
||||
|
@ -132,6 +133,7 @@ public class WebsocketNetworkManager implements INetworkManager {
|
|||
}
|
||||
|
||||
public void closeConnections() {
|
||||
EaglerAdapter.setVoiceStatus(Voice.VoiceStatus.DISCONNECTED);
|
||||
if(EaglerAdapter.connectionOpen()) {
|
||||
EaglerAdapter.endConnection();
|
||||
EaglerAdapter.setDebugVar("minecraftServer", "null");
|
||||
|
|
|
@ -11,7 +11,7 @@ import net.lax1dude.eaglercraft.EaglerProfile;
|
|||
|
||||
import net.lax1dude.eaglercraft.GuiScreenEditProfile;
|
||||
import net.lax1dude.eaglercraft.GuiScreenLicense;
|
||||
import net.lax1dude.eaglercraft.GuiScreenVoiceChannel;
|
||||
import net.lax1dude.eaglercraft.GuiVoiceOverlay;
|
||||
import net.lax1dude.eaglercraft.LocalStorageManager;
|
||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
||||
|
@ -166,6 +166,8 @@ public class Minecraft implements Runnable {
|
|||
/** Profiler currently displayed in the debug screen pie chart */
|
||||
private String debugProfilerName = "root";
|
||||
|
||||
public GuiVoiceOverlay voiceOverlay;
|
||||
|
||||
public Minecraft() {
|
||||
this.tempDisplayHeight = 480;
|
||||
this.fullscreen = false;
|
||||
|
@ -240,6 +242,7 @@ public class Minecraft implements Runnable {
|
|||
this.checkGLError("Post startup");
|
||||
this.guiAchievement = new GuiAchievement(this);
|
||||
this.ingameGUI = new GuiIngame(this);
|
||||
this.voiceOverlay = new GuiVoiceOverlay(this);
|
||||
|
||||
//if (this.serverName != null) {
|
||||
// this.displayGuiScreen(new GuiConnecting(new GuiMainMenu(), this, this.serverName, this.serverPort));
|
||||
|
@ -443,7 +446,6 @@ public class Minecraft implements Runnable {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GuiScreenVoiceChannel.fadeInTimer = System.currentTimeMillis();
|
||||
EaglerAdapter.glDisable(EaglerAdapter.GL_BLEND);
|
||||
EaglerAdapter.glEnable(EaglerAdapter.GL_ALPHA_TEST);
|
||||
EaglerAdapter.glAlphaFunc(EaglerAdapter.GL_GREATER, 0.1F);
|
||||
|
@ -1039,12 +1041,15 @@ public class Minecraft implements Runnable {
|
|||
this.displayWidth = par1 <= 0 ? 1 : par1;
|
||||
this.displayHeight = par2 <= 0 ? 1 : par2;
|
||||
|
||||
if (this.currentScreen != null) {
|
||||
ScaledResolution var3 = new ScaledResolution(this.gameSettings, par1, par2);
|
||||
int var4 = var3.getScaledWidth();
|
||||
int var5 = var3.getScaledHeight();
|
||||
|
||||
if (this.currentScreen != null) {
|
||||
this.currentScreen.setWorldAndResolution(this, var4, var5);
|
||||
}
|
||||
|
||||
this.voiceOverlay.setResolution(var4, var5);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1104,7 +1109,7 @@ public class Minecraft implements Runnable {
|
|||
}
|
||||
|
||||
GuiMultiplayer.tickRefreshCooldown();
|
||||
GuiScreenVoiceChannel.tickVoiceConnection();
|
||||
EaglerAdapter.tickVoice();
|
||||
|
||||
if (this.currentScreen == null || this.currentScreen.allowUserInput) {
|
||||
this.mcProfiler.endStartSection("mouse");
|
||||
|
|
|
@ -7,7 +7,6 @@ import net.minecraft.client.Minecraft;
|
|||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
import net.lax1dude.eaglercraft.EaglerImage;
|
||||
import net.lax1dude.eaglercraft.EaglercraftRandom;
|
||||
import net.lax1dude.eaglercraft.GuiScreenVoiceChannel;
|
||||
import net.lax1dude.eaglercraft.TextureLocation;
|
||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||
import net.lax1dude.eaglercraft.glemu.EffectPipeline;
|
||||
|
@ -876,7 +875,7 @@ public class EntityRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
GuiScreenVoiceChannel.drawOverlay();
|
||||
mc.voiceOverlay.drawOverlay();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,6 +137,11 @@ public class GameSettings {
|
|||
|
||||
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) {
|
||||
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 };
|
||||
|
@ -526,6 +531,17 @@ public class GameSettings {
|
|||
if(yee.hasKey("allowFNAWSkins")) allowFNAWSkins = yee.getBoolean("allowFNAWSkins");
|
||||
if(yee.hasKey("showOtherCapes")) showOtherCapes = yee.getBoolean("showOtherCapes");
|
||||
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) {
|
||||
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("showOtherCapes", showOtherCapes);
|
||||
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) {
|
||||
yee.setInteger(keyBindings[var4].keyDescription, keyBindings[var4].keyCode);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
if(mc.currentScreen == null || !(mc.currentScreen instanceof GuiIngameMenu)) {
|
||||
int offset = this.mc.isChatOpen() ? 135 : 0;
|
||||
int offset2 = this.mc.isChatOpen() ? 4 : 0;
|
||||
String str = "not using an xbox live account";
|
||||
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 2 + offset2, 0xFFDDDD);
|
||||
str = "eaglercraft: " + ConfigConstants.version;
|
||||
var8.drawStringWithShadow(str, (var6 * 4 / 3) - 2 - var8.getStringWidth(str) - offset, 12 + offset2, 14737632);
|
||||
}
|
||||
|
||||
EaglerAdapter.glPopMatrix();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
package net.minecraft.src;
|
||||
|
||||
import net.lax1dude.eaglercraft.AbortedException;
|
||||
import net.lax1dude.eaglercraft.ConfigConstants;
|
||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
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 {
|
||||
|
||||
private GuiVoiceMenu voiceMenu;
|
||||
|
||||
public GuiIngameMenu() {
|
||||
voiceMenu = new GuiVoiceMenu(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(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")));
|
||||
GuiButton var3;
|
||||
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();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
this.mc.displayGuiScreen(new GuiScreenVoiceChannel(this));
|
||||
break;
|
||||
|
||||
case 8:
|
||||
this.mc.displayGuiScreen(new GuiScreenSkinCapeSettings(this));
|
||||
break;
|
||||
|
@ -69,6 +73,7 @@ public class GuiIngameMenu extends GuiScreen {
|
|||
*/
|
||||
public void updateScreen() {
|
||||
super.updateScreen();
|
||||
voiceMenu.updateScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,5 +93,55 @@ public class GuiIngameMenu extends GuiScreen {
|
|||
this.drawString(fontRenderer, var1.translateKey("menu.skinCapeSettingsNote1"), 0, 9, c);
|
||||
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 var5 = var3.getScaledHeight();
|
||||
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.lax1dude.eaglercraft.TextureLocation;
|
||||
import net.lax1dude.eaglercraft.Voice;
|
||||
import net.lax1dude.eaglercraft.adapter.Tessellator;
|
||||
import net.lax1dude.eaglercraft.DefaultSkinRenderer;
|
||||
import net.lax1dude.eaglercraft.EaglerAdapter;
|
||||
|
@ -432,6 +433,8 @@ public abstract class RenderLiving extends Render {
|
|||
}
|
||||
}
|
||||
|
||||
private static final TextureLocation voiceGuiIcons = new TextureLocation("/gui/voice.png");
|
||||
|
||||
/**
|
||||
* 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.glDisable(EaglerAdapter.GL_BLEND);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ public class Client {
|
|||
public static HTMLElement rootElement = null;
|
||||
public static Minecraft instance = null;
|
||||
public static void main(String[] args) {
|
||||
registerErrorHandler();
|
||||
//try {
|
||||
String[] e = getOpts();
|
||||
try {
|
||||
|
@ -30,6 +29,7 @@ public class Client {
|
|||
showCrashScreen(s.toString());
|
||||
return;
|
||||
}
|
||||
registerErrorHandler();
|
||||
LocalStorageManager.loadStorage();
|
||||
if(e.length > 2 && e[2].length() > 0) {
|
||||
ServerList.loadDefaultServers(e[2]);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package net.lax1dude.eaglercraft.adapter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -8,12 +11,15 @@ import java.nio.IntBuffer;
|
|||
import java.nio.charset.Charset;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.teavm.interop.Async;
|
||||
|
@ -72,9 +78,11 @@ import net.lax1dude.eaglercraft.EaglerImage;
|
|||
import net.lax1dude.eaglercraft.EarlyLoadScreen;
|
||||
import net.lax1dude.eaglercraft.LocalStorageManager;
|
||||
import net.lax1dude.eaglercraft.ServerQuery;
|
||||
import net.lax1dude.eaglercraft.Voice;
|
||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLQuery;
|
||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGLVertexArray;
|
||||
import net.minecraft.src.MathHelper;
|
||||
import net.lax1dude.eaglercraft.adapter.teavm.EaglercraftVoiceClient;
|
||||
import net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext;
|
||||
import static net.lax1dude.eaglercraft.adapter.teavm.WebGL2RenderingContext.*;
|
||||
|
||||
|
@ -345,6 +353,8 @@ public class EaglerAdapterImpl2 {
|
|||
|
||||
EarlyLoadScreen.paintScreen();
|
||||
|
||||
voiceClient = startVoiceClient();
|
||||
|
||||
downloadAssetPack(assetPackageURI);
|
||||
|
||||
try {
|
||||
|
@ -385,6 +395,9 @@ public class EaglerAdapterImpl2 {
|
|||
}, 5000);
|
||||
}
|
||||
|
||||
@JSBody(params = { }, script = "return window.startVoiceClient();")
|
||||
private static native EaglercraftVoiceClient startVoiceClient();
|
||||
|
||||
public static final void destroyContext() {
|
||||
|
||||
}
|
||||
|
@ -1546,7 +1559,7 @@ public class EaglerAdapterImpl2 {
|
|||
return (p1 >= 0 && p1 < 256) ? LWJGLKeyNames[p1] : "null";
|
||||
}
|
||||
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() {
|
||||
return false;
|
||||
|
@ -1997,29 +2010,198 @@ public class EaglerAdapterImpl2 {
|
|||
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");
|
||||
connected = true;
|
||||
}
|
||||
public static final void voiceVolume(float volume) {
|
||||
|
||||
|
||||
//TODO: voice start =======================================================================
|
||||
|
||||
// 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 boolean voiceActive() {
|
||||
return connected;
|
||||
|
||||
// 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 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() {
|
||||
return connected;
|
||||
return false;
|
||||
}
|
||||
public static final String[] voiceUsers() {
|
||||
return new String[0];
|
||||
private static Voice.VoiceChannel enabledChannel = Voice.VoiceChannel.NONE;
|
||||
|
||||
// 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) {
|
||||
}
|
||||
public static final String[] voiceUsersTalking() {
|
||||
return new String[0];
|
||||
}
|
||||
public static final void voiceEnd() {
|
||||
connected = false;
|
||||
});
|
||||
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 Voice.VoiceChannel getVoiceChannel() {
|
||||
return enabledChannel;
|
||||
}
|
||||
public static final Voice.VoiceStatus getVoiceStatus() {
|
||||
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() {
|
||||
|
||||
}
|
||||
|
|
|
@ -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 New Issue
Block a user