use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.
the class InteractiveChatVelocity method handleChat.
private void handleChat(PlayerChatEvent event) {
if (!event.getResult().isAllowed()) {
return;
}
try {
Field messageField = event.getClass().getDeclaredField("message");
messageField.setAccessible(true);
messageField.set(event, Registry.ID_PATTERN.matcher(event.getMessage()).replaceAll(""));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
String message = event.getMessage();
if (!player.getCurrentServer().isPresent()) {
return;
}
String newMessage = event.getMessage();
boolean hasInteractiveChat = false;
BackendInteractiveChatData data = serverInteractiveChatInfo.get(player.getCurrentServer().get().getServerInfo().getName());
if (data != null) {
hasInteractiveChat = data.hasInteractiveChat();
}
boolean usage = false;
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
if (icplaceholder.getKeyword().matcher(message).find()) {
usage = true;
break outer;
}
}
}
if (newMessage.startsWith("/")) {
if (usage && hasInteractiveChat) {
for (String parsecommand : InteractiveChatVelocity.parseCommands) {
if (newMessage.matches(parsecommand)) {
String command = newMessage.trim();
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
Pattern placeholder = icplaceholder.getKeyword();
Matcher matcher = placeholder.matcher(command);
if (matcher.find()) {
String uuidmatch = "<cmd=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(command.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
command = command.substring(0, matcher.start()) + uuidmatch + command.substring(matcher.end());
if (command.length() > 256) {
command = command.substring(0, 256);
}
event.setResult(ChatResult.message(command));
break outer;
}
}
}
break;
}
}
}
} else {
if (usage && InteractiveChatVelocity.useAccurateSenderFinder && hasInteractiveChat) {
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
Pattern placeholder = icplaceholder.getKeyword();
Matcher matcher = placeholder.matcher(message);
if (matcher.find()) {
String uuidmatch = "<chat=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(message.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
message = message.substring(0, matcher.start()) + uuidmatch + message.substring(matcher.end());
if (message.length() > 256) {
message = message.substring(0, 256);
}
event.setResult(ChatResult.message(message));
break outer;
}
}
}
}
try {
Field messageField = event.getClass().getDeclaredField("message");
messageField.setAccessible(true);
messageField.set(event, message);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
proxyServer.getScheduler().buildTask(plugin, () -> {
Map<String, Long> messages = forwardedMessages.get(uuid);
if (messages != null && messages.remove(newMessage) != null) {
try {
PluginMessageSendingVelocity.sendMessagePair(uuid, newMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}).delay(100, TimeUnit.MILLISECONDS).schedule();
}
}
use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.
the class PluginMessageSendingVelocity method sendPlayerListData.
public static void sendPlayerListData() throws IOException {
ByteArrayDataOutput output = ByteStreams.newDataOutput();
Collection<Player> players = getServer().getAllPlayers();
List<PlayerListPlayerData> dataList = new ArrayList<>();
for (Player player : players) {
if (player.getCurrentServer().isPresent()) {
String server = player.getCurrentServer().get().getServer().getServerInfo().getName();
BackendInteractiveChatData info = InteractiveChatVelocity.serverInteractiveChatInfo.get(server);
if (info != null && info.hasInteractiveChat()) {
dataList.add(new PlayerListPlayerData(server, player.getUniqueId(), player.getUsername()));
}
}
}
output.writeInt(dataList.size());
for (PlayerListPlayerData data : dataList) {
DataTypeIO.writeString(output, data.getServer(), StandardCharsets.UTF_8);
DataTypeIO.writeUUID(output, data.getUniqueId());
DataTypeIO.writeString(output, data.getName(), StandardCharsets.UTF_8);
}
int packetNumber = InteractiveChatVelocity.random.nextInt();
int packetId = 0x00;
byte[] data = output.toByteArray();
byte[][] dataArray = CustomArrayUtils.divideArray(data, 32700);
for (int i = 0; i < dataArray.length; i++) {
byte[] chunk = dataArray[i];
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.writeInt(packetNumber);
out.writeShort(packetId);
out.writeBoolean(i == (dataArray.length - 1));
out.write(chunk);
for (RegisteredServer server : getServer().getAllServers()) {
if (!server.getPlayersConnected().isEmpty()) {
server.sendPluginMessage(ICChannelIdentifier.INSTANCE, out.toByteArray());
InteractiveChatVelocity.pluginMessagesCounter.incrementAndGet();
}
}
}
}
use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.
the class ServerPingVelocity method getPing.
@SuppressWarnings("deprecation")
public static CompletableFuture<ServerPingVelocity> getPing(ServerInfo server) {
CompletableFuture<ServerPingVelocity> future = new CompletableFuture<>();
new Thread(() -> {
try (Socket socket = new Socket()) {
InetSocketAddress address = server.getAddress();
socket.connect(new InetSocketAddress(address.getHostName(), address.getPort()), 1500);
if (socket.isConnected()) {
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream out = new DataOutputStream(buffer);
out.writeByte(0x00);
DataStreamIO.writeVarInt(out, -1);
DataStreamIO.writeString(out, Registry.PLUGIN_MESSAGING_PROTOCOL_IDENTIFIER, StandardCharsets.UTF_8);
out.writeShort(25566);
DataStreamIO.writeVarInt(out, 1);
byte[] handshake = buffer.toByteArray();
DataStreamIO.writeVarInt(output, handshake.length);
output.write(handshake);
buffer = new ByteArrayOutputStream();
out = new DataOutputStream(buffer);
out.writeByte(0x00);
byte[] request = buffer.toByteArray();
DataStreamIO.writeVarInt(output, request.length);
output.write(request);
DataStreamIO.readVarInt(input);
int packetId = DataStreamIO.readVarInt(input);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x00) {
// we want a status response
throw new IOException("Invalid packetID " + Integer.toHexString(packetId));
}
// length of json string
int length = DataStreamIO.readVarInt(input);
if (length == -1) {
throw new IOException("Premature end of stream.");
}
if (length == 0) {
throw new IOException("Invalid string length.");
}
byte[] in = new byte[length];
input.readFully(in);
String jsonStr = new String(in);
boolean present;
String version;
MCVersion minecraftVersion;
String exactMinecraftVersion;
int protocol;
try {
JSONObject json = (JSONObject) new JSONParser().parse(jsonStr);
Object descriptionObj = json.get("description");
JSONObject data;
if (descriptionObj instanceof JSONObject) {
JSONObject description = (JSONObject) json.get("description");
String descriptionAsStr = PlainTextComponentSerializer.plainText().serialize(InteractiveChatComponentSerializer.gson().deserialize(description.toJSONString()));
data = (JSONObject) new JSONParser().parse(descriptionAsStr);
} else {
data = (JSONObject) new JSONParser().parse(StringEscapeUtils.unescapeJava(descriptionObj.toString()));
}
present = (boolean) data.get("present");
version = (String) data.get("version");
minecraftVersion = MCVersion.fromNumber((int) (long) data.get("minecraftVersion"));
exactMinecraftVersion = (String) data.get("exactMinecraftVersion");
protocol = data.containsKey("protocol") ? (int) (long) data.get("protocol") : 0;
} catch (Exception e) {
present = false;
version = UNKNOWN_VERSION;
minecraftVersion = MCVersion.UNSUPPORTED;
exactMinecraftVersion = UNKNOWN_VERSION;
protocol = UNKNOWN_PROTOCOL;
}
long start = System.currentTimeMillis();
buffer = new ByteArrayOutputStream();
out = new DataOutputStream(buffer);
out.writeByte(0x01);
out.writeLong(start);
byte[] ping = buffer.toByteArray();
DataStreamIO.writeVarInt(output, ping.length);
output.write(ping);
DataStreamIO.readVarInt(input);
packetId = DataStreamIO.readVarInt(input);
int pong = (int) (System.currentTimeMillis() - start);
if (packetId == -1) {
throw new IOException("Premature end of stream.");
}
if (packetId != 0x01) {
// we want a pong
throw new IOException("Invalid packetID " + Integer.toHexString(packetId));
}
future.complete(new ServerPingVelocity(pong, present));
BackendInteractiveChatData data = InteractiveChatVelocity.serverInteractiveChatInfo.get(server.getName());
if (data == null) {
InteractiveChatVelocity.serverInteractiveChatInfo.put(server.getName(), new BackendInteractiveChatData(server.getName(), true, present, version, minecraftVersion, exactMinecraftVersion, pong, protocol));
} else {
data.setPing(pong);
if (!data.isOnline()) {
data.setOnline(true);
}
if (data.hasInteractiveChat() != present) {
data.setInteractiveChat(present);
}
if (!data.getVersion().equals(version)) {
data.setVersion(version);
}
if (!data.getMinecraftVersion().equals(minecraftVersion)) {
data.setMinecraftVersion(minecraftVersion);
}
if (!data.getExactMinecraftVersion().equals(exactMinecraftVersion)) {
data.setExactMinecraftVersion(exactMinecraftVersion);
}
if (data.getProtocolVersion() != protocol) {
data.setProtocolVersion(protocol);
}
}
} else {
future.complete(new ServerPingVelocity(-1, false));
BackendInteractiveChatData data = InteractiveChatVelocity.serverInteractiveChatInfo.get(server.getName());
if (data == null) {
InteractiveChatVelocity.serverInteractiveChatInfo.put(server.getName(), new BackendInteractiveChatData(server.getName(), false, false, UNKNOWN_VERSION, MCVersion.UNSUPPORTED, UNKNOWN_VERSION, -1, UNKNOWN_PROTOCOL));
} else {
data.setPing(-1);
if (data.isOnline()) {
data.setOnline(false);
}
if (data.hasInteractiveChat()) {
data.setInteractiveChat(false);
}
if (!data.getVersion().equals(UNKNOWN_VERSION)) {
data.setVersion(UNKNOWN_VERSION);
}
if (data.getProtocolVersion() != UNKNOWN_PROTOCOL) {
data.setProtocolVersion(UNKNOWN_PROTOCOL);
}
}
}
} catch (IOException e) {
future.complete(new ServerPingVelocity(-1, false));
BackendInteractiveChatData data = InteractiveChatVelocity.serverInteractiveChatInfo.get(server.getName());
if (data == null) {
InteractiveChatVelocity.serverInteractiveChatInfo.put(server.getName(), new BackendInteractiveChatData(server.getName(), false, false, UNKNOWN_VERSION, MCVersion.UNSUPPORTED, UNKNOWN_VERSION, -1, UNKNOWN_PROTOCOL));
} else {
data.setPing(-1);
if (data.isOnline()) {
data.setOnline(false);
}
if (data.hasInteractiveChat()) {
data.setInteractiveChat(false);
}
if (!data.getVersion().equals(UNKNOWN_VERSION)) {
data.setVersion(UNKNOWN_VERSION);
}
if (data.getProtocolVersion() != UNKNOWN_PROTOCOL) {
data.setProtocolVersion(UNKNOWN_PROTOCOL);
}
}
}
}).start();
return future;
}
use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.
the class CommandsBungee method execute.
@Override
public void execute(CommandSender sender, String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
try {
if (args.length == 0) {
defaultMessage(sender);
return;
}
if (args[0].equalsIgnoreCase("backendinfo") && InteractiveChatBungee.hasPermission(sender, "interactivechat.backendinfo").get()) {
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.AQUA + "Proxy -> InteractiveChat: " + InteractiveChatBungee.plugin.getDescription().getVersion() + " (PM Protocol: " + Registry.PLUGIN_MESSAGING_PROTOCOL_VERSION + ")"));
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.AQUA + "Expected latency: " + InteractiveChatBungee.delay + " ms"));
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.AQUA + "Backends under this proxy:"));
ProxyServer.getInstance().getServers().values().stream().sorted(Comparator.comparing(each -> each.getName())).forEach(server -> {
String name = server.getName();
BackendInteractiveChatData data = InteractiveChatBungee.serverInteractiveChatInfo.get(name);
if (data == null) {
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.RED + name + " -> Attempting to retrieve data from backend..."));
} else {
String minecraftVersion = data.getExactMinecraftVersion();
if (data.isOnline()) {
if (!data.hasInteractiveChat()) {
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.YELLOW + name + " -> InteractiveChat: NOT INSTALLED (PM Protocol: -1) | Minecraft: " + minecraftVersion + " | Ping: " + (data.getPing() < 0 ? "N/A" : (data.getPing() + " ms"))));
} else {
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.GREEN + name + " -> InteractiveChat: " + data.getVersion() + " (PM Protocol: " + data.getProtocolVersion() + ") | Minecraft: " + minecraftVersion + " | Ping: " + (data.getPing() < 0 ? "N/A" : (data.getPing() + " ms"))));
}
} else {
InteractiveChatBungee.sendMessage(sender, LegacyComponentSerializer.legacySection().deserialize(ChatColor.RED + name + " -> Status: OFFLINE"));
}
}
});
return;
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
defaultMessage(sender);
}
}).start();
}
use of com.loohp.interactivechat.proxy.objectholders.BackendInteractiveChatData in project InteractiveChat by LOOHP.
the class InteractiveChatBungee method handleChat.
private void handleChat(ChatEvent event) {
if (event.isCancelled()) {
return;
}
event.setMessage(Registry.ID_PATTERN.matcher(event.getMessage()).replaceAll(""));
ProxiedPlayer player = (ProxiedPlayer) event.getSender();
UUID uuid = player.getUniqueId();
String message = event.getMessage();
String newMessage = event.getMessage();
boolean hasInteractiveChat = false;
Server server = player.getServer();
if (server != null) {
BackendInteractiveChatData data = serverInteractiveChatInfo.get(server.getInfo().getName());
if (data != null) {
hasInteractiveChat = data.hasInteractiveChat();
}
}
boolean usage = false;
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
Matcher matcher = icplaceholder.getKeyword().matcher(message);
if (matcher.find()) {
int start = matcher.start();
if ((start < 1 || message.charAt(start - 1) != '\\') || (start > 1 && message.charAt(start - 1) == '\\' && message.charAt(start - 2) == '\\')) {
usage = true;
break outer;
}
}
}
}
if (newMessage.startsWith("/")) {
if (usage && hasInteractiveChat) {
for (String parsecommand : InteractiveChatBungee.parseCommands) {
if (newMessage.matches(parsecommand)) {
String command = newMessage.trim();
if (tagEveryIdentifiableMessage) {
String uuidmatch = " <cmd=" + uuid + ">";
if (command.length() > 256 - uuidmatch.length()) {
command = command.substring(0, 256 - uuidmatch.length());
}
command = command + uuidmatch;
event.setMessage(command);
} else {
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
Pattern placeholder = icplaceholder.getKeyword();
Matcher matcher = placeholder.matcher(command);
if (matcher.find()) {
int start = matcher.start();
if ((start < 1 || command.charAt(start - 1) != '\\') || (start > 1 && command.charAt(start - 1) == '\\' && command.charAt(start - 2) == '\\')) {
String uuidmatch = "<cmd=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(command.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
command = command.substring(0, matcher.start()) + uuidmatch + command.substring(matcher.end());
if (command.length() > 256) {
command = command.substring(0, 256);
}
event.setMessage(command);
break outer;
}
}
}
}
}
break;
}
}
}
} else {
if (usage && useAccurateSenderFinder && hasInteractiveChat) {
if (tagEveryIdentifiableMessage) {
String uuidmatch = " <cmd=" + uuid + ">";
if (message.length() > 256 - uuidmatch.length()) {
message = message.substring(0, 256 - uuidmatch.length());
}
message = message + uuidmatch;
event.setMessage(message);
} else {
outer: for (List<ICPlaceholder> serverPlaceholders : placeholderList.values()) {
for (ICPlaceholder icplaceholder : serverPlaceholders) {
Pattern placeholder = icplaceholder.getKeyword();
Matcher matcher = placeholder.matcher(message);
if (matcher.find()) {
int start = matcher.start();
if ((start < 1 || message.charAt(start - 1) != '\\') || (start > 1 && message.charAt(start - 1) == '\\' && message.charAt(start - 2) == '\\')) {
String uuidmatch = "<chat=" + uuid + ":" + Registry.ID_ESCAPE_PATTERN.matcher(message.substring(matcher.start(), matcher.end())).replaceAll("\\>") + ":>";
message = message.substring(0, matcher.start()) + uuidmatch + message.substring(matcher.end());
if (message.length() > 256) {
message = message.substring(0, 256);
}
event.setMessage(message);
break outer;
}
}
}
}
}
}
ProxyServer.getInstance().getScheduler().schedule(plugin, () -> {
Map<String, Long> messages = forwardedMessages.get(uuid);
if (messages != null && messages.remove(newMessage) != null) {
try {
PluginMessageSendingBungee.sendMessagePair(uuid, newMessage);
} catch (IOException e) {
e.printStackTrace();
}
}
}, 100, TimeUnit.MILLISECONDS);
}
}
Aggregations