From a37d8ecb318f4988dd2f165b29d4e98d03d425e8 Mon Sep 17 00:00:00 2001
From: ZeroEpoch1969 <13510767+ZeroEpoch1969@users.noreply.github.com>
Date: Fri, 24 Jan 2020 23:27:16 -0700
Subject: [PATCH] yeah
---
TotalFreedomMod.iml | 4 +-
pom.xml | 19 ++
.../totalfreedommod/EntityWiper.java | 55 +++-
.../totalfreedommod/LoginProcess.java | 18 ++
.../totalfreedommod/admin/Admin.java | 24 +-
.../command/Command_chatcolor.java | 53 ----
.../command/Command_cleardiscordqueue.java | 20 ++
.../command/Command_entitywipe.java | 94 ++++++-
.../command/Command_linkdiscord.java | 50 ++--
.../command/Command_mobpurge.java | 36 +--
.../command/Command_myadmin.java | 100 ++++++-
.../command/Command_mymasterbuilder.java | 237 +++++++++++++++++
.../command/Command_notes.java | 135 ++++++++++
.../command/Command_playerverify.java | 46 +++-
.../command/Command_purgeall.java | 2 +-
.../command/Command_realtime.java | 4 +-
.../command/Command_verify.java | 142 ++++++++--
.../totalfreedommod/discord/Discord.java | 248 +++++++++++++++++-
.../discord/PrivateMessageListener.java | 33 ++-
.../masterbuilder/MasterBuilder.java | 24 +-
.../PlayerVerification.java | 6 +-
.../playerverification/VPlayer.java | 67 ++++-
.../totalfreedommod/util/FUtil.java | 15 ++
23 files changed, 1243 insertions(+), 189 deletions(-)
delete mode 100644 src/main/java/me/totalfreedom/totalfreedommod/command/Command_chatcolor.java
create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/command/Command_cleardiscordqueue.java
create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/command/Command_mymasterbuilder.java
create mode 100644 src/main/java/me/totalfreedom/totalfreedommod/command/Command_notes.java
diff --git a/TotalFreedomMod.iml b/TotalFreedomMod.iml
index 42591655..a17c989b 100644
--- a/TotalFreedomMod.iml
+++ b/TotalFreedomMod.iml
@@ -49,7 +49,7 @@
-
+
@@ -82,7 +82,6 @@
-
@@ -163,5 +162,6 @@
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1b8638cf..788a6761 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,6 +94,11 @@
papermc
https://papermc.io/repo/repository/maven-public/
+
+
+ rayzr-repo
+ https://cdn.rawgit.com/Rayzr522/maven-repo/master/
+
@@ -118,6 +123,13 @@
compile
+
+ commons-codec
+ commons-codec
+ 1.9
+ compile
+
+
org.spigotmc
spigot
@@ -187,6 +199,12 @@
1.15.1-R0.1-SNAPSHOT
provided
+
+
+ me.rayzr522
+ jsonmessage
+ 1.0.0
+
@@ -344,6 +362,7 @@
commons-io:commons-io
org.apache.commons:commons-lang3
+ commons-codec:commons-codec
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/EntityWiper.java b/src/main/java/me/totalfreedom/totalfreedommod/EntityWiper.java
index 1b89127a..030b9ac0 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/EntityWiper.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/EntityWiper.java
@@ -7,6 +7,8 @@ import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
@@ -23,7 +25,6 @@ public class EntityWiper extends FreedomService
EntityType.ARMOR_STAND,
EntityType.PAINTING,
EntityType.BOAT,
- EntityType.PLAYER,
EntityType.LEASH_HITCH,
EntityType.ITEM_FRAME
);
@@ -37,9 +38,9 @@ public class EntityWiper extends FreedomService
@Override
public void run()
{
- wipe();
+ wipeEntities(false);
}
- }.runTaskTimer(plugin, 1L, 300 * 5); // 5 minutes
+ }.runTaskTimer(plugin, 600L, 600L); // 30 second delay after startup + run every 30 seconds
}
@Override
@@ -51,15 +52,19 @@ public class EntityWiper extends FreedomService
// Methods for wiping
- public int wipe()
+ public int wipeEntities(boolean bypassBlacklist)
{
int removed = 0;
for (World world : Bukkit.getWorlds())
{
for (Entity entity : world.getEntities())
{
- if (!BLACKLIST.contains(entity.getType()) || !Groups.MOB_TYPES.contains(entity.getType()))
+ if (!(entity instanceof Player))
{
+ if (!bypassBlacklist && (BLACKLIST.contains(entity.getType()) || Groups.MOB_TYPES.contains(entity.getType())))
+ {
+ continue;
+ }
entity.remove();
removed++;
}
@@ -67,4 +72,44 @@ public class EntityWiper extends FreedomService
}
return removed;
}
+
+ public int wipeEntities(EntityType entityType)
+ {
+ int removed = 0;
+ for (World world : Bukkit.getWorlds())
+ {
+ for (Entity entity : world.getEntities())
+ {
+ if (!entity.getType().equals(entityType))
+ {
+ continue;
+ }
+ entity.remove();
+ removed++;
+ }
+ }
+ return removed;
+ }
+
+ public int purgeMobs(EntityType type)
+ {
+ int removed = 0;
+ for (World world : Bukkit.getWorlds())
+ {
+ for (Entity entity : world.getLivingEntities())
+ {
+ if (entity instanceof LivingEntity && !(entity instanceof Player))
+ {
+ if (type != null && !entity.getType().equals(type))
+ {
+ continue;
+ }
+ entity.remove();
+ removed++;
+ }
+ }
+ }
+ return removed;
+ }
+
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java b/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java
index 00da1f8c..d98b7456 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/LoginProcess.java
@@ -8,6 +8,7 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
+import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FSync;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.ChatColor;
@@ -19,6 +20,7 @@ import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.scheduler.BukkitRunnable;
+import me.rayzr522.jsonmessage.JSONMessage;
public class LoginProcess extends FreedomService
{
@@ -246,6 +248,22 @@ public class LoginProcess extends FreedomService
{
fPlayer.setTag(FUtil.colorize(vPlayer.getTag()));
}
+ int noteCount = vPlayer.getNotes().size();
+ if (noteCount != 0)
+ {
+ String noteMessage = "This player has " + noteCount + " staff note" + (noteCount > 1 ? "s" : "") + ".";
+ JSONMessage notice = JSONMessage.create(ChatColor.GOLD + noteMessage + " Click here to view them.")
+ .tooltip("Click here to view them.")
+ .runCommand("/notes " + player.getName() + " list");
+ FLog.info(noteMessage);
+ for (Player p : server.getOnlinePlayers())
+ {
+ if (plugin.al.isAdminImpostor(p))
+ {
+ notice.send(p);
+ }
+ }
+ }
}
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java b/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java
index a921165f..385422f2 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/admin/Admin.java
@@ -1,6 +1,7 @@
package me.totalfreedom.totalfreedommod.admin;
import com.google.common.collect.Lists;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import lombok.Getter;
@@ -34,6 +35,7 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable
private Rank rank = Rank.SUPER_ADMIN;
@Getter
private final List ips = Lists.newArrayList();
+ private final List backupCodes = Lists.newArrayList();
@Getter
@Setter
private Date lastLogin = new Date();
@@ -92,7 +94,8 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable
.append("- Potion Spy: ").append(potionSpy).append("\n")
.append("- Admin Chat Format: ").append(acFormat).append("\n")
.append("- Old Tags: ").append(oldTags).append("\n")
- .append("- Log Stick: ").append(logStick);
+ .append("- Log Stick: ").append(logStick)
+ .append("- Backup Codes: ").append(backupCodes.size()).append("/10").append("\n");
return output.toString();
}
@@ -113,6 +116,8 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable
rank = Rank.findRank(cs.getString("rank"));
ips.clear();
ips.addAll(cs.getStringList("ips"));
+ backupCodes.clear();
+ backupCodes.addAll(cs.getStringList("backupCodes"));
lastLogin = FUtil.stringToDate(cs.getString("last_login"));
loginMessage = cs.getString("login_message", null);
discordID = cs.getString("discord_id", null);
@@ -132,6 +137,7 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable
cs.set("active", active);
cs.set("rank", rank.toString());
cs.set("ips", Lists.newArrayList(ips));
+ cs.set("backupCodes", Lists.newArrayList(backupCodes));
cs.set("last_login", FUtil.dateToString(lastLogin));
cs.set("login_message", loginMessage);
cs.set("discord_id", discordID);
@@ -183,6 +189,22 @@ public class Admin implements ConfigLoadable, ConfigSavable, Validatable
ips.clear();
}
+ public List getBackupCodes()
+ {
+ return Collections.unmodifiableList(backupCodes);
+ }
+
+ public void setBackupCodes(List codes)
+ {
+ backupCodes.clear();
+ backupCodes.addAll(codes);
+ }
+
+ public void removeBackupCode(String code)
+ {
+ backupCodes.remove(code);
+ }
+
public void setActive(boolean active)
{
this.active = active;
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_chatcolor.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_chatcolor.java
deleted file mode 100644
index 05e4ae4a..00000000
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_chatcolor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package me.totalfreedom.totalfreedommod.command;
-
-import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
-import me.totalfreedom.totalfreedommod.rank.Rank;
-import me.totalfreedom.totalfreedommod.util.FUtil;
-import org.apache.commons.lang.StringUtils;
-import org.bukkit.ChatColor;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
-@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
-@CommandParameters(description = "Change your default chat color.", usage = "/ ")
-public class Command_chatcolor extends FreedomCommand
-{
-
- @Override
- public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
- {
- if (args.length != 1)
- {
- return false;
- }
-
- VPlayer vPlayer = plugin.pv.getVerificationPlayer(playerSender);
-
- if (args[0].equals("clear"))
- {
- vPlayer.setColor(null);
- msg("Default chat color cleared.");
- return true;
- }
-
- if (args[0].equalsIgnoreCase("k")
- || args[0].equalsIgnoreCase("0")
- || args[0].equalsIgnoreCase("m"))
- {
- msg("You are not allowed to use that color as default.");
- return true;
- }
-
- ChatColor color = ChatColor.getByChar(args[0]);
- if (color == null)
- {
- msg("Please enter a valid color. Example: a, 2, e");
- return true;
- }
-
- vPlayer.setColor(color);
- msg("Default chat color set to \"" + args[0] + ".\"");
- return true;
- }
-}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_cleardiscordqueue.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_cleardiscordqueue.java
new file mode 100644
index 00000000..8e3260d9
--- /dev/null
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_cleardiscordqueue.java
@@ -0,0 +1,20 @@
+package me.totalfreedom.totalfreedommod.command;
+
+import me.totalfreedom.totalfreedommod.rank.Rank;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+@CommandPermissions(level = Rank.SENIOR_ADMIN, source = SourceType.ONLY_CONSOLE)
+@CommandParameters(description = "Clear the discord message queue", usage = "/")
+public class Command_cleardiscordqueue extends FreedomCommand
+{
+
+ @Override
+ public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
+ {
+ plugin.dc.clearQueue();
+ msg("Cleared the discord message queue.");
+ return true;
+ }
+}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_entitywipe.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_entitywipe.java
index 617798d8..46bf9297 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_entitywipe.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_entitywipe.java
@@ -1,26 +1,106 @@
package me.totalfreedom.totalfreedommod.command;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
-import org.bukkit.Bukkit;
-import org.bukkit.World;
+import me.totalfreedom.totalfreedommod.util.Groups;
+import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.SUPER_ADMIN, source = SourceType.BOTH)
-@CommandParameters(description = "Remove various server entities that may cause lag, such as dropped items, minecarts, and boats.", usage = "/", aliases = "ew,rd")
+@CommandParameters(description = "Remove various server entities that may cause lag, such as dropped items, minecarts, and boats.", usage = "/ [name | -a]", aliases = "ew,rd")
public class Command_entitywipe extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
- FUtil.adminAction(sender.getName(), "Removing all server entities", true);
- int removed = plugin.ew.wipe();
- msg(removed + " entities removed.");
+ EntityType type = null;
+ String entityName = null;
+ boolean bypassBlacklist = false;
+ if (args.length > 0)
+ {
+ if (args[0].equals("-a"))
+ {
+ bypassBlacklist = true;
+ }
+ else
+ {
+ try
+ {
+ type = EntityType.valueOf(args[0].toUpperCase());
+ }
+ catch (Exception e)
+ {
+ msg(args[0] + " is not a valid entity type.", ChatColor.RED);
+ return true;
+ }
+ if (!getAllEntities().contains(type))
+ {
+ msg(FUtil.formatName(type.name()) + " is an entity, however: it is a mob.", ChatColor.RED);
+ return true;
+ }
+ }
+ }
+
+ if (type != null)
+ {
+ entityName = FUtil.formatName(type.name());
+ }
+
+ FUtil.adminAction(sender.getName(), "Purging all " + (type != null ? entityName + "s" : "entities"), true);
+ int count;
+ if (type != null)
+ {
+ count = plugin.ew.wipeEntities(type);
+ }
+ else
+ {
+ count = plugin.ew.wipeEntities(bypassBlacklist);
+ }
+ msg(count + " " + (type != null ? entityName : "entities") + FUtil.showS(count) + " removed.");
return true;
}
+
+ public static List getAllEntities()
+ {
+ List entityTypes = new ArrayList<>();
+ for (EntityType entityType : EntityType.values())
+ {
+ if (!Groups.MOB_TYPES.contains(entityType))
+ {
+ entityTypes.add(entityType);
+ }
+ }
+ return entityTypes;
+ }
+
+ public static List getAllEntityNames()
+ {
+ List names = new ArrayList<>();
+ for (EntityType entityType : getAllEntities())
+ {
+ names.add(entityType.name());
+ }
+ return names;
+ }
+
+ @Override
+ public List getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
+ {
+ List names = getAllEntityNames();
+ names.add("-a");
+ if (args.length == 1)
+ {
+ return names;
+ }
+
+ return Collections.emptyList();
+ }
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_linkdiscord.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_linkdiscord.java
index f4e3c2e1..3d17eb49 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_linkdiscord.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_linkdiscord.java
@@ -1,8 +1,8 @@
package me.totalfreedom.totalfreedommod.command;
-import java.util.Random;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.discord.Discord;
+import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.ChatColor;
@@ -24,6 +24,8 @@ public class Command_linkdiscord extends FreedomCommand
return true;
}
+ String code;
+
if (plugin.al.isAdmin(playerSender))
{
Admin admin = plugin.al.getAdmin(playerSender);
@@ -33,20 +35,33 @@ public class Command_linkdiscord extends FreedomCommand
return true;
}
- if (Discord.LINK_CODES.containsValue(admin))
+ if (Discord.ADMIN_LINK_CODES.containsValue(admin))
{
- msg("Your linking code is " + ChatColor.GREEN + Discord.getCodeForAdmin(admin), ChatColor.AQUA);
+ code = Discord.getCodeForAdmin(admin);
}
else
{
- String code = "";
- Random random = new Random();
- for (int i = 0; i < 5; i++)
- {
- code += random.nextInt(10);
- }
- Discord.LINK_CODES.put(code, admin);
- msg("Your linking code is " + ChatColor.GREEN + code, ChatColor.AQUA);
+ code = plugin.dc.generateCode(5);
+ Discord.ADMIN_LINK_CODES.put(code, admin);
+ }
+ }
+ else if (plugin.mbl.isMasterBuilder(playerSender))
+ {
+ MasterBuilder masterBuilder = plugin.mbl.getMasterBuilder(playerSender);
+ if (masterBuilder.getDiscordID() != null)
+ {
+ msg("Your Minecraft account is already linked to a Discord account.", ChatColor.RED);
+ return true;
+ }
+
+ if (Discord.MASTER_BUILDER_LINK_CODES.containsValue(masterBuilder))
+ {
+ code = Discord.getCodeForMasterBuilder(masterBuilder);
+ }
+ else
+ {
+ code = plugin.dc.generateCode(5);
+ Discord.MASTER_BUILDER_LINK_CODES.put(code, masterBuilder);
}
}
else
@@ -60,21 +75,16 @@ public class Command_linkdiscord extends FreedomCommand
if (Discord.PLAYER_LINK_CODES.containsValue(data))
{
- msg("Your linking code is " + ChatColor.GREEN + Discord.getCodeForPlayer(data), ChatColor.AQUA);
- msg("Take this code and DM the server bot (" + plugin.dc.formatBotTag() + ") the code (do not put anything else in the message, only the code)");
+ code = Discord.getCodeForPlayer(data);
}
else
{
- String code = "";
- Random random = new Random();
- for (int i = 0; i < 5; i++)
- {
- code += random.nextInt(10);
- }
+ code = plugin.dc.generateCode(5);
Discord.PLAYER_LINK_CODES.put(code, data);
- msg("Your linking code is " + ChatColor.GREEN + code, ChatColor.AQUA);
}
}
+ msg("Your linking code is " + ChatColor.AQUA + code, ChatColor.GREEN);
+ msg("Take this code and DM the server bot (" + plugin.dc.formatBotTag() + ") the code (do not put anything else in the message, only the code)");
return true;
}
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mobpurge.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mobpurge.java
index 159c9d55..e6797d8e 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mobpurge.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mobpurge.java
@@ -6,15 +6,10 @@ import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import me.totalfreedom.totalfreedommod.util.Groups;
-import org.apache.commons.lang.WordUtils;
-import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
-import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
-import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.SUPER_ADMIN, source = SourceType.BOTH)
@@ -41,43 +36,22 @@ public class Command_mobpurge extends FreedomCommand
if (!Groups.MOB_TYPES.contains(type))
{
- msg(WordUtils.capitalizeFully(type.name().replace("_", " ")) + " is an entity, however it is not a mob.", ChatColor.RED);
+ msg(FUtil.formatName(type.name()) + " is an entity, however it is not a mob.", ChatColor.RED);
return true;
}
}
if (type != null)
{
- mobName = WordUtils.capitalizeFully(type.name().replace("_", " "));
+ mobName = FUtil.formatName(type.name());
}
- FUtil.adminAction(sender.getName(), "Purging all " + (type != null ? mobName + "s" : "mobs"), true);
- msg(purgeMobs(type) + " " + (type != null ? mobName : "mob") + "s removed.");
+ FUtil.adminAction(sender.getName(), "Purging all " + (type != null ? mobName + "s" : "mobs"), true);
+ int count = plugin.ew.purgeMobs(type);
+ msg(count + " " + (type != null ? mobName : "mob") + FUtil.showS(count) + " removed.");
return true;
}
- public static int purgeMobs(EntityType type)
- {
- int removed = 0;
- for (World world : Bukkit.getWorlds())
- {
- for (Entity ent : world.getLivingEntities())
- {
- if (ent instanceof LivingEntity && !(ent instanceof Player))
- {
- if (type != null && !ent.getType().equals(type))
- {
- continue;
- }
- ent.remove();
- removed++;
- }
- }
- }
-
- return removed;
- }
-
public static List getAllMobNames()
{
List names = new ArrayList<>();
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_myadmin.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_myadmin.java
index 0b3da351..4afd44a7 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_myadmin.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_myadmin.java
@@ -1,6 +1,9 @@
package me.totalfreedom.totalfreedommod.command;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
@@ -12,17 +15,14 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-@CommandPermissions(level = Rank.OP, source = SourceType.BOTH)
-@CommandParameters(description = "Manage my admin entry", usage = "/ [-o ] | setlogin | clearlogin | setacformat | clearacformat> | oldtags | logstick | syncroles>")
+@CommandPermissions(level = Rank.SUPER_ADMIN, source = SourceType.ONLY_IN_GAME)
+@CommandParameters(description = "Manage my admin entry", usage = "/ [-o ] | setlogin | clearlogin | setacformat | clearacformat> | oldtags | logstick | syncroles | genbackupcodes>")
public class Command_myadmin extends FreedomCommand
{
@Override
protected boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
- checkPlayer();
- checkRank(Rank.SUPER_ADMIN);
-
if (args.length < 1)
{
return false;
@@ -47,7 +47,7 @@ public class Command_myadmin extends FreedomCommand
target = getAdmin(targetPlayer);
if (target == null)
{
- msg("That player is not admin", ChatColor.RED);
+ msg("That player is not an admin", ChatColor.RED);
return true;
}
@@ -84,6 +84,7 @@ public class Command_myadmin extends FreedomCommand
target.addIp(targetIp);
plugin.al.save();
+ plugin.al.updateTables();
msg(counter + " IPs removed.");
msg(targetPlayer, target.getIps().get(0) + " is now your only IP address");
@@ -240,10 +241,97 @@ public class Command_myadmin extends FreedomCommand
return true;
}
+ case "genbackupcodes":
+ if (!plugin.dc.enabled)
+ {
+ msg("The Discord verification system is currently disabled.", ChatColor.RED);
+ return true;
+ }
+ else if (target.getDiscordID() == null || target.getDiscordID().isEmpty())
+ {
+ msg("Discord verification is not enabled for you.", ChatColor.RED);
+ return true;
+ }
+
+ msg("Generating backup codes...", ChatColor.GREEN);
+
+ boolean generated = plugin.dc.sendBackupCodes(target);
+
+ if (generated)
+ {
+ msg("Your backup codes have been sent to your discord account. They can be re-generated at anytime.", ChatColor.GREEN);
+ }
+ else
+ {
+ msg("Failed to generate backup codes, please contact a developer (preferably Seth)", ChatColor.RED);
+ }
+ return true;
+
default:
{
return false;
}
}
}
+
+ @Override
+ public List getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
+ {
+ if (!plugin.al.isAdmin(sender))
+ {
+ return Collections.emptyList();
+ }
+
+ List singleArguments = Arrays.asList("clearips", "setlogin", "setacformat");
+ List doubleArguments = Arrays.asList("clearip", "clearlogin", "clearacformat", "oldtags", "logstick", "syncroles", "genbackupcodes");
+ if (args.length == 1)
+ {
+ List options = new ArrayList<>();
+ options.add("-o");
+ options.addAll(singleArguments);
+ options.addAll(doubleArguments);
+ return options;
+ }
+ else if (args.length == 2)
+ {
+ if (args[0].equals("-o"))
+ {
+ return FUtil.getPlayerList();
+ }
+ else
+ {
+ if (doubleArguments.contains(args[0]))
+ {
+ if (args[0].equals("clearip"))
+ {
+ List ips = plugin.al.getAdmin(sender).getIps();
+ ips.remove(Ips.getIp(playerSender));
+ return ips;
+ }
+ }
+ }
+ }
+ else if (args.length == 3)
+ {
+ if (args[0].equals("-o"))
+ {
+ List options = new ArrayList<>();
+ options.addAll(singleArguments);
+ options.addAll(doubleArguments);
+ return options;
+ }
+ }
+ else if (args.length == 4)
+ {
+ if (args[0].equals("-o") && args[2].equals("clearip"))
+ {
+ Admin admin = plugin.al.getEntryByName(args[1]);
+ if (admin != null)
+ {
+ return admin.getIps();
+ }
+ }
+ }
+ return FUtil.getPlayerList();
+ }
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mymasterbuilder.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mymasterbuilder.java
new file mode 100644
index 00000000..8b36f837
--- /dev/null
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_mymasterbuilder.java
@@ -0,0 +1,237 @@
+package me.totalfreedom.totalfreedommod.command;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
+import me.totalfreedom.totalfreedommod.rank.Rank;
+import me.totalfreedom.totalfreedommod.util.FUtil;
+import net.pravian.aero.util.Ips;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
+@CommandParameters(description = "Manage my Master Builder entry", usage = "/ [-o ] | genbackupcodes>", aliases = "mymb")
+public class Command_mymasterbuilder extends FreedomCommand
+{
+
+ @Override
+ protected boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
+ {
+ if (args.length < 1)
+ {
+ return false;
+ }
+
+ Player init = null;
+ MasterBuilder target = plugin.mbl.getMasterBuilder(playerSender);
+ Player targetPlayer = playerSender;
+
+ // -o switch
+ if (args[0].equals("-o"))
+ {
+ if (!FUtil.canManageMasterBuilders(playerSender.getName()))
+ {
+ return noPerms();
+ }
+ init = playerSender;
+ targetPlayer = getPlayer(args[1]);
+ if (targetPlayer == null)
+ {
+ msg(FreedomCommand.PLAYER_NOT_FOUND);
+ return true;
+ }
+
+ target = plugin.mbl.getMasterBuilder(playerSender);
+ if (target == null)
+ {
+ msg("That player is not a Master Builder", ChatColor.RED);
+ return true;
+ }
+
+ // Shift 2
+ args = Arrays.copyOfRange(args, 2, args.length);
+ if (args.length < 1)
+ {
+ return false;
+ }
+ }
+
+ final String targetIp = Ips.getIp(targetPlayer);
+
+ switch (args[0])
+ {
+ case "clearips":
+ {
+ if (args.length != 1)
+ {
+ return false; // Double check: the player might mean "clearip"
+ }
+
+ if (init == null)
+ {
+ FUtil.adminAction(sender.getName(), "Clearing my IPs", false);
+ }
+ else
+ {
+ FUtil.adminAction(sender.getName(), "Clearing " + target.getName() + "' IPs", true);
+ }
+
+ int counter = target.getIps().size() - 1;
+ target.clearIPs();
+ target.addIp(targetIp);
+
+ plugin.mbl.save();
+ plugin.mbl.updateTables();
+
+ msg(counter + " IPs removed.");
+ msg(targetPlayer, target.getIps().get(0) + " is now your only IP address");
+ return true;
+ }
+
+ case "clearip":
+ {
+ if (args.length != 2)
+ {
+ return false; // Double check: the player might mean "clearips"
+ }
+
+ if (!target.getIps().contains(args[1]))
+ {
+ if (init == null)
+ {
+ msg("That IP is not registered to you.");
+ }
+ else
+ {
+ msg("That IP does not belong to that player.");
+ }
+ return true;
+ }
+
+ if (targetIp.equals(args[1]))
+ {
+ if (init == null)
+ {
+ msg("You cannot remove your current IP.");
+ }
+ else
+ {
+ msg("You cannot remove that Master Builders's current IP.");
+ }
+ return true;
+ }
+
+ FUtil.adminAction(sender.getName(), "Removing an IP" + (init == null ? "" : " from " + targetPlayer.getName() + "'s IPs"), true);
+
+ target.removeIp(args[1]);
+ plugin.mbl.save();
+ plugin.mbl.updateTables();
+
+ msg("Removed IP " + args[1]);
+ msg("Current IPs: " + StringUtils.join(target.getIps(), ", "));
+ return true;
+ }
+
+ case "genbackupcodes":
+ if (!plugin.dc.enabled)
+ {
+ msg("The Discord verification system is currently disabled.", ChatColor.RED);
+ return true;
+ }
+ else if (target.getDiscordID() == null || target.getDiscordID().isEmpty())
+ {
+ msg("Discord verification is not enabled for you.", ChatColor.RED);
+ return true;
+ }
+
+ msg("Generating backup codes...", ChatColor.GREEN);
+
+ boolean generated = plugin.dc.sendBackupCodes(target);
+
+ if (generated)
+ {
+ msg("Your backup codes have been sent to your discord account. They can be re-generated at anytime.", ChatColor.GREEN);
+ }
+ else
+ {
+ msg("Failed to generate backup codes, please contact a developer (preferably Seth)", ChatColor.RED);
+ }
+ return true;
+
+ default:
+ {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public List getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
+ {
+
+ if (!plugin.mbl.isMasterBuilder(playerSender) && !FUtil.canManageMasterBuilders(playerSender.getName()))
+ {
+ return Collections.emptyList();
+ }
+
+ List singleArguments = Arrays.asList("clearips");
+ List doubleArguments = Arrays.asList("clearip", "genbackupcodes");
+ if (args.length == 1)
+ {
+ List options = new ArrayList<>();
+ options.add("-o");
+ options.addAll(singleArguments);
+ options.addAll(doubleArguments);
+ return options;
+ }
+ else if (args.length == 2)
+ {
+ if (args[0].equals("-o"))
+ {
+ return FUtil.getPlayerList();
+ }
+ else
+ {
+ if (doubleArguments.contains(args[0]))
+ {
+ if (args[0].equals("clearip"))
+ {
+ if (args[0].equals("clearip"))
+ {
+ List ips = plugin.mbl.getMasterBuilder(sender).getIps();
+ ips.remove(Ips.getIp(playerSender));
+ return ips;
+ }
+ }
+ }
+ }
+ }
+ else if (args.length == 3)
+ {
+ if (args[0].equals("-o"))
+ {
+ List options = new ArrayList<>();
+ options.addAll(singleArguments);
+ options.addAll(doubleArguments);
+ return options;
+ }
+ }
+ else if (args.length == 4)
+ {
+ if (args[0].equals("-o") && args[2].equals("clearip"))
+ {
+ MasterBuilder masterBuilder = plugin.mbl.getEntryByName(args[1]);
+ if (masterBuilder != null)
+ {
+ return masterBuilder.getIps();
+ }
+ }
+ }
+ return FUtil.getPlayerList();
+ }
+}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_notes.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_notes.java
new file mode 100644
index 00000000..1deb538b
--- /dev/null
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_notes.java
@@ -0,0 +1,135 @@
+package me.totalfreedom.totalfreedommod.command;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import me.totalfreedom.totalfreedommod.player.PlayerData;
+import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
+import me.totalfreedom.totalfreedommod.rank.Rank;
+import me.totalfreedom.totalfreedommod.util.FUtil;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.ArrayUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+@CommandPermissions(level = Rank.SUPER_ADMIN, source = SourceType.BOTH)
+@CommandParameters(description = "Manage notes for a player", usage = "/ | remove | clear>")
+public class Command_notes extends FreedomCommand
+{
+
+ @Override
+ public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
+ {
+ if (args.length < 2)
+ {
+ return false;
+ }
+
+ VPlayer vPlayer;
+
+ final Player player = getPlayer(args[0]);
+ if (player == null)
+ {
+ final PlayerData entry = plugin.pl.getData(args[0]);
+
+ if (entry == null)
+ {
+ msg("Can't find that user. If target is not logged in, make sure that you spelled the name exactly.");
+ return true;
+ }
+
+ vPlayer = plugin.pv.getVerificationPlayer(entry.getUsername());
+ }
+ else
+ {
+ vPlayer = plugin.pv.getVerificationPlayer(player);
+ }
+
+ if (args[1].equals("list"))
+ {
+ final StringBuilder noteList = new StringBuilder();
+ noteList.append(ChatColor.GREEN + "Player notes for " + vPlayer.getName() + ":");
+ int id = 1;
+ for (Map, ?> noteMap : vPlayer.getNotes())
+ {
+ String admin = String.valueOf(noteMap.keySet().toArray()[0]);
+ String note = String.valueOf(noteMap.get(admin));
+ String noteLine = id + ". " + admin + ": " + note;
+ noteList.append("\n" + ChatColor.GOLD + noteLine);
+ id++;
+ }
+ msg(noteList.toString());
+ return true;
+ }
+ else if (args[1].equals("add"))
+ {
+ if (args.length < 3)
+ {
+ return false;
+ }
+ String note = StringUtils.join(ArrayUtils.subarray(args, 2, args.length), " ");
+ vPlayer.addNote(sender.getName(), note);
+ plugin.pv.saveVerificationData(vPlayer);
+ msg("Note added.", ChatColor.GREEN);
+ return true;
+ }
+ else if (args[1].equals("remove"))
+ {
+ if (args.length < 3)
+ {
+ return false;
+ }
+ int id;
+ try
+ {
+ id = Integer.valueOf(args[2]);
+ }
+ catch (NumberFormatException e)
+ {
+ msg("Invalid number: " + args[2], ChatColor.RED);
+ return true;
+ }
+ id--;
+ if (vPlayer.removeNote(id))
+ {
+ plugin.pv.saveVerificationData(vPlayer);
+ msg("Note removed.");
+ }
+ else
+ {
+ msg("No note with the ID of " + args[2] + "exists.", ChatColor.RED);
+ }
+ return true;
+ }
+ else if (args[1].equals("clear"))
+ {
+ int count = vPlayer.getNotes().size();
+ vPlayer.clearNotes();
+ plugin.pv.saveVerificationData(vPlayer);
+ msg("Cleared " + count + " notes.", ChatColor.GREEN);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public List getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
+ {
+ if (args.length == 1)
+ {
+ return FUtil.getPlayerList();
+ }
+ else if (args.length == 2)
+ {
+ return Arrays.asList("list", "add", "remove", "clear");
+ }
+ else if (args.length > 2 && (args[1].equals("add")))
+ {
+ return FUtil.getPlayerList();
+ }
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_playerverify.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_playerverify.java
index c9b705a5..63d1f977 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_playerverify.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_playerverify.java
@@ -13,7 +13,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
-@CommandParameters(description = "Manage your verification", usage = "/ <", aliases = "playerverification,pv")
+@CommandParameters(description = "Manage your verification", usage = "/ ", aliases = "playerverification,pv")
public class Command_playerverify extends FreedomCommand
{
@Override
@@ -66,21 +66,19 @@ public class Command_playerverify extends FreedomCommand
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
- if (data.getEnabled())
+ else if (data.getEnabled())
{
msg("Discord verification is already enabled for you.", ChatColor.RED);
return true;
}
+ else if (data.getDiscordId() == null)
+ {
+ msg("Please link a discord account with /linkdiscord.", ChatColor.RED);
+ return true;
+ }
data.setEnabled(true);
plugin.pv.saveVerificationData(data);
- if (data.getDiscordId() != null)
- {
- msg("Re-enabled Discord verification.", ChatColor.GREEN);
- }
- else
- {
- msg("Enabled Discord verification. Please type /linkdiscord to link a Discord account.", ChatColor.GREEN);
- }
+ msg("Re-enabled Discord verification.", ChatColor.GREEN);
return true;
case "disable":
@@ -99,7 +97,33 @@ public class Command_playerverify extends FreedomCommand
boolean specified = target.getDiscordId() != null;
msg(ChatColor.GRAY + "Discord Verification Enabled: " + (enabled ? ChatColor.GREEN + "true" : ChatColor.RED + "false"));
msg(ChatColor.GRAY + "Discord ID: " + (specified ? ChatColor.GREEN + target.getDiscordId() : ChatColor.RED + "not set"));
+ msg(ChatColor.GRAY + "Backup Codes: " + data.getBackupCodes().size() + "/" + "10");
return true;
+
+ case "genbackupcodes":
+ if (!plugin.dc.enabled)
+ {
+ msg("The Discord verification system is currently disabled.", ChatColor.RED);
+ return true;
+ }
+ else if (!data.getEnabled())
+ {
+ msg("Discord verification is not enabled for you.", ChatColor.RED);
+ return true;
+ }
+
+ boolean generated = plugin.dc.sendBackupCodes(data);
+
+ if (generated)
+ {
+ msg("Your backup codes have been sent to your discord account. They can be re-generated at anytime.", ChatColor.GREEN);
+ }
+ else
+ {
+ msg("Failed to generate backup codes, please contact a developer (preferably Seth)", ChatColor.RED);
+ }
+ return true;
+
default:
return false;
}
@@ -109,7 +133,7 @@ public class Command_playerverify extends FreedomCommand
{
if (args.length == 1)
{
- return Arrays.asList("enable", "disable", "status", "clearips");
+ return Arrays.asList("enable", "disable", "status", "clearips", "genbackupcodes");
}
return Collections.emptyList();
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_purgeall.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_purgeall.java
index 193814b8..9ad6c9d7 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_purgeall.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_purgeall.java
@@ -78,7 +78,7 @@ public class Command_purgeall extends FreedomCommand
plugin.fm.setGlobalFreeze(false);
// Remove all mobs
- Command_mobpurge.purgeMobs(null);
+ plugin.ew.purgeMobs(null);
return true;
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_realtime.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_realtime.java
index 71150c4d..12f35600 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_realtime.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_realtime.java
@@ -41,7 +41,7 @@ public class Command_realtime extends FreedomCommand
player.setUtcOffset(tz);
player.setRealTime(true);
plugin.rt.enable(playerSender);
- plugin.pv.save();
+ plugin.pv.saveVerificationData(player);
msg("Your in-game time is now synced with real time.");
return true;
}
@@ -56,7 +56,7 @@ public class Command_realtime extends FreedomCommand
player.setRealTime(false);
msg("Your in-game time is no longer synced with real time.");
plugin.rt.disable(playerSender);
- plugin.pv.save();
+ plugin.pv.saveVerificationData(player);
return true;
}
return true;
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_verify.java b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_verify.java
index 24c5ff70..f6a382b1 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/command/Command_verify.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/command/Command_verify.java
@@ -1,12 +1,11 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.Date;
-import java.util.Random;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
-import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
import me.totalfreedom.totalfreedommod.player.FPlayer;
+import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.pravian.aero.util.Ips;
@@ -44,7 +43,7 @@ public class Command_verify extends FreedomCommand
plugin.pl.getPlayer(player).getFreezeData().setFrozen(false);
player.sendMessage(ChatColor.GRAY + "You have been unfrozen.");
}
- plugin.pv.verifyPlayer(player);
+ plugin.pv.verifyPlayer(player, null);
plugin.rm.updateDisplay(player);
return true;
}
@@ -62,7 +61,7 @@ public class Command_verify extends FreedomCommand
return true;
}
- if (!plugin.pv.isPlayerImpostor(playerSender) && !plugin.al.isAdminImpostor(playerSender))
+ if (!plugin.pv.isPlayerImpostor(playerSender) && !plugin.al.isAdminImpostor(playerSender) && !plugin.mbl.isMasterBuilderImpostor(playerSender))
{
msg("You are not an impostor, therefore you do not need to verify.", ChatColor.RED);
return true;
@@ -70,7 +69,17 @@ public class Command_verify extends FreedomCommand
String discordId = "";
- if (plugin.al.isAdminImpostor(playerSender))
+ if (plugin.pv.isPlayerImpostor(playerSender))
+ {
+ VPlayer vPlayer = plugin.pv.getVerificationPlayer(playerSender);
+ if (vPlayer.getDiscordId() == null)
+ {
+ msg("You do not have a Discord account linked to your Minecraft account, please verify the manual way.", ChatColor.RED);
+ return true;
+ }
+ discordId = vPlayer.getDiscordId();
+ }
+ else if (plugin.al.isAdminImpostor(playerSender))
{
Admin admin = plugin.al.getEntryByName(playerSender.getName());
if (admin.getDiscordID() == null)
@@ -80,48 +89,109 @@ public class Command_verify extends FreedomCommand
}
discordId = admin.getDiscordID();
}
-
- if (plugin.pv.isPlayerImpostor(playerSender))
+ else if (plugin.mbl.isMasterBuilderImpostor(playerSender))
{
- if (plugin.pv.getVerificationPlayer(playerSender).getDiscordId() == null)
+ MasterBuilder masterBuilder = plugin.mbl.getEntryByName(playerSender.getName());
+ if (masterBuilder.getDiscordID() == null)
{
msg("You do not have a Discord account linked to your Minecraft account, please verify the manual way.", ChatColor.RED);
return true;
}
- discordId = plugin.pv.getVerificationPlayer(playerSender).getDiscordId();
+ discordId = masterBuilder.getDiscordID();
}
if (args.length < 1)
{
- String code = "";
- Random random = new Random();
- for (int i = 0; i < 10; i++)
+ String code = plugin.dc.generateCode(10);
+ if (plugin.pv.isPlayerImpostor(playerSender))
{
- code += random.nextInt(10);
+ VPlayer vPlayer = plugin.pv.getVerificationPlayer(playerSender);
+ plugin.dc.addPlayerVerificationCode(code, vPlayer);
}
- Discord.VERIFY_CODES.add(code);
- Discord.bot.getUserById(discordId).openPrivateChannel().complete().sendMessage("A user with the IP `" + Ips.getIp(playerSender) + "` has sent a verification request. Please run the following in-game command: `/verify " + code + "`").complete();
+ else if (plugin.al.isAdminImpostor(playerSender))
+ {
+ Admin admin = plugin.al.getEntryByName(playerSender.getName());
+ plugin.dc.addAdminVerificationCode(code, admin);
+ }
+ else if (plugin.mbl.isMasterBuilderImpostor(playerSender))
+ {
+ MasterBuilder masterBuilder = plugin.mbl.getEntryByName(playerSender.getName());
+ plugin.dc.addMasterBuilderVerificationCode(code, masterBuilder);
+ }
+ plugin.dc.bot.getUserById(discordId).openPrivateChannel().complete().sendMessage("A user with the IP `" + Ips.getIp(playerSender) + "` has sent a verification request. Please run the following in-game command: `/verify " + code + "`").complete();
msg("A verification code has been sent to your account, please copy the code and run /verify ", ChatColor.GREEN);
}
else
{
String code = args[0];
- if (!Discord.VERIFY_CODES.contains(code))
+ String backupCode = null;
+
+ if (plugin.pv.isPlayerImpostor(playerSender))
{
- msg("You have entered an invalid verification code", ChatColor.RED);
+ VPlayer vPlayer = plugin.pv.getVerificationPlayer(playerSender);
+ VPlayer mapPlayer = plugin.dc.getPlayerVerificationCodes().get(code);
+ if (mapPlayer == null)
+ {
+ if (!vPlayer.getBackupCodes().contains(plugin.dc.getMD5(code)))
+ {
+ msg("You have entered an invalid verification code", ChatColor.RED);
+ return true;
+ }
+ else
+ {
+ backupCode = plugin.dc.getMD5(code);
+ }
+ }
+ else
+ {
+ plugin.dc.removePlayerVerificationCode(code);
+ }
+
+ final FPlayer fPlayer = plugin.pl.getPlayer(playerSender);
+ FUtil.bcastMsg(playerSender.getName() + " has verified!", ChatColor.GOLD);
+ plugin.rm.updateDisplay(playerSender);
+ playerSender.setOp(true);
+ msg(YOU_ARE_OP);
+ if (fPlayer.getFreezeData().isFrozen())
+ {
+ fPlayer.getFreezeData().setFrozen(false);
+ msg("You have been unfrozen.");
+ }
+ plugin.pv.verifyPlayer(playerSender, backupCode);
return true;
}
-
- if (plugin.al.isAdminImpostor(playerSender))
+ else if (plugin.al.isAdminImpostor(playerSender))
{
Admin admin = plugin.al.getEntryByName(playerSender.getName());
- Discord.VERIFY_CODES.remove(code);
+ Admin mapAdmin = plugin.dc.getAdminVerificationCodes().get(code);
+ if (mapAdmin == null)
+ {
+ if (!admin.getBackupCodes().contains(plugin.dc.getMD5(code)))
+ {
+ msg("You have entered an invalid verification code", ChatColor.RED);
+ return true;
+ }
+ else
+ {
+ backupCode = plugin.dc.getMD5(code);
+ }
+ }
+ else
+ {
+ plugin.dc.removeAdminVerificationCode(code);
+ }
+
FUtil.bcastMsg(playerSender.getName() + " has verified!", ChatColor.GOLD);
FUtil.adminAction(ConfigEntry.SERVER_NAME.getString(), "Re-adding " + admin.getName() + " to the admin list", true);
admin.setName(playerSender.getName());
admin.addIp(Ips.getIp(playerSender));
+ if (backupCode != null)
+ {
+ admin.removeBackupCode(backupCode);
+ }
+
if (!plugin.mbl.isMasterBuilder(playerSender))
{
MasterBuilder masterBuilder = null;
@@ -161,11 +231,38 @@ public class Command_verify extends FreedomCommand
}
return true;
}
-
- if (plugin.pv.isPlayerImpostor(playerSender))
+ else if (plugin.mbl.isMasterBuilderImpostor(playerSender))
{
+ MasterBuilder masterBuilder = plugin.mbl.getEntryByName(playerSender.getName());
+ MasterBuilder mapMasterBuilder = plugin.dc.getMasterBuilderVerificationCodes().get(code);
+ if (mapMasterBuilder == null)
+ {
+ if (!masterBuilder.getBackupCodes().contains(plugin.dc.getMD5(code)))
+ {
+ msg("You have entered an invalid verification code", ChatColor.RED);
+ return true;
+ }
+ else
+ {
+ backupCode = plugin.dc.getMD5(code);
+ }
+ }
+ else
+ {
+ plugin.dc.removeMasterBuilderVerificationCode(code);
+ }
+
+ if (backupCode != null)
+ {
+ masterBuilder.removeBackupCode(backupCode);
+ }
+
final FPlayer fPlayer = plugin.pl.getPlayer(playerSender);
FUtil.bcastMsg(playerSender.getName() + " has verified!", ChatColor.GOLD);
+ masterBuilder.setLastLogin(new Date());
+ masterBuilder.addIp(Ips.getIp(playerSender));
+ plugin.mbl.save();
+ plugin.mbl.updateTables();
plugin.rm.updateDisplay(playerSender);
playerSender.setOp(true);
msg(YOU_ARE_OP);
@@ -174,7 +271,6 @@ public class Command_verify extends FreedomCommand
fPlayer.getFreezeData().setFrozen(false);
msg("You have been unfrozen.");
}
- plugin.pv.verifyPlayer(playerSender);
return true;
}
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java
index 36751d67..379ad368 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/Discord.java
@@ -2,17 +2,24 @@ package me.totalfreedom.totalfreedommod.discord;
import com.earth2me.essentials.User;
import com.google.common.base.Strings;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.security.auth.login.LoginException;
import me.totalfreedom.totalfreedommod.FreedomService;
-import me.totalfreedom.totalfreedommod.GameRuleHandler;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
+import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
@@ -22,13 +29,17 @@ import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
+import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.SelfUser;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
+import net.dv8tion.jda.internal.utils.concurrent.CountingThreadFactory;
import net.pravian.aero.util.StringUtils;
+import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.WordUtils;
import org.bukkit.GameRule;
import org.bukkit.entity.Player;
@@ -40,12 +51,20 @@ import org.bukkit.event.player.PlayerQuitEvent;
public class Discord extends FreedomService
{
- public static HashMap LINK_CODES = new HashMap<>();
- public static HashMap PLAYER_LINK_CODES = new HashMap();
- public static List VERIFY_CODES = new ArrayList();
+ public static HashMap PLAYER_LINK_CODES = new HashMap<>();
+ public static HashMap PLAYER_VERIFICATION_CODES = new HashMap<>();
+ public static HashMap ADMIN_LINK_CODES = new HashMap<>();
+ public static HashMap ADMIN_VERIFICATION_CODES = new HashMap<>();
+ public static HashMap MASTER_BUILDER_LINK_CODES = new HashMap<>();
+ public static HashMap MASTER_BUILDER_VERIFICATION_CODES = new HashMap<>();
+ public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR = new ScheduledThreadPoolExecutor(5, new CountingThreadFactory(this::poolIdentifier, "RateLimit"));
+ public List> sentMessages = new ArrayList<>();
+
public static JDA bot = null;
public Boolean enabled = false;
+ Random random = new Random();
+
public Discord(TotalFreedomMod plugin)
{
super(plugin);
@@ -67,12 +86,13 @@ public class Discord extends FreedomService
}
try
{
-
+ RATELIMIT_EXECUTOR.setRemoveOnCancelPolicy(true);
bot = new JDABuilder(AccountType.BOT)
.setToken(ConfigEntry.DISCORD_TOKEN.getString())
.addEventListeners(new PrivateMessageListener())
.addEventListeners(new DiscordToMinecraftListener())
.setAutoReconnect(true)
+ .setRateLimitPool(RATELIMIT_EXECUTOR)
.addEventListeners(new ListenerAdapter()
{
@Override
@@ -99,11 +119,31 @@ public class Discord extends FreedomService
}
+ public String poolIdentifier()
+ {
+ return "JDA";
+ }
+
+ public void clearQueue()
+ {
+ for (CompletableFuture messages : sentMessages)
+ {
+ if (!messages.isDone())
+ {
+ messages.cancel(true);
+ }
+ }
+ sentMessages.clear();
+ messageChatChannel("**Message queue cleared**");
+ }
+
// Do no ask why this is here. I spent two hours trying to make a simple thing work
- public class StartEvent {
+ public class StartEvent
+ {
private final JDA api;
- public StartEvent(JDA api) {
+ public StartEvent(JDA api)
+ {
this.api = api;
}
@@ -113,6 +153,181 @@ public class Discord extends FreedomService
}
}
+ public boolean sendBackupCodes(VPlayer vPlayer)
+ {
+ List codes = generateBackupCodes();
+ List encryptedCodes = generateEncryptedBackupCodes(codes);
+ net.dv8tion.jda.api.entities.User user = bot.getUserById(vPlayer.getDiscordId());
+ File file = generateBackupCodesFile(vPlayer.getName(), codes);
+ if (file == null)
+ {
+ return false;
+ }
+ PrivateChannel privateChannel = user.openPrivateChannel().complete();
+ privateChannel.sendMessage("Do not share these codes with anyone as they can be used to impose as you.").addFile(file).complete();
+ vPlayer.setBackupCodes(encryptedCodes);
+ plugin.pv.saveVerificationData(vPlayer);
+ file.delete();
+ return true;
+ }
+
+ public boolean sendBackupCodes(Admin admin)
+ {
+ List codes = generateBackupCodes();
+ List encryptedCodes = generateEncryptedBackupCodes(codes);
+ net.dv8tion.jda.api.entities.User user = bot.getUserById(admin.getDiscordID());
+ File file = generateBackupCodesFile(admin.getName(), codes);
+ if (file == null)
+ {
+ return false;
+ }
+ PrivateChannel privateChannel = user.openPrivateChannel().complete();
+ privateChannel.sendMessage("Do not share these codes with anyone as they can be used to impose as you.").addFile(file).complete();
+ admin.setBackupCodes(encryptedCodes);
+ plugin.al.save();
+ plugin.al.updateTables();
+ file.delete();
+ return true;
+ }
+
+ public boolean sendBackupCodes(MasterBuilder masterBuilder)
+ {
+ List codes = generateBackupCodes();
+ List encryptedCodes = generateEncryptedBackupCodes(codes);
+ net.dv8tion.jda.api.entities.User user = bot.getUserById(masterBuilder.getDiscordID());
+ File file = generateBackupCodesFile(masterBuilder.getName(), codes);
+ if (file == null)
+ {
+ return false;
+ }
+ PrivateChannel privateChannel = user.openPrivateChannel().complete();
+ privateChannel.sendMessage("Do not share these codes with anyone as they can be used to impose as you.").addFile(file).complete();
+ masterBuilder.setBackupCodes(encryptedCodes);
+ plugin.mbl.save();
+ plugin.mbl.updateTables();
+ file.delete();
+ return true;
+ }
+
+ public List generateBackupCodes()
+ {
+ List codes = new ArrayList<>();
+ for (int i = 0; i < 10; i++)
+ {
+ codes.add(randomString(10));
+ }
+ return codes;
+ }
+
+ public String randomString(int size)
+ {
+ List chars = Arrays.asList("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz".split("(?!^)"));
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < size; i++)
+ {
+ stringBuilder.append(chars.get(random.nextInt(chars.size())));
+ }
+ return stringBuilder.toString();
+ }
+
+ public String generateCode(int size)
+ {
+ String code = "";
+ Random random = new Random();
+ for (int i = 0; i < size; i++)
+ {
+ code += random.nextInt(10);
+ }
+ return code;
+ }
+
+ public List generateEncryptedBackupCodes(List codes)
+ {
+ List encryptedCodes = new ArrayList<>();
+ for (String code : codes)
+ {
+ encryptedCodes.add(getMD5(code));
+ }
+ return encryptedCodes;
+ }
+
+ public File generateBackupCodesFile(String name, List codes)
+ {
+ StringBuilder text = new StringBuilder();
+ text.append("Below are your backup codes for use on TotalFreedom in the event you lose access to your discord account.\n")
+ .append("Simply pick a code, and run /verify on the server. Each code is one use, so be sure to cross it off once you use it.\n")
+ .append("To generate new codes, simply run /generatebackupcodes\n\n");
+
+ for (String code : codes)
+ {
+ text.append(code + "\n");
+ }
+
+ String fileUrl = plugin.getDataFolder().getAbsolutePath() + "/TF-Backup-Codes-" + name + ".txt";
+ try
+ {
+ FileWriter fileWriter = new FileWriter(fileUrl);
+ fileWriter.write(text.toString());
+ fileWriter.close();
+ }
+ catch (IOException e)
+ {
+ FLog.severe("Failed to generate backup codes file: " + e.toString());
+ return null;
+ }
+ return new File(fileUrl);
+ }
+
+ public static String getMD5(String string)
+ {
+ return DigestUtils.md5Hex(string);
+ }
+
+ public void addPlayerVerificationCode(String code, VPlayer vPlayer)
+ {
+ PLAYER_VERIFICATION_CODES.put(code, vPlayer);
+ }
+
+ public void removePlayerVerificationCode(String code)
+ {
+ PLAYER_VERIFICATION_CODES.remove(code);
+ }
+
+ public HashMap getPlayerVerificationCodes()
+ {
+ return PLAYER_VERIFICATION_CODES;
+ }
+
+ public void addAdminVerificationCode(String code, Admin admin)
+ {
+ ADMIN_VERIFICATION_CODES.put(code, admin);
+ }
+
+ public void removeAdminVerificationCode(String code)
+ {
+ ADMIN_VERIFICATION_CODES.remove(code);
+ }
+
+ public HashMap getAdminVerificationCodes()
+ {
+ return ADMIN_VERIFICATION_CODES;
+ }
+
+ public void addMasterBuilderVerificationCode(String code, MasterBuilder masterBuilder)
+ {
+ MASTER_BUILDER_VERIFICATION_CODES.put(code, masterBuilder);
+ }
+
+ public void removeMasterBuilderVerificationCode(String code)
+ {
+ MASTER_BUILDER_VERIFICATION_CODES.remove(code);
+ }
+
+ public HashMap getMasterBuilderVerificationCodes()
+ {
+ return MASTER_BUILDER_VERIFICATION_CODES;
+ }
+
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event)
{
@@ -157,7 +372,8 @@ public class Discord extends FreedomService
}
if (enabled && !chat_channel_id.isEmpty())
{
- bot.getTextChannelById(chat_channel_id).sendMessage(message).queue();
+ CompletableFuture sentMessage = bot.getTextChannelById(chat_channel_id).sendMessage(message).submit(true);
+ sentMessages.add(sentMessage);
}
}
@@ -169,9 +385,9 @@ public class Discord extends FreedomService
public static String getCodeForAdmin(Admin admin)
{
- for (String code : LINK_CODES.keySet())
+ for (String code : ADMIN_LINK_CODES.keySet())
{
- if (LINK_CODES.get(code).equals(admin))
+ if (ADMIN_LINK_CODES.get(code).equals(admin))
{
return code;
}
@@ -191,6 +407,18 @@ public class Discord extends FreedomService
return null;
}
+ public static String getCodeForMasterBuilder(MasterBuilder masterBuilder)
+ {
+ for (String code : MASTER_BUILDER_LINK_CODES.keySet())
+ {
+ if (MASTER_BUILDER_LINK_CODES.get(code).equals(masterBuilder))
+ {
+ return code;
+ }
+ }
+ return null;
+ }
+
@Override
protected void onStop()
{
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/discord/PrivateMessageListener.java b/src/main/java/me/totalfreedom/totalfreedommod/discord/PrivateMessageListener.java
index dc1a6836..efca196a 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/discord/PrivateMessageListener.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/discord/PrivateMessageListener.java
@@ -2,6 +2,7 @@ package me.totalfreedom.totalfreedommod.discord;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.Admin;
+import me.totalfreedom.totalfreedommod.masterbuilder.MasterBuilder;
import me.totalfreedom.totalfreedommod.playerverification.VPlayer;
import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -16,26 +17,42 @@ public class PrivateMessageListener extends ListenerAdapter
if (event.getMessage().getContentRaw().matches("[0-9][0-9][0-9][0-9][0-9]"))
{
String code = event.getMessage().getContentRaw();
- if (Discord.LINK_CODES.get(code) != null)
+ String name;
+ if (Discord.ADMIN_LINK_CODES.get(code) != null)
{
- Admin admin = Discord.LINK_CODES.get(code);
+ Admin admin = Discord.ADMIN_LINK_CODES.get(code);
+ name = admin.getName();
admin.setDiscordID(event.getMessage().getAuthor().getId());
- Discord.LINK_CODES.remove(code);
- event.getChannel().sendMessage("Link successful. Now this Discord account is linked with your Minecraft account `" + admin.getName() + "`.\n"
- + "Now when you are an impostor on the server, you may use `/verify` to verify.").complete();
+ TotalFreedomMod.plugin().al.save();
+ TotalFreedomMod.plugin().al.updateTables();
+ Discord.ADMIN_LINK_CODES.remove(code);
Discord.syncRoles(admin);
}
- if (Discord.PLAYER_LINK_CODES.get(code) != null)
+ else if (Discord.PLAYER_LINK_CODES.get(code) != null)
{
VPlayer player = Discord.PLAYER_LINK_CODES.get(code);
+ name = player.getName();
player.setDiscordId(event.getMessage().getAuthor().getId());
player.setEnabled(true);
TotalFreedomMod.plugin().pv.saveVerificationData(player);
Discord.PLAYER_LINK_CODES.remove(code);
- event.getChannel().sendMessage("Link successful. Now this Discord account is linked with your Minecraft account `" + player.getName() + "`.\n"
- + "Now when you are an impostor on the server, you may use `/verify` to verify.").complete();
}
+ else if (Discord.MASTER_BUILDER_LINK_CODES.get(code) != null)
+ {
+ MasterBuilder masterBuilder = Discord.MASTER_BUILDER_LINK_CODES.get(code);
+ name = masterBuilder.getName();
+ masterBuilder.setDiscordID(event.getMessage().getAuthor().getId());
+ TotalFreedomMod.plugin().mbl.save();
+ TotalFreedomMod.plugin().mbl.updateTables();
+ Discord.MASTER_BUILDER_LINK_CODES.remove(code);
+ }
+ else
+ {
+ return;
+ }
+ event.getChannel().sendMessage("Link successful. Now this Discord account is linked with your Minecraft account **" + name + "**.\n"
+ + "Now when you are an impostor on the server, you may use `/verify` to verify.").complete();
}
}
}
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/masterbuilder/MasterBuilder.java b/src/main/java/me/totalfreedom/totalfreedommod/masterbuilder/MasterBuilder.java
index c21939cd..f4a8f4af 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/masterbuilder/MasterBuilder.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/masterbuilder/MasterBuilder.java
@@ -1,6 +1,7 @@
package me.totalfreedom.totalfreedommod.masterbuilder;
import com.google.common.collect.Lists;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import lombok.Getter;
@@ -25,6 +26,7 @@ public class MasterBuilder implements ConfigLoadable, ConfigSavable, Validatable
private String name;
@Getter
private final List ips = Lists.newArrayList();
+ private final List backupCodes = Lists.newArrayList();
@Getter
@Setter
private Date lastLogin = new Date();
@@ -62,7 +64,8 @@ public class MasterBuilder implements ConfigLoadable, ConfigSavable, Validatable
.append("- Last Login: ").append(FUtil.dateToString(lastLogin)).append("\n")
.append("- Discord ID: ").append(discordID).append("\n")
.append("- Tag: ").append(tag).append("\n")
- .append("- Clear Chat Opt Out: ").append(clearChatOptOut);
+ .append("- Clear Chat Opt Out: ").append(clearChatOptOut)
+ .append("- Backup Codes: ").append(backupCodes.size()).append("/10").append("\n");
return output.toString();
}
@@ -81,6 +84,8 @@ public class MasterBuilder implements ConfigLoadable, ConfigSavable, Validatable
name = cs.getString("username", configKey);
ips.clear();
ips.addAll(cs.getStringList("ips"));
+ backupCodes.clear();
+ backupCodes.addAll(cs.getStringList("backupCodes"));
lastLogin = FUtil.stringToDate(cs.getString("last_login"));
discordID = cs.getString("discord_id", null);
tag = cs.getString("tag", null);
@@ -93,6 +98,7 @@ public class MasterBuilder implements ConfigLoadable, ConfigSavable, Validatable
Validate.isTrue(isValid(), "Could not save master builder entry: " + name + ". Entry not valid!");
cs.set("username", name);
cs.set("ips", Lists.newArrayList(ips));
+ cs.set("backupCodes", Lists.newArrayList(backupCodes));
cs.set("last_login", FUtil.dateToString(lastLogin));
cs.set("discord_id", discordID);
cs.set("tag", tag);
@@ -125,6 +131,22 @@ public class MasterBuilder implements ConfigLoadable, ConfigSavable, Validatable
ips.clear();
}
+ public List getBackupCodes()
+ {
+ return Collections.unmodifiableList(backupCodes);
+ }
+
+ public void setBackupCodes(List codes)
+ {
+ backupCodes.clear();
+ backupCodes.addAll(codes);
+ }
+
+ public void removeBackupCode(String code)
+ {
+ backupCodes.remove(code);
+ }
+
@Override
public boolean isValid()
{
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/playerverification/PlayerVerification.java b/src/main/java/me/totalfreedom/totalfreedommod/playerverification/PlayerVerification.java
index 40c0a492..17e290fa 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/playerverification/PlayerVerification.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/playerverification/PlayerVerification.java
@@ -51,7 +51,7 @@ public class PlayerVerification extends FreedomService
&& !vPlayer.getIps().contains(Ips.getIp(player));
}
- public void verifyPlayer(Player player)
+ public void verifyPlayer(Player player, String backupCode)
{
if (!isPlayerImpostor(player))
{
@@ -59,6 +59,10 @@ public class PlayerVerification extends FreedomService
}
VPlayer vPlayer = getVerificationPlayer(player);
+ if (backupCode != null)
+ {
+ vPlayer.removeBackupCode(backupCode);
+ }
vPlayer.addIp(Ips.getIp(player));
dataMap.put(player.getName(), vPlayer);
YamlConfig config = getConfig(vPlayer);
diff --git a/src/main/java/me/totalfreedom/totalfreedommod/playerverification/VPlayer.java b/src/main/java/me/totalfreedom/totalfreedommod/playerverification/VPlayer.java
index f28b0b1d..4f1d5535 100644
--- a/src/main/java/me/totalfreedom/totalfreedommod/playerverification/VPlayer.java
+++ b/src/main/java/me/totalfreedom/totalfreedommod/playerverification/VPlayer.java
@@ -2,14 +2,16 @@ package me.totalfreedom.totalfreedommod.playerverification;
import com.google.common.collect.Lists;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import lombok.Getter;
import lombok.Setter;
+import me.totalfreedom.totalfreedommod.util.FLog;
import net.pravian.aero.base.ConfigLoadable;
import net.pravian.aero.base.ConfigSavable;
import net.pravian.aero.base.Validatable;
import org.apache.commons.lang.Validate;
-import org.bukkit.ChatColor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
@@ -17,6 +19,8 @@ public class VPlayer implements ConfigLoadable, ConfigSavable, Validatable
{
private final List ips = Lists.newArrayList();
+ private final List