/*
* This file is part of Libelula Minecraft Edition Project.
*
* Libelula Minecraft Edition is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Libelula Minecraft Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Libelula Minecraft Edition.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
package me.libelula.networkmanager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
/**
*
* @author Diego D'Onofrio <ddonofrio@member.fsf.org>
*/
public class CommunicationManager {
public enum MessageType {
CHAT, WHISPER, NOTIFY_PLAYER, ENTER, LEFT, FRIEND_REQUEST,
FRIEND_REQUEST_ANSWER, RUN_COMMAND
}
private class Server extends Thread {
public boolean running;
private DatagramSocket serverSocket;
private final byte[] receiveData;
public Server() {
receiveData = new byte[1024];
running = true;
}
public void setPort(int port) throws SocketException {
serverSocket = new DatagramSocket(port);
}
@Override
public void run() {
while (running) {
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
try {
serverSocket.receive(receivePacket);
if (plugin.getConfig().getBoolean("debug")) {
plugin.getLogger().log(Level.INFO, "DEBUG: msg size={0}", receivePacket.getLength());
}
String recievedText = new String(receivePacket.getData()).substring(0, receivePacket.getLength());
String command[] = recievedText.split("\0");
ServerManager.Server remoteServer;
if (command.length < 1) {
continue;
}
if (plugin.getConfig().getBoolean("debug")) {
String messageList = "";
for (String part : command) {
messageList = messageList + "\"" + part + "\", ";
}
plugin.getLogger().log(Level.INFO, "<Debug> Message received: {0}", messageList);
}
switch (command[0]) {
case "ENTER":
if (command.length != 4) {
continue;
}
// 1 - server ID
// 2 - player.getName()
// 3 - player.getDisplayName()
remoteServer = plugin.sm.getServer(command[1]);
if (remoteServer != null) {
plugin.pm.addRemotePlayer(remoteServer, command[2], command[3]);
if (plugin.getConfig().getBoolean("debug")) {
plugin.getLogger().log(Level.INFO, "Player {0} added to our list.", command[2]);
}
} else {
plugin.getLogger().log(Level.SEVERE, "Receiving messages from unconfigured remote server:{0}", command[1]);
}
break;
case "CHAT":
if (command.length != 5) {
continue;
}
// 1 - server ID
// 2 - player.getName()
// 3 - player.getDisplayName()
// 4 - message
break;
case "WHISPER":
if (command.length != 6) {
continue;
}
// 1 - server ID
// 2 - sender.getName()
// 3 - reciever.getName()
// 4 - sender.getDisplayName()
// 5 - message
remoteServer = plugin.sm.getServer(command[1]);
if (remoteServer != null) {
PlayerManager.PlayerInfo pi = plugin.pm.getPlayerInfo(command[2]);
if (pi == null || !pi.getServer().getServerId().equals(remoteServer.getServerId())) {
plugin.pm.addRemotePlayer(remoteServer, command[2], command[4]);
}
{
final ServerManager.Server server = remoteServer;
final String recieverName = command[3];
final String senderName = command[2];
final String senderDisplayName = command[4];
final String message = command[5];
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Player reciever = null;
for (Player player : plugin.getServer().getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(recieverName)) {
reciever = player;
break;
}
}
if (reciever != null) {
plugin.pm.processRemoteMessage(server,
reciever, senderName, senderDisplayName, message);
} else {
String args[] = {senderName, plugin.getPrefix() + ChatColor.RED + "Jugador \"" + recieverName + "\" no encontrado."};
sendMessage(formatMessage(MessageType.NOTIFY_PLAYER, args),
server.getAddress());
}
}
});
}
} else {
plugin.getLogger().log(Level.SEVERE, "Receiving messages from unconfigured remote server:{0}", command[1]);
}
break;
case "NOTIFY_PLAYER":
if (command.length != 4) {
continue;
}
// 1 - server ID
// 2 - reciever.getName()
// 3 - message
{
final String recieverName = command[2];
final String message = command[3];
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Player reciever = null;
for (Player player : plugin.getServer().getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(recieverName)) {
reciever = player;
break;
}
}
if (reciever != null) {
reciever.sendMessage(message);
}
}
});
}
break;
case "FRIEND_REQUEST":
if (command.length != 4) {
continue;
}
// 1 - server ID
// 2 - reciever.getName()
// 3 - sender.getName()
{
final ServerManager.Server server = plugin.sm.getServer(command[1]);;
final String recieverName = command[2];
final String senderName = command[3];
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Player reciever = null;
for (Player player : plugin.getServer().getOnlinePlayers()) {
if (player.getName().equalsIgnoreCase(recieverName)) {
reciever = player;
break;
}
}
if (reciever != null) {
PlayerManager.PlayerInfo pi = plugin.pm.getPlayerInfo(recieverName);
if (pi != null) {
// plugin.pm.localyProcessAddFriendRequest(reciever, pi, senderName);
} else {
String args[] = {senderName, plugin.getPrefix() + ChatColor.RED + "Jugador \"" + recieverName + "\" no encontrado."};
sendMessage(formatMessage(MessageType.NOTIFY_PLAYER, args),
server.getAddress());
}
} else {
}
}
});
}
break;
case "FRIEND_REQUEST_ANSWER":
if (command.length != 5) {
continue;
}
// 1 - server ID
// 2 - requester.getName()
// 3 - answeringPlayer.getName()
// 4 - answer: ACCEPT/DENY
{
final ServerManager.Server server = plugin.sm.getServer(command[1]);;
final String requesterName = command[2];
final String answeringPlayerName = command[3];
final boolean hasAccepted = command[4].equals("ACCEPT");
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
Player requester = plugin.pm.getOnlinePlayer(requesterName);
if (requester != null) {
PlayerManager.PlayerInfo pi = plugin.pm.getPlayerInfo(requesterName);
if (pi != null) {
if (hasAccepted) {
requester.sendMessage(plugin.getPrefix() + "Ahora " + answeringPlayerName + " es tu amigo.");
requester.sendMessage(plugin.getPrefix() + "Se ha incrementado tu reputación en 1 punto.");
} else {
requester.sendMessage(plugin.getPrefix() + "El jugador " + answeringPlayerName + " no desea ser tu amigo en este momento.");
}
} else {
if (hasAccepted) {
String args[] = {answeringPlayerName, plugin.getPrefix()
+ ChatColor.RED + "Error enviando amistad a la otra parte, es posible que él no sea tu amigo."};
sendMessage(formatMessage(MessageType.NOTIFY_PLAYER, args),
server.getAddress());
}
}
} else {
if (hasAccepted) {
String args[] = {answeringPlayerName, plugin.getPrefix()
+ ChatColor.RED + "Error enviando amistad a la otra parte, es posible que él no sea tu amigo."};
sendMessage(formatMessage(MessageType.NOTIFY_PLAYER, args),
server.getAddress());
}
}
}
});
}
break;
case "RUN_COMMAND":
if (command.length != 4) {
continue;
}
// 1 - server ID
// 2 - sender.getName()
// 3 - Command
{
final ServerManager.Server server = plugin.sm.getServer(command[1]);;
final String sender = command[2];
final String commandLine = command[3];
Bukkit.getScheduler().runTask(plugin, new Runnable() {
@Override
public void run() {
plugin.getLogger().log(Level.INFO,
"RPC: Server={0} | sender={1} | cmd={2}",
new Object[]{server.getName(), sender, commandLine});
Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), commandLine);
String args[] = {sender, plugin.getPrefix()
+ ChatColor.GREEN + plugin.sm.getServerId() + " Enterado."};
sendMessage(formatMessage(MessageType.NOTIFY_PLAYER, args),
server.getAddress());
}
});
}
break;
}
/* responce:
InetAddress IPAddress = receivePacket.getAddress();
int port = receivePacket.getPort();
String capitalizedSentence = sentence.toUpperCase();
sendData = capitalizedSentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port);
serverSocket.send(sendPacket);
*/
} catch (IOException ex) {
Logger.getLogger(CommunicationManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
serverSocket.disconnect();
serverSocket.close();
}
}
private final Server server;
private final Main plugin;
public CommunicationManager(Main plugin) {
this.plugin = plugin;
server = new Server();
}
public void startServer(int port) throws SocketException {
server.setPort(port);
server.start();
}
public void stopServer() {
server.running = false;
String message = "NOP";
try (DatagramSocket clientSocket = new DatagramSocket()) {
DatagramPacket sendPacket;
sendPacket = new DatagramPacket(message.getBytes(), message.length(),
plugin.sm.getInetSocketAddress());
clientSocket.send(sendPacket);
clientSocket.close();
} catch (SocketException ex) {
Logger.getLogger(CommunicationManager.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CommunicationManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendMessage(final String message, final InetSocketAddress address) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
@Override
public void run() {
try (DatagramSocket clientSocket = new DatagramSocket()) {
DatagramPacket sendPacket = new DatagramPacket(message.getBytes(), message.length(), address);
clientSocket.send(sendPacket);
clientSocket.close();
} catch (SocketException ex) {
Logger.getLogger(CommunicationManager.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(CommunicationManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
public String queryServer(String message, InetSocketAddress address) throws SocketException,
UnknownHostException, IOException {
String ret;
try (DatagramSocket clientSocket = new DatagramSocket()) {
byte[] receiveData = new byte[1024];
DatagramPacket sendPacket = new DatagramPacket(message.getBytes(), message.length(), address);
clientSocket.send(sendPacket);
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
clientSocket.setSoTimeout(1000);
clientSocket.receive(receivePacket);
ret = new String(receivePacket.getData());
clientSocket.close();
}
return ret;
}
public String getSting(URL url) throws IOException {
String configuration = "";
URLConnection con = url.openConnection();
con.setConnectTimeout(1000);
con.setReadTimeout(1000);
try (BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
configuration = configuration + inputLine + "\n";
}
in.close();
}
return configuration;
}
public void broadCast(String message) {
for (InetSocketAddress address : plugin.sm.getAddresses()) {
sendMessage(message, address);
}
}
public String formatMessage(MessageType messageType, String[] args) {
String ret;
switch (messageType) {
case ENTER:
// 1 - server ID
// 2 - player.getName()
// 3 - player.getDisplayName()
ret = "ENTER\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0";
break;
case WHISPER:
// 1 - server ID
// 2 - sender.getName()
// 3 - reciever.getName()
// 4 - sender.getDisplayName()
// 5 - message
ret = "WHISPER\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0" + args[2] + "\0" + args[3] + "\0";
break;
case NOTIFY_PLAYER:
// 1 - server ID
// 2 - reciever.getName()
// 3 - message
ret = "NOTIFY_PLAYER\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0";
break;
case FRIEND_REQUEST:
// 1 - server ID
// 2 - reciever.getName()
// 3 - sender.getName()
ret = "FRIEND_REQUEST\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0";
break;
case FRIEND_REQUEST_ANSWER:
// 1 - server ID
// 2 - requester.getName()
// 3 - answeringPlayer.getName()
// 4 - answer: ACCEPT/DENY
ret = "FRIEND_REQUEST_ANSWER\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0" + args[2] + "\0";
break;
case RUN_COMMAND:
// 1 - server ID
// 2 - sender.getName()
// 3 - Command
ret = "RUN_COMMAND\0" + plugin.sm.getServerId() + "\0" + args[0] + "\0" + args[1] + "\0";
default:
ret = "NOOP";
break;
}
return ret
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
}
}