diff --git a/Plugins/Mineplex.Core/src/mineplex/core/portal/Portal.java b/Plugins/Mineplex.Core/src/mineplex/core/portal/Portal.java index 28496a9b4..8a8427201 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/portal/Portal.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/portal/Portal.java @@ -19,6 +19,8 @@ import mineplex.core.portal.Commands.*; import mineplex.serverdata.Region; import mineplex.serverdata.ServerCommandManager; import mineplex.serverdata.ServerManager; +import mineplex.serverdata.transfers.ServerTransfer; +import mineplex.serverdata.transfers.TransferCommand; public class Portal extends MiniPlugin { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/portal/TransferHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/portal/TransferHandler.java new file mode 100644 index 000000000..725f8ee15 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/portal/TransferHandler.java @@ -0,0 +1,29 @@ +package mineplex.core.portal; + +import mineplex.serverdata.CommandCallback; +import mineplex.serverdata.ServerCommand; +import mineplex.serverdata.transfers.ServerTransfer; +import mineplex.serverdata.transfers.TransferCommand; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class TransferHandler implements CommandCallback +{ + + public void run(ServerCommand command) + { + if (command instanceof TransferCommand) + { + TransferCommand transferCommand = (TransferCommand) command; + ServerTransfer transfer = transferCommand.getTransfer(); + + Player player = Bukkit.getPlayer(transfer.getPlayerName()); + + if (player != null && player.isOnline()) + { + Portal.getInstance().SendPlayerToServer(player, transfer.getServerName()); + } + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/Report.java b/Plugins/Mineplex.Core/src/mineplex/core/report/Report.java new file mode 100644 index 000000000..5e7ab4592 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/Report.java @@ -0,0 +1,44 @@ +package mineplex.core.report; + +import java.util.HashSet; +import java.util.Set; + +import mineplex.serverdata.Data; + +public class Report implements Data +{ + + private int _reportId; + public int getReportId() { return _reportId; } + + private String _serverName; + public String getServerName() { return _serverName; } + + private String _playerName; + public String getPlayerName() { return _playerName; } + + // Set of account ids of players who contributed to reporting this player + private Set _reporters; + public Set getReporters() { return _reporters; } + public void addReporter(String reporter) { _reporters.add(reporter); } + + /** + * Class constructor + * @param reportId + * @param playerName + * @param serverName + */ + public Report(int reportId, String playerName, String serverName) + { + _reportId = reportId; + _playerName = playerName; + _serverName = serverName; + _reporters = new HashSet(); + } + + @Override + public String getDataId() + { + return String.valueOf(_reportId); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java new file mode 100644 index 000000000..63479b604 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java @@ -0,0 +1,318 @@ +package mineplex.core.report; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import mineplex.core.account.CoreClient; +import mineplex.core.command.CommandCenter; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.portal.Portal; +import mineplex.core.report.command.ReportNotification; +import mineplex.serverdata.DataRepository; +import mineplex.serverdata.RedisDataRepository; +import mineplex.serverdata.Region; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.exceptions.JedisConnectionException; + +/** + * ReportManager hooks into a synchronized network-wide report system + * with methods for updating/fetching/closing reports in real time. + * @author Ty + * + */ +public class ReportManager { + + private static ReportManager instance; + + // Holds active/open reports in a synchronized database. + private DataRepository reportRepository; + + private DataRepository reportProfiles; + + // Stores/logs closed tickets, and various reporter/staff actions. + private ReportRepository reportSqlRepository; + + // A mapping of PlayerName(String) to the ReportId(Integer) for all active reports on this server. + private Map activeReports; + + /** + * Private constructor to prevent non-singleton instances. + */ + private ReportManager() + { + this.reportRepository = new RedisDataRepository(Region.ALL, Report.class, "reports"); + this.reportProfiles = new RedisDataRepository(Region.ALL, ReportProfile.class, "reportprofiles"); + this.activeReports = new HashMap(); + + // TODO: Get JavaPlugin instance and locate ConnectionString from config? + this.reportSqlRepository = new ReportRepository(ReportPlugin.getPlugin(), "CONNECTION STRING HERE"); + reportSqlRepository.initialize(); + } + + public void retrieveReportResult(int reportId, Player reportCloser, String reason) + { + // Prompt the report closer with a menu of options to determine the result + // of the report. When confirmation is received, THEN close report. + } + + public void closeReport(int reportId, Player reportCloser, String reason) + { + retrieveReportResult(reportId, reportCloser, reason); + } + + public void closeReport(int reportId, Player reportCloser, String reason, + ReportResult result) + { + if (isActiveReport(reportId)) + { + Report report = getReport(reportId); + reportRepository.removeElement(String.valueOf(reportId)); // Remove report from redis database + removeActiveReport(reportId); + + int closerId = getPlayerAccount(reportCloser).GetAccountId(); + String playerName = getReport(reportId).getPlayerName(); + int playerId = getPlayerAccount(playerName).GetAccountId(); + String server = null; // TODO: Get current server name + reportSqlRepository.logReport(reportId, playerId, server, closerId, result, reason); + + // Update the reputation/profiles of all reporters on this closing report. + for (String reporterName : report.getReporters()) + { + CoreClient reporterAccount = getPlayerAccount(reporterName); + ReportProfile reportProfile = getReportProfile(String.valueOf(reporterAccount.GetAccountId())); + reportProfile.onReportClose(result); + reportProfiles.addElement(reportProfile); + } + + if (reportCloser != null) + { + // Notify staff that the report was closed. + sendReportNotification(String.format("[Report %d] %s closed this report. (%s).", reportId, + reportCloser.getName(), result.toDisplayMessage())); + } + } + + } + + public void handleReport(int reportId, Player reportHandler) + { + if (reportRepository.elementExists(String.valueOf(reportId))) + { + Report report = getReport(reportId); + Portal.transferPlayer(reportHandler.getName(), report.getServerName()); + String handlerName = reportHandler.getName(); + sendReportNotification(String.format("[Report %d] %s is handling this report.", reportId, handlerName)); + + // TODO: Send display message to handler when they arrive on the server + // with info about the case/report. + + int handlerId = getPlayerAccount(reportHandler).GetAccountId(); + reportSqlRepository.logReportHandling(reportId, handlerId); // Log handling into sql database + } + } + + public void reportPlayer(Player reporter, Player reportedPlayer, String reason) + { + int reporterId = getPlayerAccount(reporter).GetAccountId(); + ReportProfile reportProfile = getReportProfile(String.valueOf(reporterId)); + + if (reportProfile.canReport()) + { + Report report = null; + + if (hasActiveReport(reportedPlayer)) + { + int reportId = getActiveReport(reportedPlayer.getName()); + report = getReport(reportId); + report.addReporter(reporter.getName()); + } + else + { + String serverName = null; // TODO: Fetch name of current server + int reportId = generateReportId(); + report = new Report(reportId, reportedPlayer.getName(), serverName); + report.addReporter(reporter.getName()); + activeReports.put(reportedPlayer.getName().toLowerCase(), report.getReportId()); + reportRepository.addElement(report); + } + + if (report != null) + { + // [Report 42] [MrTwiggy +7] [Cheater102 - 5 - Speed hacking] + String message = String.format("[Report %d] [%s %d] [%s - %d - %s]", report.getReportId(), + reporter.getName(), reportProfile.getReputation(), + reportedPlayer.getName(), report.getReporters().size(), reason); + sendReportNotification(message); + reportSqlRepository.logReportSending(report.getReportId(), reporterId, reason); + } + } + } + + public void onPlayerQuit(Player player) + { + if (hasActiveReport(player)) + { + int reportId = getActiveReport(player.getName()); + this.closeReport(reportId, null, "Player Quit", ReportResult.UNDETERMINED); + // TODO: Handle 'null' report closer in closeReport metohd for NPEs. + + sendReportNotification(String.format("[Report %d] %s has left the game.", reportId, player.getName())); + } + } + + public ReportProfile getReportProfile(String playerName) + { + ReportProfile profile = reportProfiles.getElement(playerName); + + if (profile == null) + { + profile = new ReportProfile(playerName, getAccountId(playerName)); + saveReportProfile(profile); + } + + return profile; + } + + private void saveReportProfile(ReportProfile profile) + { + reportProfiles.addElement(profile); + } + + /** + * @return a uniquely generated report id. + */ + public int generateReportId() + { + JedisPool pool = ((RedisDataRepository) reportRepository).getJedisPool(); + Jedis jedis = pool.getResource(); + long uniqueReportId = -1; + + try + { + uniqueReportId = jedis.incr("reports.unique-id"); + } + catch (JedisConnectionException exception) + { + exception.printStackTrace(); + pool.returnBrokenResource(jedis); + jedis = null; + } + finally + { + if (jedis != null) + { + pool.returnResource(jedis); + } + } + + return (int) uniqueReportId; + } + + public Report getReport(int reportId) + { + return reportRepository.getElement(String.valueOf(reportId)); + } + + private CoreClient getPlayerAccount(Player player) + { + return getPlayerAccount(player.getName()); + } + + private CoreClient getPlayerAccount(String playerName) + { + return CommandCenter.Instance.GetClientManager().Get(playerName); + } + + private int getAccountId(String playerName) + { + return getPlayerAccount(playerName).GetAccountId(); + } + + /** + * @param player - the player whose report notification settings are to be checked + * @return true, if the player should receive report notifications, false otherwise. + */ + public boolean hasReportNotifications(Player player) + { + // If player is not staff, return false. + // If player is staff but has report notifications pref disabled, return false; + // Else return true. + return false; + } + + /** + * Send a network-wide {@link ReportNotification} to all online staff. + * @param message - the report notification message to send. + */ + public void sendReportNotification(String message) + { + ReportNotification reportNotification = new ReportNotification(message); + reportNotification.publish(); + } + + /** + * @param playerName - the name of the player whose active report id is being fetched + * @return the report id for the active report corresponding with playerName, if one + * currently exists, -1 otherwise. + */ + public int getActiveReport(String playerName) + { + if (activeReports.containsKey(playerName.toLowerCase())) + { + return activeReports.get(playerName.toLowerCase()); + } + + return -1; + } + + public boolean hasActiveReport(Player player) + { + return getActiveReport(player.getName()) != -1; + } + + public boolean isActiveReport(int reportId) + { + for (Entry activeReport : activeReports.entrySet()) + { + if (activeReport.getValue() == reportId) + { + return true; + } + } + + return false; + } + + public boolean removeActiveReport(int reportId) + { + for (Entry activeReport : activeReports.entrySet()) + { + if (activeReport.getValue() == reportId) + { + activeReports.remove(activeReport.getKey()); + return true; + } + } + + return false; + } + + /** + * @return the singleton instance of {@link ReportManager}. + */ + public static ReportManager getInstance() + { + if (instance == null) + { + instance = new ReportManager(); + } + + return instance; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java new file mode 100644 index 000000000..5293cf78b --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java @@ -0,0 +1,32 @@ +package mineplex.core.report; + +import mineplex.core.MiniPlugin; +import mineplex.core.report.command.ReportCloseCommand; +import mineplex.core.report.command.ReportCommand; +import mineplex.core.report.command.ReportDebugCommand; +import mineplex.core.report.command.ReportHandleCommand; + +import org.bukkit.plugin.java.JavaPlugin; + +public class ReportPlugin extends MiniPlugin +{ + + private static JavaPlugin instance; + public static JavaPlugin getPlugin() { return instance; } + + public ReportPlugin(JavaPlugin plugin, String serverName) + { + super("ReportPlugin", plugin); + + instance = plugin; + } + + @Override + public void AddCommands() + { + AddCommand(new ReportCommand(this)); + AddCommand(new ReportHandleCommand(this)); + AddCommand(new ReportCloseCommand(this)); + AddCommand(new ReportDebugCommand(this)); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java new file mode 100644 index 000000000..2192676d4 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java @@ -0,0 +1,61 @@ +package mineplex.core.report; + +import mineplex.serverdata.Data; + +public class ReportProfile implements Data +{ + + private String _playerName; + + private int _playerId; + + private int _totalReports; + + private int _successfulReports; + + private int _reputation; + public int getReputation() { return _reputation; } + + private boolean _banned; + + public ReportProfile(String playerName, int playerId) + { + _playerName = playerName; + _playerId = playerId; + _totalReports = 0; + _successfulReports = 0; + _reputation = 0; + _banned = false; + } + + @Override + public String getDataId() + { + return String.valueOf(_playerId); + } + + public boolean canReport() + { + return !_banned; + } + + /** + * Called when a report made by this player is closed. + * @param result - the result of the closed report. + */ + public void onReportClose(ReportResult result) + { + _totalReports++; + + if (result == ReportResult.MUTED || result == ReportResult.BANNED) + { + _successfulReports++; + _reputation++; + } + else if (result == ReportResult.ABUSE) + { + _reputation = -1; + _banned = true; + } + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java new file mode 100644 index 000000000..968010e9c --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java @@ -0,0 +1,78 @@ +package mineplex.core.report; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.UUID; +import java.util.Map.Entry; + +import mineplex.core.common.util.NautHashMap; +import mineplex.core.database.RepositoryBase; +import mineplex.core.database.ResultSetCallable; +import mineplex.core.database.column.ColumnInt; +import mineplex.core.database.column.ColumnVarChar; +import mineplex.core.preferences.UserPreferences; + +import org.bukkit.plugin.java.JavaPlugin; + +public class ReportRepository extends RepositoryBase +{ + /* + * *ReportTicket +id, date, accountId reported player, server, accountId of staff who closed, result, reason + +ReportSenders +id, date, reportId, accountId of Reporter, Reason for report + +ReportHandlers +id, date, reportId, accountId of Staff + +This will be used to determine if staff are handling + */ + + private static String CREATE_TICKET_TABLE = "CREATE TABLE IF NOT EXISTS reportTickets (reportId INT NOT NULL, date LONG, eventDate LONG, playerId INT NOT NULL, server VARCHAR(50), closerId INT NOT NULL, result VARCHAR(25), reason VARCHAR(100), PRIMARY KEY (reportId), INDEX playerIdIndex (playerId), INDEX closerIdIndex (closerId));"; + private static String CREATE_HANDLER_TABLE = "CREATE TABLE IF NOT EXISTS reportHandlers (id INT NOT NULL AUTO_INCREMENT, reportId INT NOT NULL, eventDate LONG, handlerId INT NOT NULL, PRIMARY KEY (id), INDEX handlerIdIndex (handlerId) );"; + private static String CREATE_REPORTERS_TABLE = "CREATE TABLE IF NOT EXISTS reportSenders (id INT NOT NULL AUTO_INCREMENT, reportId INT NOT NULL, eventDate LONG, reporterId INT NOT NULL, reason VARCHAR(100), PRIMARY KEY (id), INDEX reporterIdIndex (reporterId));"; + + private static String INSERT_TICKET = "INSERT INTO reportTickets (reportId, eventDate, playerId, server, closerId, result, reason) VALUES (?, now(), ?, ?, ?, ?, ?);"; + private static String INSERT_HANDLER = "INSERT INTO reportHandlers (eventDate, reportId, handlerId) VALUES(now(), ?, ?);"; + private static String INSERT_SENDER = "INSERT INTO reportSenders (eventDate, reportId, reporterId, reason) VALUES(now(), ?, ?, ?);"; + + public ReportRepository(JavaPlugin plugin, String connectionString) + { + super(plugin, connectionString, "root", "tAbechAk3wR7tuTh"); // TODO: Config file for host/pass? + } + + @Override + protected void initialize() + { + executeUpdate(CREATE_TICKET_TABLE); + executeUpdate(CREATE_HANDLER_TABLE); + executeUpdate(CREATE_REPORTERS_TABLE); + } + + @Override + protected void update() + { + + } + + public void logReportHandling(int reportId, int handlerId) + { + executeUpdate(INSERT_HANDLER, new ColumnInt("reportId", reportId), new ColumnInt("handlerId", handlerId)); + } + + public void logReportSending(int reportId, int reporterId, String reason) + { + executeUpdate(INSERT_SENDER, new ColumnInt("reportId", reportId), new ColumnInt("reporterId", reporterId), + new ColumnVarChar("reason", 100, reason)); + } + + public void logReport(int reportId, int playerId, String server, int closerId, ReportResult result, String reason) + { + executeUpdate(INSERT_TICKET, new ColumnInt("reportId", reportId), new ColumnInt("playerId", playerId), + new ColumnVarChar("server", 50, server), new ColumnInt("closerId", closerId), + new ColumnVarChar("result", 25, result.toString()), new ColumnVarChar("reason", 100, reason)); + } + +} \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportResult.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportResult.java new file mode 100644 index 000000000..fc2f3abcf --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportResult.java @@ -0,0 +1,25 @@ +package mineplex.core.report; + +import org.bukkit.ChatColor; + +public enum ReportResult +{ + UNDETERMINED(ChatColor.WHITE, "Could not determine"), + MUTED(ChatColor.YELLOW, "Muted"), + BANNED(ChatColor.RED, "Banned"), + ABUSE(ChatColor.DARK_RED, "Abuse of report system"); + + private ChatColor color; + private String displayMessage; + + private ReportResult(ChatColor color, String displayMessage) + { + this.color = color; + this.displayMessage = displayMessage; + } + + public String toDisplayMessage() + { + return color + displayMessage; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java new file mode 100644 index 000000000..49e232446 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java @@ -0,0 +1,39 @@ +package mineplex.core.report.command; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.common.util.Callback; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.portal.Portal; +import mineplex.core.report.ReportManager; +import mineplex.core.report.ReportPlugin; + +import org.bukkit.entity.Player; + +public class ReportCloseCommand extends CommandBase +{ + + public ReportCloseCommand(ReportPlugin plugin) + { + super(plugin, Rank.ADMIN, "reportclose", "rc"); + } + + @Override + public void Execute(final Player player, final String[] args) + { + if(args == null || args.length < 2) + { + UtilPlayer.message(player, F.main(Plugin.GetName(), C.cRed + "Your arguments are inappropriate for this command!")); + return; + } + else + { + int reportId = Integer.parseInt(args[0]); + String reason = F.combine(args, 1, null, false); + + ReportManager.getInstance().closeReport(reportId, player, reason); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java new file mode 100644 index 000000000..f9cebd2aa --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java @@ -0,0 +1,48 @@ +package mineplex.core.report.command; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.common.util.Callback; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.portal.Portal; +import mineplex.core.report.ReportManager; +import mineplex.core.report.ReportPlugin; + +import org.bukkit.entity.Player; + +public class ReportCommand extends CommandBase +{ + + public ReportCommand(ReportPlugin plugin) + { + super(plugin, Rank.ALL, "report"); + } + + @Override + public void Execute(final Player player, final String[] args) + { + if(args == null || args.length < 2) + { + UtilPlayer.message(player, F.main(Plugin.GetName(), C.cRed + "Your arguments are inappropriate for this command!")); + return; + } + else + { + String playerName = args[0]; + Player reportedPlayer = UtilPlayer.searchOnline(player, playerName, false); + String reason = F.combine(args, 1, null, false); + + if (reportedPlayer != null) + { + ReportManager.getInstance().reportPlayer(player, reportedPlayer, reason); + } + else + { + UtilPlayer.message(player, F.main(Plugin.GetName(), C.cRed + "Unable to find player '" + + playerName + "'!")); + } + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java new file mode 100644 index 000000000..099bbe14b --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java @@ -0,0 +1,38 @@ +package mineplex.core.report.command; + +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.C; +import mineplex.core.common.util.Callback; +import mineplex.core.common.util.F; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.portal.Portal; +import mineplex.core.report.ReportManager; +import mineplex.core.report.ReportPlugin; + +import org.bukkit.entity.Player; + +public class ReportHandleCommand extends CommandBase +{ + + public ReportHandleCommand(ReportPlugin plugin) + { + super(plugin, Rank.ADMIN, "reporthandle", "rh"); + } + + @Override + public void Execute(final Player player, final String[] args) + { + if(args == null || args.length < 1) + { + UtilPlayer.message(player, F.main(Plugin.GetName(), C.cRed + "Your arguments are inappropriate for this command!")); + return; + } + else + { + int reportId = Integer.parseInt(args[0]); + + ReportManager.getInstance().handleReport(reportId, player); + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java new file mode 100644 index 000000000..3b670328d --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java @@ -0,0 +1,31 @@ +package mineplex.core.report.command; + +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.report.ReportManager; +import mineplex.serverdata.ServerCommand; + +public class ReportNotification extends ServerCommand +{ + + // TODO: Encode in JSON-interactive chat message + private String notification; + + public ReportNotification(String notification) + { + super(); // Send to all servers + } + + public void run() + { + // Message all players that can receive report notifications. + for (Player player : UtilServer.getPlayers()) + { + if (ReportManager.getInstance().hasReportNotifications(player)) + { + player.sendMessage(notification); + } + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java b/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java index 36e62d011..1a0daeb0b 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/status/ServerStatusManager.java @@ -15,6 +15,7 @@ import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.serverdata.MinecraftServer; import mineplex.serverdata.Region; +import mineplex.serverdata.ServerCommandManager; import mineplex.serverdata.ServerManager; import mineplex.serverdata.ServerRepository; import mineplex.serverdata.Utility; @@ -47,6 +48,9 @@ public class ServerStatusManager extends MiniPlugin setupConfigValues(); _name = plugin.getConfig().getString("serverstatus.name"); + + ServerCommandManager.getInstance().initializeServer(_name); + _us = plugin.getConfig().getBoolean("serverstatus.us"); Region region = _us ? Region.US : Region.EU; diff --git a/Plugins/Mineplex.Queuer/.classpath b/Plugins/Mineplex.Queuer/.classpath index aedde4fb1..567d1286d 100644 --- a/Plugins/Mineplex.Queuer/.classpath +++ b/Plugins/Mineplex.Queuer/.classpath @@ -8,6 +8,5 @@ - diff --git a/Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueRepository.java b/Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueRepository.java index 6be115ca6..212ea83a5 100644 --- a/Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueRepository.java +++ b/Plugins/Mineplex.Queuer/src/mineplex/queuer/QueueRepository.java @@ -9,14 +9,14 @@ import java.util.Set; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; -import mineplex.core.portal.Portal; -import mineplex.core.portal.ServerTransfer; import mineplex.serverdata.DataRepository; import mineplex.serverdata.MinecraftServer; import mineplex.serverdata.RedisDataRepository; import mineplex.serverdata.Region; import mineplex.serverdata.ServerManager; import mineplex.serverdata.ServerRepository; +import mineplex.serverdata.transfers.ServerTransfer; +import mineplex.serverdata.transfers.TransferCommand; public class QueueRepository { @@ -130,7 +130,10 @@ public class QueueRepository { for (String playerName : queueParty.getPlayers()) { - Portal.transferPlayer(playerName, emptyServer.getName()); + // Execute a transfer command + ServerTransfer serverTransfer = new ServerTransfer(playerName, emptyServer.getName()); + TransferCommand transferCommand = new TransferCommand(serverTransfer); + transferCommand.publish(); } } } diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandCallback.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandCallback.java new file mode 100644 index 000000000..0e0c86cf3 --- /dev/null +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandCallback.java @@ -0,0 +1,7 @@ +package mineplex.serverdata; + +public interface CommandCallback +{ + + public void run(ServerCommand command); +} diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandType.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandType.java new file mode 100644 index 000000000..9e0b34edb --- /dev/null +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/CommandType.java @@ -0,0 +1,17 @@ +package mineplex.serverdata; + +public class CommandType +{ + + private Class _commandClazz; + public Class getCommandType() { return _commandClazz; } + + private CommandCallback _commandCallback; + public CommandCallback getCallback() { return _commandCallback; } + + public CommandType(Class commandClazz, CommandCallback commandCallback) + { + _commandClazz = commandClazz; + _commandCallback = commandCallback; + } +} diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/RedisDataRepository.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/RedisDataRepository.java index 3802afd13..2577ca1bc 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/RedisDataRepository.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/RedisDataRepository.java @@ -27,9 +27,9 @@ public class RedisDataRepository implements DataRepository // The geographical region of the servers stored by this ServerRepository private Region _region; - private Class elementType; + private Class _elementType; - private String elementLabel; + private String _elementLabel; /** * Class constructor @@ -40,10 +40,10 @@ public class RedisDataRepository implements DataRepository public RedisDataRepository(String host, int port, Region region, Class elementType, String elementLabel) { - this._jedisPool = new JedisPool(new JedisPoolConfig(), host, port); - this._region = region; - this.elementType = elementType; - this.elementLabel = elementLabel; + _jedisPool = new JedisPool(new JedisPoolConfig(), host, port); + _region = region; + _elementType = elementType; + _elementLabel = elementLabel; } public RedisDataRepository(Region region, Class elementType, String elementLabel) @@ -54,7 +54,7 @@ public class RedisDataRepository implements DataRepository public String getElementSetKey() { - return concatenate("data", elementLabel, _region.toString()); + return concatenate("data", _elementLabel, _region.toString()); } public String generateKey(T element) @@ -315,7 +315,7 @@ public class RedisDataRepository implements DataRepository protected T deserialize(String serializedData) { - return Utility.deserialize(serializedData, elementType); + return Utility.deserialize(serializedData, _elementType); } protected String serialize(T element) diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommand.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommand.java index a442a5af6..f31752243 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommand.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommand.java @@ -4,7 +4,7 @@ public abstract class ServerCommand { // The names of servers targetted to receive this ServerCommand. - private String[] targetServers; + private String[] _targetServers; /** * Class constructor @@ -12,13 +12,16 @@ public abstract class ServerCommand */ public ServerCommand(String... targetServers) { - this.targetServers = targetServers; + _targetServers = targetServers; } /** * Run the command on it's destination target server. */ - public abstract void run(); + public void run() + { + // Not yet implemented in base + } /** * @param serverName - the name of the server to be checked for whether they are a target @@ -27,10 +30,10 @@ public abstract class ServerCommand */ public boolean isTargetServer(String serverName) { - if (targetServers == null || targetServers.length == 0) // Targets all online servers + if (_targetServers == null || _targetServers.length == 0) // Targets all online servers return true; - for (String targetServer : targetServers) + for (String targetServer : _targetServers) { if (targetServer.equalsIgnoreCase(serverName)) { diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommandManager.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommandManager.java index 8bc85c3e0..361d7d501 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommandManager.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerCommandManager.java @@ -3,6 +3,7 @@ package mineplex.serverdata; import java.util.HashMap; import java.util.Map; +import mineplex.serverdata.transfers.TransferCommand; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; @@ -11,23 +12,30 @@ public class ServerCommandManager { // The singleton instance of ServerCommandManager - private static ServerCommandManager instance; + private static ServerCommandManager _instance; public final String SERVER_COMMANDS_CHANNEL = "commands.server"; private JedisPool _jedisPool; - private Map> _commandTypes; + private Map _commandTypes; + + private String _localServerName; + public void initializeServer(String serverName) { _localServerName = serverName; } + public boolean isServerInitialized() { return _localServerName != null; } /** * Private class constructor to prevent non-singleton instances. */ private ServerCommandManager() { - this._jedisPool = new JedisPool(new JedisPoolConfig(), ServerManager.DEFAULT_REDIS_HOST, + _jedisPool = new JedisPool(new JedisPoolConfig(), ServerManager.DEFAULT_REDIS_HOST, ServerManager.DEFAULT_REDIS_PORT); - this._commandTypes = new HashMap>(); + _commandTypes = new HashMap(); initialize(); + + // Register default command types + registerCommandType(TransferCommand.class); } /** @@ -92,14 +100,27 @@ public class ServerCommandManager */ public void handleCommand(String commandType, String serializedCommand) { + if (!isServerInitialized()) + { + // TODO: Log un-initialized server receiving command? + return; + } + if (_commandTypes.containsKey(commandType)) { - ServerCommand serverCommand = Utility.deserialize(serializedCommand, _commandTypes.get(commandType)); + Class commandClazz = _commandTypes.get(commandType).getCommandType(); + ServerCommand serverCommand = Utility.deserialize(serializedCommand, commandClazz); - //if (serverCommand.isTargetServer("THIS SERVER NAME HERE")) // TODO: Find server name ref - //{ + if (serverCommand.isTargetServer(_localServerName)) + { // TODO: Run synchronously? - serverCommand.run(); // Run the server command + CommandCallback callback = _commandTypes.get(commandType).getCallback(); + serverCommand.run(); // Run server command without callback + + if (callback != null) + { + callback.run(serverCommand); // Run callback + } //} } } @@ -108,12 +129,22 @@ public class ServerCommandManager * Register a new type of {@link ServerCommand}. * @param commandType - the {@link ServerCommand} type to register. */ - public void registerCommandType(String commandName, Class commandType) + public void registerCommandType(Class commandType, CommandCallback callback) { - if (!_commandTypes.containsKey(commandName)) + String commandName = commandType.toString(); + + if (_commandTypes.containsKey(commandName)) { - _commandTypes.put(commandName, commandType); + // Log overwriting of command type? } + + CommandType cmdType = new CommandType(commandType, callback); + _commandTypes.put(commandName, cmdType); + } + + public void registerCommandType(Class commandType) + { + registerCommandType(commandType, null); } /** @@ -121,11 +152,11 @@ public class ServerCommandManager */ public static ServerCommandManager getInstance() { - if (instance == null) + if (_instance == null) { - instance = new ServerCommandManager(); + _instance = new ServerCommandManager(); } - return instance; + return _instance; } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/portal/ServerTransfer.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/ServerTransfer.java similarity index 60% rename from Plugins/Mineplex.Core/src/mineplex/core/portal/ServerTransfer.java rename to Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/ServerTransfer.java index cdbcd82de..c0893814d 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/portal/ServerTransfer.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/ServerTransfer.java @@ -1,15 +1,15 @@ -package mineplex.core.portal; +package mineplex.serverdata.transfers; public class ServerTransfer { // The name of the player who is being transferred. - private String playerName; - public String getPlayerName() { return playerName; } + private String _playerName; + public String getPlayerName() { return _playerName; } // The name of the destination server in this ServerTransfer. - private String serverName; - public String getServerName() { return serverName; } + private String _serverName; + public String getServerName() { return _serverName; } /** * Class constructor @@ -18,7 +18,7 @@ public class ServerTransfer */ public ServerTransfer(String playerName, String serverName) { - this.playerName = playerName; - this.serverName = serverName; + _playerName = playerName; + _serverName = serverName; } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/portal/TransferCommand.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/TransferCommand.java similarity index 59% rename from Plugins/Mineplex.Core/src/mineplex/core/portal/TransferCommand.java rename to Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/TransferCommand.java index 928dd8819..bc74ca9fd 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/portal/TransferCommand.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/transfers/TransferCommand.java @@ -1,7 +1,4 @@ -package mineplex.core.portal; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; +package mineplex.serverdata.transfers; import mineplex.serverdata.ServerCommand; @@ -15,7 +12,8 @@ public class TransferCommand extends ServerCommand { // The ServerTransfer to be sent to another server for enactment - private ServerTransfer transfer; + private ServerTransfer _transfer; + public ServerTransfer getTransfer() { return _transfer; } /** * Class constructor @@ -23,17 +21,12 @@ public class TransferCommand extends ServerCommand */ public TransferCommand(ServerTransfer transfer) { - this.transfer = transfer; + _transfer = transfer; } @Override public void run() { - Player player = Bukkit.getPlayer(transfer.getPlayerName()); - - if (player != null && player.isOnline()) - { - Portal.getInstance().SendPlayerToServer(player, transfer.getServerName()); - } + // Utilitizes a callback functionality to seperate dependencies } }