Whisper support

This commit is contained in:
Manevolent
2018-08-17 16:27:18 -04:00
parent 0cd72622a2
commit da3495c297
7 changed files with 269 additions and 26 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ out/
.userlibraries
# Maven
target/
targetId/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
+1 -1
View File
@@ -10,7 +10,7 @@
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.targetId>1.8</maven.compiler.targetId>
</properties>
<dependencies>
@@ -0,0 +1,30 @@
package com.github.manevolent.ts3j.enums;
public enum GroupWhisperTarget {
ALL_CHANNELS(0),
CURRENT_CHANNEL(1),
PARENT_CHANNEL(2),
ALL_PARENT_CHANNEL(3),
CHANNEL_FAMILY(4),
COMPLETE_CHANNEL_FAMILY(5),
SUBCHANNELS(6)
;
private final int index;
GroupWhisperTarget(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
public static GroupWhisperTarget fromId(int index) {
for (GroupWhisperTarget value : values())
if (value.getIndex() == index) return value;
throw new IllegalArgumentException("invalid index: " + index);
}
}
@@ -0,0 +1,27 @@
package com.github.manevolent.ts3j.enums;
public enum GroupWhisperType {
SERVER_GROUP(0),
CHANNEL_GROUP(1),
CHANNEL_COMMANDER(2),
ALL_CLIENTS(3)
;
private final int index;
GroupWhisperType(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
public static GroupWhisperType fromId(int index) {
for (GroupWhisperType value : values())
if (value.getIndex() == index) return value;
throw new IllegalArgumentException("invalid index: " + index);
}
}
@@ -1,63 +1,63 @@
package com.github.manevolent.ts3j.protocol.packet;
import com.github.manevolent.ts3j.enums.CodecType;
import com.github.manevolent.ts3j.enums.GroupWhisperTarget;
import com.github.manevolent.ts3j.enums.GroupWhisperType;
import com.github.manevolent.ts3j.protocol.ProtocolRole;
import com.github.manevolent.ts3j.protocol.header.HeaderFlag;
import com.github.manevolent.ts3j.protocol.header.PacketHeader;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class PacketBody1VoiceWhisper extends PacketBody {
private int packetId;
private int clientId;
private CodecType codecType;
private WhisperTarget target;
private byte[] codecData;
public PacketBody1VoiceWhisper(ProtocolRole role) {
super(PacketBodyType.VOICE_WHISPER, role);
}
@Override
public void setHeaderValues(PacketHeader header) {
if (target instanceof WhisperTargetGroup)
header.setPacketFlag(HeaderFlag.NEW_PROTOCOL, true);
else
header.setPacketFlag(HeaderFlag.NEW_PROTOCOL, false);
}
@Override
public void read(PacketHeader header, ByteBuffer buffer) {
packetId = buffer.getShort() & 0x0000FFFF;
packetId = buffer.getShort() & 0xFFFF;
if (getRole() == ProtocolRole.SERVER)
clientId = buffer.getShort() & 0x0000FFFF;
clientId = buffer.getShort() & 0xFFFF;
codecType = CodecType.fromId((int) (buffer.get() & 0xFF));
if (getRole() == ProtocolRole.CLIENT) {
if (header.getPacketFlag(HeaderFlag.NEW_PROTOCOL)) {
int groupWhisperType = buffer.get() & 0xFF;
int groupWhisperTarget = buffer.get() & 0xFF;
long targetChannelIdorGroupId = buffer.getLong();
// TODO
setTarget(new WhisperTargetGroup());
} else {
int channelIdCount = buffer.get() & 0xFF;
int clientIdCount = buffer.get() & 0xFF;
List<Long> channelIds = new ArrayList<>(channelIdCount);
for (int i = 0; i < channelIdCount; i ++) channelIds.add(buffer.getLong());
List<Integer> clientIds = new ArrayList<>(clientIdCount);
for (int i = 0; i < clientIdCount; i ++) clientIds.add(buffer.getShort() & 0xFFFF);
// TODO
setTarget(new WhisperTargetMultiple());
}
} else {
setTarget(new WhisperTargetServerToClient());
}
codecData = new byte[buffer.remaining()];
target.read(buffer);
buffer.get(codecData);
read(buffer);
}
// We implemented the above so this is unneccessary.
@Override
public void read(ByteBuffer buffer) {
throw new UnsupportedOperationException();
codecData = new byte[buffer.remaining()];
buffer.get(codecData);
}
@Override
@@ -69,6 +69,9 @@ public class PacketBody1VoiceWhisper extends PacketBody {
buffer.put((byte)(codecType.getIndex() & 0xFF));
if (getRole() == ProtocolRole.CLIENT)
target.write(buffer);
buffer.put(codecData);
}
@@ -76,8 +79,7 @@ public class PacketBody1VoiceWhisper extends PacketBody {
public int getSize() {
switch (getRole()) {
case CLIENT:
// TODO
throw new UnsupportedOperationException();
return 2 + 1 + target.getSize() + codecData.length;
case SERVER:
return 2 + 2 + 1 + codecData.length;
default:
@@ -119,4 +121,173 @@ public class PacketBody1VoiceWhisper extends PacketBody {
this.clientId = clientId;
}
public WhisperTarget getTarget() {
return target;
}
public void setTarget(WhisperTarget target) {
this.target = target;
}
public static abstract class WhisperTarget {
public abstract void write(ByteBuffer buffer);
public abstract void read(ByteBuffer buffer);
public abstract int getSize();
}
public static class WhisperTargetServerToClient extends WhisperTarget {
@Override
public void write(ByteBuffer buffer) {
// Do nothing
}
@Override
public void read(ByteBuffer buffer) {
// Do nothing
}
@Override
public int getSize() {
return 0; // Empty
}
}
public static class WhisperTargetMultiple extends WhisperTarget {
private int[] channelIds;
private int[] clientIds;
public int[] getChannelIds() {
return channelIds;
}
public void setChannelIds(int[] channelIds) {
this.channelIds = channelIds;
}
public int[] getClientIds() {
return clientIds;
}
public void setClientIds(int[] clientIds) {
this.clientIds = clientIds;
}
@Override
public void write(ByteBuffer buffer) {
if (channelIds != null)
buffer.put((byte) (channelIds.length & 0xFF));
else
buffer.put((byte) 0x00);
if (clientIds != null)
buffer.put((byte) (clientIds.length & 0xFF));
else
buffer.put((byte) 0x00);
if (channelIds != null) {
for (int channelId : channelIds) {
buffer.putLong((long) channelId);
}
}
if (clientIds != null) {
for (int clientId : clientIds) {
buffer.putShort((short) (clientId & 0xFFFF));
}
}
}
@Override
public void read(ByteBuffer buffer) {
int channelIdCount = buffer.get() & 0xFF;
int clientIdCount = buffer.get() & 0xFF;
channelIds = new int[channelIdCount];
for (int n = 0; n < channelIdCount; n ++)
channelIds[n] = (int) (buffer.getLong());
clientIds = new int[clientIdCount];
for (int n = 0; n < channelIdCount; n ++)
clientIds[n] = (buffer.getShort() & 0xFFFF);
}
@Override
public int getSize() {
return 2 + 2 +
(channelIds == null ? 0 : channelIds.length * 8) +
(clientIds == null ? 0 : clientIds.length * 2);
}
}
public static class WhisperTargetGroup extends WhisperTarget {
private GroupWhisperType whisperType;
private GroupWhisperTarget whisperTarget;
private long targetId;
@Override
public void write(ByteBuffer buffer) {
buffer.put((byte) (whisperType.getIndex() & 0xFF));
buffer.put((byte) (whisperTarget.getIndex() & 0xFF));
buffer.putLong(targetId);
}
@Override
public void read(ByteBuffer buffer) {
whisperType = GroupWhisperType.fromId(buffer.get() & 0xFF);
whisperTarget = GroupWhisperTarget.fromId(buffer.get() & 0xFF);
targetId = buffer.getLong();
}
@Override
public int getSize() {
return 1 + 1 + 8;
}
public GroupWhisperType getWhisperType() {
return whisperType;
}
public void setWhisperType(GroupWhisperType whisperType) {
this.whisperType = whisperType;
}
public GroupWhisperTarget getWhisperTarget() {
return whisperTarget;
}
public void setWhisperTarget(GroupWhisperTarget whisperTarget) {
this.whisperTarget = whisperTarget;
}
public long getTargetId() {
return targetId;
}
public void setTargetId(long targetId) {
this.targetId = targetId;
}
}
public static WhisperTarget createChannel(int channelId) {
WhisperTargetMultiple multiple = new WhisperTargetMultiple();
multiple.setChannelIds(new int[] { channelId });
return multiple;
}
public static WhisperTarget createClient(int clientId) {
WhisperTargetMultiple multiple = new WhisperTargetMultiple();
multiple.setClientIds(new int[] { clientId });
return multiple;
}
public static WhisperTarget createServer() {
WhisperTargetGroup group = new WhisperTargetGroup();
group.setWhisperTarget(GroupWhisperTarget.ALL_CHANNELS);
group.setWhisperType(GroupWhisperType.ALL_CLIENTS);
return group;
}
}
@@ -5,6 +5,7 @@ import com.github.manevolent.ts3j.command.CommandProcessor;
import com.github.manevolent.ts3j.command.MultiCommand;
import com.github.manevolent.ts3j.protocol.Packet;
import com.github.manevolent.ts3j.protocol.packet.PacketBody0Voice;
import com.github.manevolent.ts3j.protocol.packet.PacketBody1VoiceWhisper;
import com.github.manevolent.ts3j.protocol.packet.PacketBody2Command;
import com.github.manevolent.ts3j.protocol.packet.PacketBody3CommandLow;
import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket;
@@ -57,6 +58,10 @@ public abstract class LocalClientHandlerFull extends LocalClientHandler {
Consumer<PacketBody0Voice> handler = getClient().getVoiceHandler();
if (handler != null) handler.accept((PacketBody0Voice) packet.getBody());
break;
case VOICE_WHISPER:
Consumer<PacketBody1VoiceWhisper> whisperConsumer = getClient().getWhisperHandler();
if (whisperConsumer != null) whisperConsumer.accept((PacketBody1VoiceWhisper) packet.getBody());
break;
}
}
}
@@ -70,6 +70,8 @@ public abstract class AbstractTeamspeakClientSocket
private CommandProcessor commandProcessor;
private Consumer<PacketBody0Voice> voiceHandler;
private Consumer<PacketBody1VoiceWhisper> whisperHandler;
private Consumer<Throwable> exceptionHandler = Throwable::printStackTrace;
private Identity identity = null;
@@ -886,6 +888,14 @@ public abstract class AbstractTeamspeakClientSocket
this.voiceHandler = voiceHandler;
}
public Consumer<PacketBody1VoiceWhisper> getWhisperHandler() {
return whisperHandler;
}
public void setWhisperHandler(Consumer<PacketBody1VoiceWhisper> whisperHandler) {
this.whisperHandler = whisperHandler;
}
private class NetworkHandler implements Runnable {
@Override
public void run() {