diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/jsonchat/ChildJsonMessage.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/jsonchat/ChildJsonMessage.java index e6fdb1914..3cab17227 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/jsonchat/ChildJsonMessage.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/jsonchat/ChildJsonMessage.java @@ -20,7 +20,7 @@ public class ChildJsonMessage extends JsonMessage _parent = parent; } - + public ChildJsonMessage add(String text) { Builder.append("}, "); @@ -42,6 +42,38 @@ public class ChildJsonMessage extends JsonMessage return this; } + + @Override + public ChildJsonMessage italic() + { + super.italic(); + + return this; + } + + @Override + public ChildJsonMessage underlined() + { + super.underlined(); + + return this; + } + + @Override + public ChildJsonMessage strikethrough() + { + super.strikethrough(); + + return this; + } + + @Override + public ChildJsonMessage obfuscated() + { + super.obfuscated(); + + return this; + } @Override public ChildJsonMessage click(String action, String value) @@ -50,6 +82,14 @@ public class ChildJsonMessage extends JsonMessage return this; } + + @Override + public ChildJsonMessage click(ClickEvent event, String value) + { + super.click(event, value); + + return this; + } @Override public ChildJsonMessage hover(String action, String value) @@ -58,7 +98,15 @@ public class ChildJsonMessage extends JsonMessage return this; } - + + @Override + public ChildJsonMessage hover(HoverEvent event, String value) + { + super.hover(event, value); + + return this; + } + @Override public String toString() { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java b/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java index dd274ce22..b395667da 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/command/CommandBase.java @@ -39,7 +39,7 @@ public abstract class CommandBase implements ICom _aliases = Arrays.asList(aliases); } - + public Collection Aliases() { return _aliases; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesManager.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesManager.java index c69ab7bed..42a32410c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesManager.java @@ -131,6 +131,6 @@ public class PreferencesManager extends MiniDbClientPlugin @Override public String getQuery(int accountId, String uuid, String name) { - return "SELECT games, visibility, showChat, friendChat, privateMessaging, partyRequests, invisibility, forcefield, showMacReports, ignoreVelocity, pendingFriendRequests, friendDisplayInventoryUI FROM accountPreferences WHERE accountPreferences.uuid = '" + uuid + "' LIMIT 1;"; + return "SELECT games, visibility, showChat, friendChat, privateMessaging, partyRequests, invisibility, forcefield, showMacReports, ignoreVelocity, pendingFriendRequests, friendDisplayInventoryUI, showUserReports FROM accountPreferences WHERE accountPreferences.uuid = '" + uuid + "' LIMIT 1;"; } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java index 44852c23e..9f3997bff 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/PreferencesRepository.java @@ -15,9 +15,9 @@ import mineplex.core.database.column.ColumnVarChar; public class PreferencesRepository extends RepositoryBase { - //private static String CREATE_ACCOUNT_TABLE = "CREATE TABLE IF NOT EXISTS accountPreferences (id INT NOT NULL AUTO_INCREMENT, uuid VARCHAR(256), games BOOL NOT NULL DEFAULT 1, visibility BOOL NOT NULL DEFAULT 1, showChat BOOL NOT NULL DEFAULT 1, friendChat BOOL NOT NULL DEFAULT 1, privateMessaging BOOL NOT NULL DEFAULT 1, partyRequests BOOL NOT NULL DEFAULT 0, invisibility BOOL NOT NULL DEFAULT 0, forcefield BOOL NOT NULL DEFAULT 0, showMacReports BOOL NOT NULL DEFAULT 0, ignoreVelocity BOOL NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE INDEX uuid_index (uuid));"; + //private static String CREATE_ACCOUNT_TABLE = "CREATE TABLE IF NOT EXISTS accountPreferences (id INT NOT NULL AUTO_INCREMENT, uuid VARCHAR(256), games BOOL NOT NULL DEFAULT 1, visibility BOOL NOT NULL DEFAULT 1, showChat BOOL NOT NULL DEFAULT 1, friendChat BOOL NOT NULL DEFAULT 1, privateMessaging BOOL NOT NULL DEFAULT 1, partyRequests BOOL NOT NULL DEFAULT 0, invisibility BOOL NOT NULL DEFAULT 0, forcefield BOOL NOT NULL DEFAULT 0, showMacReports BOOL NOT NULL DEFAULT 0, ignoreVelocity BOOL NOT NULL DEFAULT 0, showUserReports BOOL NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE INDEX uuid_index (uuid));"; private static String INSERT_ACCOUNT = "INSERT INTO accountPreferences (uuid) VALUES (?) ON DUPLICATE KEY UPDATE uuid=uuid;"; - private static String UPDATE_ACCOUNT_PREFERENCES = "UPDATE accountPreferences SET games = ?, visibility = ?, showChat = ?, friendChat = ?, privateMessaging = ?, partyRequests = ?, invisibility = ?, forcefield = ?, showMacReports = ?, ignoreVelocity = ?, pendingFriendRequests = ?, friendDisplayInventoryUI = ? WHERE uuid=?;"; + private static String UPDATE_ACCOUNT_PREFERENCES = "UPDATE accountPreferences SET games = ?, visibility = ?, showChat = ?, friendChat = ?, privateMessaging = ?, partyRequests = ?, invisibility = ?, forcefield = ?, showMacReports = ?, ignoreVelocity = ?, pendingFriendRequests = ?, friendDisplayInventoryUI = ?, showUserReports = ? WHERE uuid=?;"; public PreferencesRepository(JavaPlugin plugin) { @@ -57,7 +57,8 @@ public class PreferencesRepository extends RepositoryBase preparedStatement.setBoolean(10, entry.getValue().IgnoreVelocity); preparedStatement.setBoolean(11, entry.getValue().PendingFriendRequests); preparedStatement.setBoolean(12, entry.getValue().friendDisplayInventoryUI); - preparedStatement.setString(13, entry.getKey()); + preparedStatement.setBoolean(13, entry.getValue().ShowUserReports); + preparedStatement.setString(14, entry.getKey()); preparedStatement.addBatch(); } @@ -83,7 +84,8 @@ public class PreferencesRepository extends RepositoryBase preparedStatement.setBoolean(10, entry.getValue().IgnoreVelocity); preparedStatement.setBoolean(11, entry.getValue().PendingFriendRequests); preparedStatement.setBoolean(12, entry.getValue().friendDisplayInventoryUI); - preparedStatement.setString(13, entry.getKey()); + preparedStatement.setBoolean(13, entry.getValue().ShowUserReports); + preparedStatement.setString(14, entry.getKey()); preparedStatement.execute(); } @@ -99,7 +101,7 @@ public class PreferencesRepository extends RepositoryBase public UserPreferences loadClientInformation(final ResultSet resultSet) throws SQLException { final UserPreferences preferences = new UserPreferences(); - + if (resultSet.next()) { preferences.HubGames = resultSet.getBoolean(1); @@ -114,6 +116,7 @@ public class PreferencesRepository extends RepositoryBase preferences.IgnoreVelocity = resultSet.getBoolean(10); preferences.PendingFriendRequests = resultSet.getBoolean(11); preferences.friendDisplayInventoryUI = resultSet.getBoolean(12); + preferences.ShowUserReports = resultSet.getBoolean(13); } return preferences; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/UserPreferences.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/UserPreferences.java index e52e7d249..6b9c5a8eb 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/UserPreferences.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/UserPreferences.java @@ -12,6 +12,7 @@ public class UserPreferences public boolean Invisibility = false; public boolean HubForcefield = false; public boolean ShowMacReports = false; + public boolean ShowUserReports = false; public boolean IgnoreVelocity = false; public boolean PendingFriendRequests = true; public boolean friendDisplayInventoryUI = true; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/PreferencesPage.java b/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/PreferencesPage.java index b051b051c..89b6dabf8 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/PreferencesPage.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/preferences/ui/PreferencesPage.java @@ -26,6 +26,7 @@ public class PreferencesPage extends ShopPageBase _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) + // Set of player names and the reason they reported this player + private Map _reportReasons; + public Map getReportReasons() { return _reportReasons; } + public Set getReporters() { return _reportReasons.keySet(); } + public void addReporter(String reporter, String reason) { _reportReasons.put(reporter, reason); } + + private String _handler = null; + public void setHandler(String handler) { _handler = handler; } + public String getHandler() { return _handler; } + + private ReportCategory _category; + public ReportCategory getCategory() { return _category; } + + public Report(int reportId, String playerName, String serverName, ReportCategory category) { _reportId = reportId; _playerName = playerName; _serverName = serverName; - _reporters = new HashSet(); + _reportReasons = new HashMap<>(); + _category = category; } @Override diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportCategory.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportCategory.java new file mode 100644 index 000000000..1aad207a1 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportCategory.java @@ -0,0 +1,78 @@ +package mineplex.core.report; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.Material; + +import mineplex.core.common.util.C; + +/** + * Contains all the reasons a player can be reported for. + * @author iKeirNez + */ +public enum ReportCategory +{ + + // descriptions borrowed from PunishPage + HACKING(0, 3, Material.IRON_SWORD, C.cRedB + "Hacking", "X-ray, Forcefield, Speed, Fly etc"), + CHAT_ABUSE(1, 1, Material.BOOK_AND_QUILL, C.cDBlueB + "Chat Abuse", "Verbal Abuse, Spam, Harassment, Trolling, etc"); + + private int _id; + private int _notifyThreshold; + private Material _displayMaterial; + private String _title; + private List _lore; + + ReportCategory(int id, int notifyThreshold, Material displayMaterial, String title, String... lore) + { + _id = id; + _notifyThreshold = notifyThreshold; + _displayMaterial = displayMaterial; + _title = title; + _lore = new ArrayList<>(); + + // prefix are lore lines + for (String loreLine : lore) { + _lore.add(C.cGray + loreLine); + } + } + + public int getId() + { + return _id; + } + + public int getNotifyThreshold() + { + return _notifyThreshold; + } + + public Material getItemMaterial() + { + return _displayMaterial; + } + + public String getTitle() + { + return _title; + } + + public List getDescription() + { + return _lore; + } + + public static ReportCategory fromId(int id) + { + for (ReportCategory category : values()) + { + if (category.getId() == id) + { + return category; + } + } + + return null; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportHandlerMessageTask.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportHandlerMessageTask.java new file mode 100644 index 000000000..60e8aecad --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportHandlerMessageTask.java @@ -0,0 +1,71 @@ +package mineplex.core.report; + +import java.util.Map; + +import org.bukkit.scheduler.BukkitRunnable; + +import mineplex.core.common.jsonchat.JsonMessage; +import mineplex.core.common.util.C; +import mineplex.core.report.command.ReportHandlerNotification; +import org.apache.commons.lang3.StringUtils; + +/** + * Displays a message containing up-to-date details of a report to it's handler. + * @author iKeirNez + */ +public class ReportHandlerMessageTask extends BukkitRunnable +{ + private static final String BORDER = C.cAqua + "------------------------------------"; + + private ReportManager _reportManager; + private Report _report; + + public ReportHandlerMessageTask(ReportManager reportManager, Report report) + { + _reportManager = reportManager; + _report = report; + } + + @Override + public void run() + { + int reportId = _report.getReportId(); + + if (_reportManager.isActiveReport(reportId)) + { + Report report = _reportManager.getReport(reportId); + JsonMessage jsonMessage = new JsonMessage(BORDER + + "\n" + + C.cAqua + "Reviewing Ticket " + C.cGold + "#" + reportId + + "\n\n" + + StringUtils.join(getReportReasons(), "\n") + + "\n\n" + + "Suspect: " + _report.getPlayerName() + + "\n" + + BORDER); + // TODO make clickable + + new ReportHandlerNotification(report, jsonMessage).publish(); + } + else + { + // report has been closed, so this task should be cancelled + cancel(); + } + } + + public String[] getReportReasons() + { + Map reportReasons = _report.getReportReasons(); + String[] output = new String[reportReasons.size()]; + int count = 0; + + for (Map.Entry entry : reportReasons.entrySet()) + { + // triple backslashes so this translates to valid JSON + output[count++] = "\\\"" + entry.getValue() + "\\\" - " + entry.getKey(); + } + + return output; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java index a6f7fd59b..bbb32b7f2 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java @@ -6,16 +6,25 @@ import java.util.Map.Entry; import mineplex.core.account.CoreClient; import mineplex.core.command.CommandCenter; -import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.Rank; +import mineplex.core.common.jsonchat.ClickEvent; +import mineplex.core.common.jsonchat.JsonMessage; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; import mineplex.core.portal.Portal; +import mineplex.core.preferences.PreferencesManager; +import mineplex.core.report.command.ReportHandlerNotification; +import mineplex.core.report.command.ReportNotificationCallback; import mineplex.core.report.command.ReportNotification; import mineplex.serverdata.Region; import mineplex.serverdata.Utility; +import mineplex.serverdata.commands.ServerCommandManager; import mineplex.serverdata.data.DataRepository; import mineplex.serverdata.redis.RedisDataRepository; -import org.bukkit.ChatColor; import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.plugin.java.JavaPlugin; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; @@ -28,163 +37,200 @@ import redis.clients.jedis.exceptions.JedisConnectionException; * */ public class ReportManager { - - private static ReportManager instance; - + + private static final String NAME = "Report"; + + private JavaPlugin _javaPlugin; + private PreferencesManager _preferencesManager; + private String _serverName; + // Holds active/open reports in a synchronized database. - private DataRepository reportRepository; - - private DataRepository reportProfiles; - + private DataRepository _reportRepository; + + private DataRepository _reportProfiles; + // Stores/logs closed tickets, and various reporter/staff actions. - private ReportRepository reportSqlRepository; - + 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() + private Map _activeReports; + + public ReportManager(JavaPlugin javaPlugin, PreferencesManager preferencesManager, String serverName) { - 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.getPluginInstance(), "CONNECTION STRING HERE"); - reportSqlRepository.initialize(); + _javaPlugin = javaPlugin; + _preferencesManager = preferencesManager; + _serverName = serverName; + _reportRepository = new RedisDataRepository(Region.ALL, Report.class, "reports"); + _reportProfiles = new RedisDataRepository(Region.ALL, ReportProfile.class, "reportprofiles"); + _activeReports = new HashMap(); + _reportSqlRepository = new ReportRepository(javaPlugin); + _reportSqlRepository.initialize(); + + ReportNotificationCallback callback = new ReportNotificationCallback(this); + ServerCommandManager.getInstance().registerCommandType("ReportNotification", ReportNotification.class, callback); + ServerCommandManager.getInstance().registerCommandType("ReportHandlerNotification", ReportHandlerNotification.class, callback); } - - 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) + ReportResult result) { if (isActiveReport(reportId)) { Report report = getReport(reportId); - reportRepository.removeElement(String.valueOf(reportId)); // Remove report from redis database + _reportRepository.removeElement(String.valueOf(reportId)); // Remove report from redis database removeActiveReport(reportId); - - int closerId = getPlayerAccount(reportCloser).getAccountId(); - String playerName = getReport(reportId).getPlayerName(); + + int closerId = reportCloser != null ? getPlayerAccount(reportCloser).getAccountId() : -1; + String playerName = report.getPlayerName(); int playerId = getPlayerAccount(playerName).getAccountId(); - String server = null; // TODO: Get current server name - reportSqlRepository.logReport(reportId, playerId, server, closerId, result, reason); - + _reportSqlRepository.logReport(reportId, playerId, _serverName, 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); + _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())); + sendStaffNotification( + F.main(getReportPrefix(reportId), String.format("%s closed the report for: %s (%s).", + reportCloser.getName(), reason, result.toDisplayMessage() + C.mBody))); + + CommandCenter.Instance.OnPlayerCommandPreprocess( + new PlayerCommandPreprocessEvent(reportCloser, "/punish " + playerName + " " + reason)); } } - } - + public void handleReport(int reportId, Player reportHandler) { - if (reportRepository.elementExists(String.valueOf(reportId))) + 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 + + if (report.getHandler() != null) { + reportHandler.sendMessage(F.main(getReportPrefix(reportId), String.format("%s is already handling this report.", report.getHandler()))); + } else { + String handlerName = reportHandler.getName(); + report.setHandler(handlerName); + _reportRepository.addElement(report); // update existing value in Redis + + sendStaffNotification(F.main(getReportPrefix(reportId), String.format("%s is handling this report.", handlerName))); + Portal.transferPlayer(reportHandler.getName(), report.getServerName()); + + // Show user details of the report every x seconds + new ReportHandlerMessageTask(this, report).runTaskTimer(_javaPlugin, 20L * 10, 20L * 10); + + int handlerId = getPlayerAccount(reportHandler).getAccountId(); + _reportSqlRepository.logReportHandling(reportId, handlerId); // Log handling into sql database + } } } - - public void reportPlayer(Player reporter, Player reportedPlayer, String reason) + + public Report reportPlayer(Player reporter, Player reportedPlayer, ReportCategory category, 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 report = getReport(reportId); + + if (reportId != -1 && report.getCategory() == category) { - int reportId = getActiveReport(reportedPlayer.getName()); - report = getReport(reportId); - report.addReporter(reporter.getName()); + report.addReporter(reporter.getName(), reason); } 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); + reportId = generateReportId(); + report = new Report(reportId, reportedPlayer.getName(), _serverName, category); + report.addReporter(reporter.getName(), reason); + _activeReports.put(reportedPlayer.getName().toLowerCase(), report.getReportId()); } - - if (report != null) + + _reportRepository.addElement(report); // add (or update) the report to Redis + + // only start notifying staff when + if (report.getReporters().size() >= category.getNotifyThreshold()) { - // [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); - } + String prefix = getReportPrefix(reportId); + + // Report #2 > iKeirNez - Flying around in arcade game (Hacking) + // Report #2 > Reported by Chiss. + // Report #2 > 5 total reporter(s). + JsonMessage message = new JsonMessage(F.main(prefix, String.format("%s - %s (%s)", + C.cGoldB + report.getPlayerName() + C.mBody, + reason, C.cGoldB + report.getCategory().getTitle() + C.mBody)) + + "\n" + + F.main(prefix, String.format("Reported by %s.", reporter.getName())) + + "\n" + + F.main(prefix, String.format("%d total reporter(s).", report.getReporters().size()))); + + if (report.getHandler() == null) + { + // this needs to be 'equals' otherwise we get errors when attempting to send this (due to incomplete JSON) + message = message.extra("\n" + F.main(getReportPrefix(reportId), "Click to handle this ticket.")) + .click(ClickEvent.RUN_COMMAND, "/reporthandle " + reportId); + + sendStaffNotification(message); + } + else + { + sendHandlerNotification(report, message); + } + } + + _reportSqlRepository.logReportSending(report.getReportId(), reporterId, category, reason); + return report; } + + return null; } - - public void onPlayerQuit(Player player) + + public void onPlayerJoin(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())); + Report report = getReport(reportId); + sendHandlerNotification(report, F.main(getReportPrefix(reportId), String.format("%s has re-joined the game.", player.getName()))); } } - + + public void onPlayerQuit(Player player) + { + if (hasActiveReport(player)) + { + int reportId = getActiveReport(player.getName()); + Report report = getReport(reportId); + sendHandlerNotification(report, F.main(getReportPrefix(reportId), String.format("%s has left the game.", player.getName()))); + } + } + public ReportProfile getReportProfile(String playerName) { - ReportProfile profile = reportProfiles.getElement(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); + _reportProfiles.addElement(profile); } - + /** * @return a uniquely generated report id. */ @@ -193,7 +239,7 @@ public class ReportManager { JedisPool pool = Utility.getPool(true); Jedis jedis = pool.getResource(); long uniqueReportId = -1; - + try { uniqueReportId = jedis.incr("reports.unique-id"); @@ -211,52 +257,96 @@ public class ReportManager { pool.returnResource(jedis); } } - + return (int) uniqueReportId; } - + public Report getReport(int reportId) { - return reportRepository.getElement(String.valueOf(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; + boolean isStaff = CommandCenter.Instance.GetClientManager().Get(player).GetRank().has(Rank.MODERATOR); + boolean hasReportNotifications = _preferencesManager.Get(player).ShowUserReports; + return isStaff && hasReportNotifications; } - + /** * Send a network-wide {@link ReportNotification} to all online staff. + * * @param message - the report notification message to send. */ - public void sendReportNotification(String message) + public void sendStaffNotification(JsonMessage message) { ReportNotification reportNotification = new ReportNotification(message); reportNotification.publish(); } - + + /** + * Send a network-wide {@link ReportNotification} to all online staff. + * + * @param message - the report notification message to send. + */ + public void sendStaffNotification(String message) + { + ReportNotification reportNotification = new ReportNotification(message); + reportNotification.publish(); + } + + /** + * Send to the handler of a {@link Report}, regardless of whether or not the handler is currently on this server instance. + * If there is no handler for a report, it will be sent to all staff instead. + * + * @param report the report of which a message should be sent ot it's handler + * @param jsonMessage the report notification message to send + */ + public void sendHandlerNotification(Report report, JsonMessage jsonMessage) + { + if (report.getHandler() != null) + { + ReportHandlerNotification reportHandlerNotification = new ReportHandlerNotification(report, jsonMessage); + reportHandlerNotification.publish(); + } + else + { + // If there is no report handler, send it to all staff + sendStaffNotification(jsonMessage); + } + } + + /** + * Send to the handler of a {@link Report}, regardless of whether or not the handler is currently on this server instance. + * If there is no handler for a report, it will be sent to all staff instead. + * + * @param report the report of which a message should be sent ot it's handler + * @param message the report notification message to send + */ + public void sendHandlerNotification(Report report, String message) + { + sendHandlerNotification(report, new JsonMessage(message)); + } + /** * @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 @@ -264,56 +354,49 @@ public class ReportManager { */ public int getActiveReport(String playerName) { - if (activeReports.containsKey(playerName.toLowerCase())) + if (_activeReports.containsKey(playerName.toLowerCase())) { - return activeReports.get(playerName.toLowerCase()); + return _activeReports.get(playerName.toLowerCase()); } - + return -1; } - + + // TODO this and related methods only function on the server where the report was created public boolean hasActiveReport(Player player) { return getActiveReport(player.getName()) != -1; } - + public boolean isActiveReport(int reportId) { - for (Entry activeReport : activeReports.entrySet()) + for (Entry activeReport : _activeReports.entrySet()) { if (activeReport.getValue() == reportId) { return true; } } - + return false; } - + public boolean removeActiveReport(int reportId) { - for (Entry activeReport : activeReports.entrySet()) + for (Entry activeReport : _activeReports.entrySet()) { if (activeReport.getValue() == reportId) { - activeReports.remove(activeReport.getKey()); + _activeReports.remove(activeReport.getKey()); return true; } } - + return false; } - - /** - * @return the singleton instance of {@link ReportManager}. - */ - public static ReportManager getInstance() + + private static String getReportPrefix(int reportId) { - if (instance == null) - { - instance = new ReportManager(); - } - - return instance; + return NAME + " #" + reportId; } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java index b03857fc8..ea0d0d54f 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportPlugin.java @@ -5,21 +5,27 @@ import mineplex.core.report.command.ReportCloseCommand; import mineplex.core.report.command.ReportCommand; import mineplex.core.report.command.ReportHandleCommand; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; public class ReportPlugin extends MiniPlugin { + private final ReportManager _reportManager; - private static JavaPlugin instance; - public static JavaPlugin getPluginInstance() { return instance; } - - public ReportPlugin(JavaPlugin plugin, String serverName) + public ReportPlugin(JavaPlugin plugin, ReportManager reportManager) { - super("ReportPlugin", plugin); - - instance = plugin; + super("Report", plugin); + + _reportManager = reportManager; } - + + public ReportManager getReportManager() + { + return _reportManager; + } + @Override public void addCommands() { @@ -28,4 +34,16 @@ public class ReportPlugin extends MiniPlugin addCommand(new ReportCloseCommand(this)); //AddCommand(new ReportDebugCommand(this)); } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) + { + _reportManager.onPlayerJoin(e.getPlayer()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) + { + _reportManager.onPlayerQuit(e.getPlayer()); + } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java index 1f70102ce..c3056dec8 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportProfile.java @@ -6,16 +6,20 @@ 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; } - + public int getTotalReports() { return _totalReports; } + + private int _acceptedReports; + public int getAcceptedReports() { return _acceptedReports; } + + private int _deniedReports; + public int getDeniedReports() { return _deniedReports; } + + private int _abuseReports; + public int getAbuseReports() { return _abuseReports; } + private boolean _banned; public ReportProfile(String playerName, int playerId) @@ -23,8 +27,9 @@ public class ReportProfile implements Data _playerName = playerName; _playerId = playerId; _totalReports = 0; - _successfulReports = 0; - _reputation = 0; + _acceptedReports = 0; + _deniedReports = 0; + _abuseReports = 0; _banned = false; } @@ -46,16 +51,19 @@ public class ReportProfile implements Data public void onReportClose(ReportResult result) { _totalReports++; - - if (result == ReportResult.MUTED || result == ReportResult.BANNED) + + switch (result) { - _successfulReports++; - _reputation++; - } - else if (result == ReportResult.ABUSE) - { - _reputation = -1; - _banned = true; + default: break; + case ACCEPTED: + _acceptedReports++; + break; + case DENIED: + _deniedReports++; + break; + case ABUSIVE: + _abuseReports++; + break; } } } \ 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 index cbae2678c..889c1f2ac 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java @@ -1,18 +1,11 @@ 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.DBPool; +import mineplex.core.database.DatabaseRunnable; import mineplex.core.database.RepositoryBase; -import mineplex.core.database.ResultSetCallable; +import mineplex.core.database.column.ColumnByte; import mineplex.core.database.column.ColumnInt; import mineplex.core.database.column.ColumnVarChar; -import mineplex.core.preferences.UserPreferences; import org.bukkit.plugin.java.JavaPlugin; @@ -30,16 +23,16 @@ 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 CREATE_TICKET_TABLE = "CREATE TABLE IF NOT EXISTS reportTickets (reportId INT NOT NULL, eventDate LONG, playerId INT NOT NULL, server VARCHAR(50), closerId INT NOT NULL, result VARCHAR(25), reason VARCHAR(100), PRIMARY KEY (reportId), FOREIGN KEY (playerId) REFERENCES accounts(id), FOREIGN KEY (closerId) REFERENCES accounts(id));"; + 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), FOREIGN KEY (reportId) REFERENCES reportTickets(reportId), FOREIGN KEY (handlerId) REFERENCES accounts(id) );"; + 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, category TINYINT, reason VARCHAR(100), PRIMARY KEY (id), FOREIGN KEY (reportId) REFERENCES reportTickets(reportId), FOREIGN KEY (reporterId) REFERENCES accounts(id));"; 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(), ?, ?, ?);"; + private static String INSERT_SENDER = "INSERT INTO reportSenders (eventDate, reportId, reporterId, category, reason) VALUES(now(), ?, ?, ?, ?);"; - public ReportRepository(JavaPlugin plugin, String connectionString) + public ReportRepository(JavaPlugin plugin) { super(plugin, DBPool.ACCOUNT); } @@ -47,11 +40,10 @@ This will be used to determine if staff are handling @Override protected void initialize() { - /* - executeUpdate(CREATE_TICKET_TABLE); - executeUpdate(CREATE_HANDLER_TABLE); - executeUpdate(CREATE_REPORTERS_TABLE); - */ + // disabled until approved + // executeUpdate(CREATE_TICKET_TABLE); + // executeUpdate(CREATE_HANDLER_TABLE); + // executeUpdate(CREATE_REPORTERS_TABLE); } @Override @@ -60,22 +52,42 @@ This will be used to determine if staff are handling } - public void logReportHandling(int reportId, int handlerId) + public void logReportHandling(final int reportId, final int handlerId) { - executeUpdate(INSERT_HANDLER, new ColumnInt("reportId", reportId), new ColumnInt("handlerId", handlerId)); + handleDatabaseCall(new DatabaseRunnable(new Runnable() + { + @Override + public void run() + { + executeUpdate(INSERT_HANDLER, new ColumnInt("reportId", reportId), new ColumnInt("handlerId", handlerId)); + } + }), "Error logging report " + reportId + " as being handled by user " + handlerId + "."); } - public void logReportSending(int reportId, int reporterId, String reason) + public void logReportSending(final int reportId, final int reporterId, final ReportCategory category, final String reason) { - executeUpdate(INSERT_SENDER, new ColumnInt("reportId", reportId), new ColumnInt("reporterId", reporterId), - new ColumnVarChar("reason", 100, reason)); + handleDatabaseCall(new DatabaseRunnable(new Runnable() + { + @Override + public void run() + { + executeUpdate(INSERT_SENDER, new ColumnInt("reportId", reportId), new ColumnInt("reporterId", reporterId), + new ColumnByte("type", (byte) category.getId()), new ColumnVarChar("reason", 100, reason)); + } + }), "Error logging report " + reportId + " by user " + reporterId + "."); } - public void logReport(int reportId, int playerId, String server, int closerId, ReportResult result, String reason) + public void logReport(final int reportId, final int playerId, final String server, final int closerId, final ReportResult result, final 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)); + handleDatabaseCall(new DatabaseRunnable(new Runnable() + { + @Override + public void run() + { + 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)); + } + }), "Error logging result for report " + reportId + "."); } - } \ 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 index fc2f3abcf..c5ba5df0c 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportResult.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportResult.java @@ -4,22 +4,45 @@ 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) + ACCEPTED(ChatColor.GREEN, "Accept Report (Punish Player)", "Accepted (Player Received Punishment)"), + DENIED(ChatColor.YELLOW, "Deny Report", "Denied"), + ABUSIVE(ChatColor.RED, "Mark Abusive Report", "Abusive Report"); + + private ChatColor _color; + private String _actionMessage; + private String _resultMessage; + private String[] _lore; + + ReportResult(ChatColor color, String actionMessage, String resultMessage, String... lore) { - this.color = color; - this.displayMessage = displayMessage; + _color = color; + _actionMessage = actionMessage; + _resultMessage = resultMessage; + _lore = lore; } - + + public ChatColor getColor() + { + return _color; + } + + public String getActionMessage() + { + return _actionMessage; + } + + public String getResultMessage() + { + return _resultMessage; + } + + public String[] getLore() + { + return _lore; + } + public String toDisplayMessage() { - return color + displayMessage; + return _color + _resultMessage; } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java index 03ce14e9a..4bd99a4e9 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCloseCommand.java @@ -3,12 +3,11 @@ 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 mineplex.core.report.ui.ReportResultPage; import org.bukkit.entity.Player; @@ -32,8 +31,16 @@ public class ReportCloseCommand extends CommandBase { int reportId = Integer.parseInt(args[0]); String reason = F.combine(args, 1, null, false); - - ReportManager.getInstance().closeReport(reportId, player, reason); + + if (Plugin.getReportManager().isActiveReport(reportId)) + { + ReportResultPage reportResultPage = new ReportResultPage(Plugin, reportId, player, reason); + reportResultPage.openInventory(); // report is closed when player selects the result + } + else + { + UtilPlayer.message(player, F.main(Plugin.getName(), C.cRed + "That report either does not exist or has been closed.")); + } } } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java index 9faf41139..b4a0f22f3 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportCommand.java @@ -3,12 +3,10 @@ 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 mineplex.core.report.ui.ReportCategoryPage; import org.bukkit.entity.Player; @@ -36,7 +34,7 @@ public class ReportCommand extends CommandBase if (reportedPlayer != null) { - ReportManager.getInstance().reportPlayer(player, reportedPlayer, reason); + new ReportCategoryPage(Plugin, player, reportedPlayer, reason).openInventory(); } else { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java index 3b037a0a2..a7d6ab95a 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandleCommand.java @@ -3,10 +3,8 @@ 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; @@ -31,8 +29,8 @@ public class ReportHandleCommand extends CommandBase else { int reportId = Integer.parseInt(args[0]); - - ReportManager.getInstance().handleReport(reportId, player); + + Plugin.getReportManager().handleReport(reportId, player); } } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandlerNotification.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandlerNotification.java new file mode 100644 index 000000000..585d85341 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportHandlerNotification.java @@ -0,0 +1,43 @@ +package mineplex.core.report.command; + +import mineplex.core.common.jsonchat.JsonMessage; +import mineplex.core.report.Report; + +/** + * A message regarding a report which is sent only to the player handling the report. + * @author iKeirNez + */ +public class ReportHandlerNotification extends ReportNotification +{ + private int _reportId; + private String _server; // the server the incident took place on + + public ReportHandlerNotification(Report report, String notification) + { + this(report, new JsonMessage(notification)); + } + + public ReportHandlerNotification(Report report, JsonMessage notification) + { + super(notification); + + if (report.getHandler() == null) + { + throw new IllegalStateException("Report has no handler."); + } + + _reportId = report.getReportId(); + _server = report.getServerName(); + setTargetServers(_server); + } + + public int getReportId() + { + return _reportId; + } + + public String getServer() + { + return _server; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java index 7d9d0153a..ca2d7814a 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotification.java @@ -1,31 +1,33 @@ package mineplex.core.report.command; -import org.bukkit.entity.Player; - -import mineplex.core.common.util.UtilServer; -import mineplex.core.report.ReportManager; +import mineplex.core.common.jsonchat.JsonMessage; import mineplex.serverdata.commands.ServerCommand; +/** + * A message regarding a report which should be sent to all moderators with report notifications enabled. + */ public class ReportNotification extends ServerCommand { - - // TODO: Encode in JSON-interactive chat message - private String notification; - + private String _notification; // in json format + public ReportNotification(String notification) { - super(); // Send to all servers + this(new JsonMessage(notification)); } - + + public ReportNotification(JsonMessage notification) + { + super(); // Send to all servers + _notification = notification.toString(); + } + + public String getNotification() + { + return _notification; + } + public void run() { - // Message all players that can receive report notifications. - for (Player player : UtilServer.getPlayers()) - { - if (ReportManager.getInstance().hasReportNotifications(player)) - { - player.sendMessage(notification); - } - } + // Utilitizes a callback functionality to seperate dependencies } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotificationCallback.java b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotificationCallback.java new file mode 100644 index 000000000..ca4e25bbb --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/command/ReportNotificationCallback.java @@ -0,0 +1,69 @@ +package mineplex.core.report.command; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; + +import mineplex.core.common.util.UtilServer; +import mineplex.core.report.Report; +import mineplex.core.report.ReportManager; +import mineplex.serverdata.commands.CommandCallback; +import mineplex.serverdata.commands.ServerCommand; + +/** + * Handles receiving of report notifications. + * @author iKeirNez + */ +public class ReportNotificationCallback implements CommandCallback +{ + private ReportManager _reportManager; + + public ReportNotificationCallback(ReportManager reportManager) + { + _reportManager = reportManager; + } + + @Override + public void run(ServerCommand command) + { + if (command instanceof ReportHandlerNotification) + { + ReportHandlerNotification reportNotification = (ReportHandlerNotification) command; + Report report = _reportManager.getReport(reportNotification.getReportId()); + + if (report != null) + { + String handlerName = report.getHandler(); + + if (handlerName != null) + { + Player handler = Bukkit.getPlayerExact(handlerName); + + if (handler != null) + { + sendRawMessage(handler, reportNotification.getNotification()); + } + } + } + } + else if (command instanceof ReportNotification) + { + ReportNotification reportNotification = (ReportNotification) command; + + // Message all players that can receive report notifications. + for (Player player : UtilServer.getPlayers()) + { + if (_reportManager.hasReportNotifications(player)) + { + sendRawMessage(player, reportNotification.getNotification()); + } + } + } + } + + private void sendRawMessage(Player player, String rawMessage) + { + Server server = UtilServer.getServer(); + server.dispatchCommand(server.getConsoleSender(), "tellraw " + player.getName() + " " + rawMessage); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryButton.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryButton.java new file mode 100644 index 000000000..1067fc08f --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryButton.java @@ -0,0 +1,35 @@ +package mineplex.core.report.ui; + +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.meta.ItemMeta; + +import mineplex.core.gui.SimpleGuiItem; +import mineplex.core.report.ReportCategory; + +/** + * Represents a clickable button in a {@link ReportCategoryPage} which determines the type of infraction a player has committed. + * @author iKeirNez + */ +public class ReportCategoryButton extends SimpleGuiItem +{ + private ReportCategoryPage _reportCategoryPage; + private ReportCategory _category; + + public ReportCategoryButton(ReportCategoryPage reportCategoryPage, ReportCategory category) { + super(category.getItemMaterial(), 1, (short) 0); + + ItemMeta itemMeta = getItemMeta(); + itemMeta.setDisplayName(category.getTitle()); + itemMeta.setLore(category.getDescription()); + setItemMeta(itemMeta); + + this._reportCategoryPage = reportCategoryPage; + this._category = category; + } + + @Override + public void click(ClickType clickType) + { + _reportCategoryPage.addReport(_category); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryPage.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryPage.java new file mode 100644 index 000000000..fe3bdf26d --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportCategoryPage.java @@ -0,0 +1,68 @@ +package mineplex.core.report.ui; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; + +import mineplex.core.common.util.C; +import mineplex.core.gui.SimpleGui; +import mineplex.core.report.ReportCategory; +import mineplex.core.report.Report; +import mineplex.core.report.ReportPlugin; + +/** + * User interface shown to a player when reporting another player. + * @author iKeirNez + */ +public class ReportCategoryPage extends SimpleGui +{ + private static final Map CATEGORY_SLOTS = Collections.unmodifiableMap(new HashMap() + {{ + int rowStartSlot = 9 * 2; // end of row 2 + put(rowStartSlot + 3, ReportCategory.HACKING); + put(rowStartSlot + 5, ReportCategory.CHAT_ABUSE); + }}); + + private ReportPlugin _reportPlugin; + private Player _reportee; + private Player _offender; + private String _reason; + + public ReportCategoryPage(ReportPlugin reportPlugin, Player reportee, Player offender, String reason) + { + super(reportPlugin.getPlugin(), reportee, "Report " + offender.getName(), 9 * 5); + + this._reportPlugin = reportPlugin; + this._reportee = reportee; + this._offender = offender; + this._reason = reason; + + buildPage(); + } + + private void buildPage() + { + for (Map.Entry entry : CATEGORY_SLOTS.entrySet()) + { + ReportCategory category = entry.getValue(); + setItem(entry.getKey(), new ReportCategoryButton(this, category)); + } + } + + public void addReport(ReportCategory category) + { + Report report = _reportPlugin.getReportManager().reportPlayer(_reportee, _offender, category, _reason); + _reportee.closeInventory(); + unregisterListener(); + _reportee.sendMessage(C.cGreen + "Report sent successfully (" + C.cGold + "#" + report.getReportId() + C.cGreen + ")."); + } + + public void unregisterListener() + { + HandlerList.unregisterAll(this); + } + +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultButton.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultButton.java new file mode 100644 index 000000000..4a28efe14 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultButton.java @@ -0,0 +1,49 @@ +package mineplex.core.report.ui; + +import java.util.List; + +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import mineplex.core.gui.SimpleGuiItem; +import mineplex.core.report.ReportResult; + +/** + * Represents a button which can be clicked to determine the result of a report. + * @author iKeirNez + */ +public class ReportResultButton extends SimpleGuiItem +{ + private ReportResultPage _reportResultPage; + private ReportResult _result; + + public ReportResultButton(ReportResultPage reportResultPage, ReportResult result, ItemStack displayItem) + { + super(displayItem); + _reportResultPage = reportResultPage; + _result = result; + } + + @Override + public void setup() + { + // replace all occurrences of "%suspect%" in the lore with the actual name + ItemMeta itemMeta = getItemMeta(); + List lore = itemMeta.getLore(); + + for (int i = 0; i < lore.size(); i++) + { + lore.set(i, lore.get(i).replace("%suspect%", _reportResultPage.getPlayer().getName())); + } + + itemMeta.setLore(lore); + setItemMeta(itemMeta); + } + + @Override + public void click(ClickType clickType) + { + _reportResultPage.setResult(_result); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultPage.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultPage.java new file mode 100644 index 000000000..176445f96 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ui/ReportResultPage.java @@ -0,0 +1,75 @@ +package mineplex.core.report.ui; + +import org.bukkit.Color; +import org.bukkit.DyeColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; + +import mineplex.core.common.util.C; +import mineplex.core.gui.SimpleGui; +import mineplex.core.itemstack.ItemBuilder; +import mineplex.core.report.ReportManager; +import mineplex.core.report.ReportPlugin; +import mineplex.core.report.ReportResult; + +/** + * User interface shown to a moderator when closing a report to determine the result of the report. + * @author iKeirNez + */ +public class ReportResultPage extends SimpleGui +{ + private static final ItemStack ITEM_ACCEPT = new ItemBuilder(Material.WOOL) + .setData(DyeColor.GREEN.getData()) + .setTitle(C.cGreen + "Accept Report") + .addLore("%suspect% is cheating without a doubt.") + .build(); + + private static final ItemStack ITEM_DENY = new ItemBuilder(Material.WOOL) + .setData(DyeColor.YELLOW.getData()) + .setTitle(C.cYellow + "Deny Report") + .addLore("There is not enough evidence against %suspect%.") + .build(); + + private static final ItemStack ITEM_ABUSE = new ItemBuilder(Material.WOOL) + .setData(DyeColor.RED.getData()) + .setTitle(C.cRed + "Flag Abuse") + .addLore("The reporter(s) were abusing the report system.") + .build(); + + private ReportManager _reportManager; + private int _reportId; + private Player _reportCloser; + private String _reason; + + public ReportResultPage(ReportPlugin reportPlugin, int reportId, Player reportCloser, String reason) + { + super(reportPlugin.getPlugin(), reportCloser, "Report Result", 9 * 3); + _reportManager = reportPlugin.getReportManager(); + _reportId = reportId; + _reportCloser = reportCloser; + _reason = reason; + + buildPage(); + } + + private void buildPage() + { + setItem(11, new ReportResultButton(this, ReportResult.ACCEPTED, ITEM_ACCEPT)); + setItem(13, new ReportResultButton(this, ReportResult.DENIED, ITEM_DENY)); + setItem(15, new ReportResultButton(this, ReportResult.ABUSIVE, ITEM_ABUSE)); + } + + public void setResult(ReportResult result) + { + _reportCloser.closeInventory(); + unregisterListener(); + _reportManager.closeReport(_reportId, _reportCloser, _reason, result); + } + + public void unregisterListener() + { + HandlerList.unregisterAll(this); + } +} diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java index 31364b88f..787cdc30f 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java @@ -41,6 +41,8 @@ import mineplex.core.preferences.PreferencesManager; import mineplex.core.projectile.ProjectileManager; import mineplex.core.punish.Punish; import mineplex.core.recharge.Recharge; +import mineplex.core.report.ReportManager; +import mineplex.core.report.ReportPlugin; import mineplex.core.resourcepack.ResUnloadCheck; import mineplex.core.resourcepack.ResPackManager; import mineplex.core.serverConfig.ServerConfiguration; @@ -150,6 +152,7 @@ public class Hub extends JavaPlugin implements IRelation } }); new GlobalPacketManager(this, clientManager, serverStatusManager, inventoryManager, donationManager, petManager, statsManager, giveawayManager); + new ReportPlugin(this, new ReportManager(this, preferenceManager, serverStatusManager.getCurrentServerName())); //new Replay(this, packetHandler); AprilFoolsManager.Initialize(this, clientManager, disguiseManager);