diff --git a/Plugins/Mineplex.Core/pom.xml b/Plugins/Mineplex.Core/pom.xml index 06ecb566d..a2d2f6e3e 100644 --- a/Plugins/Mineplex.Core/pom.xml +++ b/Plugins/Mineplex.Core/pom.xml @@ -50,6 +50,16 @@ xz 1.5 + + com.warrenstrange + googleauth + 1.1.1 + + + com.google.zxing + core + 3.3.0 + diff --git a/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorAuth.java b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorAuth.java new file mode 100644 index 000000000..a55271856 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorAuth.java @@ -0,0 +1,320 @@ +package mineplex.core.twofactor; + +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.map.MapRenderer; +import org.bukkit.map.MapView; +import org.bukkit.metadata.FixedMetadataValue; + +import com.warrenstrange.googleauth.GoogleAuthenticator; + +import mineplex.core.Managers; +import mineplex.core.MiniClientPlugin; +import mineplex.core.ReflectivelyCreateMiniPlugin; +import mineplex.core.account.CoreClientManager; +import mineplex.core.command.CommandBase; +import mineplex.core.common.Rank; +import mineplex.core.common.util.BukkitFuture; +import mineplex.core.common.util.F; +import mineplex.core.recharge.Recharge; +import mineplex.serverdata.database.DBPool; + +@ReflectivelyCreateMiniPlugin +public class TwoFactorAuth extends MiniClientPlugin +{ + private static final String TFA_SETUP = "twofactor:setup"; + private static final String TFA_AUTHENTICATING = "twofactor:authenticating"; + + private static final GoogleAuthenticator authenticator = new GoogleAuthenticator(); + private final CoreClientManager _clientManager = Managers.require(CoreClientManager.class); + private final TwoFactorRepository _repository = new TwoFactorRepository(DBPool.getAccount()); + + public TwoFactorAuth() + { + super("Two-factor Authentication"); + _clientManager.addStoredProcedureLoginProcessor( + _repository.buildSecretKeyLoginProcessor((uuid, secretKey) -> Get(uuid).setSecretKey(secretKey)) + ); + _clientManager.addStoredProcedureLoginProcessor( + _repository.buildLastIpLoginProcessor((uuid, ip) -> Get(uuid).setLastLoginIp(ip)) + ); + } + + @Override + public void addCommands() + { + // TODO: remove this when we start enforcing 2FA + addCommand(new CommandBase(this, Rank.MAPDEV, "2fa", "tfa") + { + @Override + public void Execute(Player caller, String[] args) + { + TwoFactorData data = Get(caller); + if (data.getSecretKey().isPresent()) + { + caller.sendMessage(F.main("2FA", "You already have 2FA enabled.")); + return; + } + + setup2FA(caller); + } + }); + } + + private void setup2FA(Player player) + { + String secret = authenticator.createCredentials().getKey(); + + MapView view = Bukkit.createMap(player.getWorld()); + for (MapRenderer renderer : view.getRenderers()) + { + view.removeRenderer(renderer); + } + view.addRenderer(new TwoFactorMapRenderer(player, secret)); + + ItemStack stack = new ItemStack(Material.MAP); + stack.setDurability(view.getId()); + + // Find first free hotbar slot + int slot = 0; + for (int i = 0; i < 9; i++) + { + if (player.getInventory().getItem(i) == null) + { + slot = i; + break; + } + } + + player.getInventory().setHeldItemSlot(slot); + player.getInventory().setItemInHand(stack); + + player.setMetadata(TFA_SETUP, new FixedMetadataValue(_plugin, secret)); + player.sendMessage(F.main("2FA", "Setting up two-factor authentication.")); + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) + { + Player player = event.getPlayer(); + + TwoFactorData data = Get(player); + + if (data.getLastLoginIp().isPresent() && player.getAddress().getAddress().toString().substring(1).equals(data.getLastLoginIp().get())) + { + player.sendMessage(F.main("2FA", "Authenticated")); + return; + } + + if (data.getSecretKey().isPresent()) + { + // Hooray 2FA + player.sendMessage(F.main("2FA", "Please enter your two-factor auth code")); + player.setMetadata(TFA_AUTHENTICATING, new FixedMetadataValue(_plugin, true)); + } + else + { + // 2FA not set up yet. TODO: enforce this at a later date. + } + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP)) + { + player.setItemInHand(null); + player.removeMetadata(TFA_SETUP, _plugin); + } + player.removeMetadata(TFA_AUTHENTICATING, _plugin); + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onChat(AsyncPlayerChatEvent event) + { + Player player = event.getPlayer(); + + String secret = null; + if (player.hasMetadata(TFA_SETUP)) + { + secret = player.getMetadata(TFA_SETUP).get(0).asString(); + } + else if (player.hasMetadata(TFA_AUTHENTICATING)) + { + secret = Get(player).getSecretKey().get(); + } + + if (secret == null) + { + return; + } + + // Hooray 2FA - let's see if their message matches their auth code + + event.setCancelled(true); + + int code; + try + { + code = Integer.parseInt(event.getMessage()); + } + catch (NumberFormatException e) + { + player.sendMessage(F.main("2FA", "Invalid authentication code (not a number).")); + return; + } + + if (!authenticator.authorize(secret, code)) + { + player.sendMessage(F.main("2FA", "Invalid authentication code.")); + return; + } + + // Success! + + player.sendMessage(F.main("2FA", "Authorized for 24 hours.")); + + if (player.hasMetadata(TFA_SETUP)) + { + // Remove setup map + save secret + player.setItemInHand(null); + Get(player).setSecretKey(secret); + + player.sendMessage(F.main("2FA", "Saving secret..")); + _repository.saveSecret(player, secret).whenComplete(BukkitFuture.complete((v, throwable) -> + { + if (!player.isOnline()) + { + return; + } + + if (throwable != null) + { + Get(player).setSecretKey(null); + player.sendMessage(F.main("2FA", "Something went wrong. Please try again in a moment.")); + } + else + { + player.sendMessage(F.main("2FA", "Secret key saved.")); + } + })); + } + + _repository.saveLogin(player, player.getAddress().getAddress().toString().substring(1)); + + player.removeMetadata(TFA_SETUP, _plugin); + player.removeMetadata(TFA_AUTHENTICATING, _plugin); + } + + // Cancel relevant events + + @EventHandler(ignoreCancelled = true) + public void onChangeHeldItem(PlayerItemHeldEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onClick(InventoryClickEvent event) + { + Player player = (Player) event.getWhoClicked(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onDrag(InventoryDragEvent event) + { + Player player = (Player) event.getWhoClicked(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onDrop(PlayerDropItemEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onInteract(PlayerInteractEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onInteractWithEntity(PlayerInteractEntityEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onCommand(PlayerCommandPreprocessEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + event.setMessage("/"); + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onMove(PlayerMoveEvent event) + { + Player player = event.getPlayer(); + if (player.hasMetadata(TFA_SETUP) || player.hasMetadata(TFA_AUTHENTICATING)) + { + if (Recharge.Instance.use(player, "two-factor message cooldown", 3000L, false, false)) + { + player.sendMessage(F.main("2FA", "Please enter your two-factor auth code")); + } + event.getTo().setX(event.getFrom().getX()); + event.getTo().setZ(event.getFrom().getZ()); + } + } + + @Override + protected TwoFactorData addPlayer(UUID uuid) + { + return new TwoFactorData(); + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorData.java b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorData.java new file mode 100644 index 000000000..faff1adb3 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorData.java @@ -0,0 +1,29 @@ +package mineplex.core.twofactor; + +import java.util.Optional; + +public class TwoFactorData +{ + private String _secretKey; + private String _lastIp; + + public Optional getSecretKey() + { + return Optional.ofNullable(_secretKey); + } + + public Optional getLastLoginIp() + { + return Optional.ofNullable(_lastIp); + } + + public void setSecretKey(String secretKey) + { + _secretKey = secretKey; + } + + public void setLastLoginIp(String lastIp) + { + _lastIp = lastIp; + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorMapRenderer.java b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorMapRenderer.java new file mode 100644 index 000000000..178ba775a --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorMapRenderer.java @@ -0,0 +1,155 @@ +package mineplex.core.twofactor; + +import java.util.Arrays; + +import org.bukkit.entity.Player; +import org.bukkit.map.MapCanvas; +import org.bukkit.map.MapFont; +import org.bukkit.map.MapRenderer; +import org.bukkit.map.MapView; +import org.bukkit.map.MinecraftFont; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.QRCodeWriter; + +public class TwoFactorMapRenderer extends MapRenderer +{ + private static final String SETUP_TEXT = + "\u00A7100;Two-factor Auth Setup\n\n" + + "\u00A744;1. Use your device to\n" + + "scan the QR code, or\n" + + "enter your \u00A716;secret code:\n" + + "\u00A728;%s\n\n" + + "\u00A744;2. Type the\n" + + "code from\n" + + "the app\n" + + "in chat."; + private static final MapFont FONT = MinecraftFont.Font; + private static final byte QR_COLOR = (byte)116; // Black + private static final QRCodeWriter writer = new QRCodeWriter(); + + private final Player _player; + private final byte[][] contents = new byte[128][128]; + + public TwoFactorMapRenderer(Player player, String secret) + { + _player = player; + + BitMatrix matrix; + try + { + matrix = writer.encode(String.format("otpauth://totp/%s?secret=%s&issuer=Mineplex", _player.getName(), secret), BarcodeFormat.QR_CODE, 32, 32, ImmutableMap.of(EncodeHintType.MARGIN, 0)); + + } + catch (WriterException e) + { + e.printStackTrace(); + return; + } + + // Set background color to white + for (byte[] column : contents) + { + Arrays.fill(column, (byte)32); + } + + String spacedSecret = Joiner.on(' ').join(Splitter.fixedLength(4).split(secret)); + renderText(contents, 2, 2, String.format(SETUP_TEXT, spacedSecret)); + renderQR(contents, 62, 62, matrix, 2); + + } + + private static void renderText(byte[][] contents, int startX, int startY, String text) + { + int x = startX; + int y = startY; + byte color = (byte)44; + + for (int i = 0; i < text.length(); i++) + { + char c = text.charAt(i); + if (c == '\n') + { + x = startX; + y += FONT.getHeight() + 1; + continue; + } + + if (c == '\u00A7') + { + int end = text.indexOf(';', i); + if (end >= 0) + { + color = Byte.parseByte(text.substring(i+1, end)); + i = end; + continue; + } + } + + MapFont.CharacterSprite sprite = FONT.getChar(c); + for (int k = 0; k < sprite.getWidth(); k++) + { + for (int l = 0; l < FONT.getHeight(); l++) + { + if (sprite.get(l, k)) + { + if (x+k >= 128 || y+l >= 128) + { + continue; + } + contents[x+k][y+l] = color; + } + } + } + x += sprite.getWidth() + 1; + } + } + + private static void renderQR(byte[][] contents, int x, int y, BitMatrix matrix, int scale) + { + for (int matrixX = 0 ; matrixX < matrix.getWidth(); matrixX++) + { + for (int matrixY = 0; matrixY < matrix.getHeight(); matrixY++) + { + + if (matrix.get(matrixX, matrixY)) + { + for (int i = 0; i < scale; i++) + { + for (int k = 0; k < scale; k++) + { + if (x + (matrixX * scale) + i >= 128 || y + (matrixY * scale) + k >= 128) + { + continue; + } + contents[x + (matrixX * scale) + i][y + (matrixY * scale) + k] = QR_COLOR; + } + } + } + } + } + } + + @Override + public void render(MapView mapView, MapCanvas mapCanvas, Player player) + { + if (player != _player) + { + return; + } + + for (int x = 0; x < 128; x++) + { + for (int y = 0; y < 128; y++) + { + mapCanvas.setPixel(x, y, contents[x][y]); + } + } + } +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorRepository.java new file mode 100644 index 000000000..20d5810b0 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/twofactor/TwoFactorRepository.java @@ -0,0 +1,124 @@ +package mineplex.core.twofactor; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.function.BiConsumer; + +import org.bukkit.entity.Player; + +import mineplex.core.Managers; +import mineplex.core.account.CoreClientManager; +import mineplex.core.account.ILoginProcessor; + +public class TwoFactorRepository +{ + private static final String INSERT_SECRET_KEY = "INSERT INTO twofactor (accountId,secretKey) VALUES (?,?);"; + private static final String INSERT_LOGIN = "INSERT INTO twofactor_history (accountId,ip,loginTime) VALUES (?,?,NOW());"; + private final CoreClientManager _clientManager = Managers.require(CoreClientManager.class); + private final DataSource _dataSource; + + public TwoFactorRepository(DataSource source) + { + _dataSource = source; + } + + public ILoginProcessor buildSecretKeyLoginProcessor(BiConsumer consumer) + { + return new ILoginProcessor() + { + @Override + public String getName() + { + return "Two-factor auth secret key grabber"; + } + + @Override + public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException + { + if (resultSet.next()) + { + consumer.accept(uuid, resultSet.getString(1)); + } + } + + @Override + public String getQuery(int accountId, String uuid, String name) + { + return "SELECT secretKey FROM twofactor WHERE accountId=" + accountId + ";"; + } + }; + } + + public ILoginProcessor buildLastIpLoginProcessor(BiConsumer consumer) + { + return new ILoginProcessor() + { + @Override + public String getName() + { + return "Two-factor auth last login grabber"; + } + + @Override + public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException + { + if (resultSet.next()) + { + consumer.accept(uuid, resultSet.getString(1)); + } + } + + @Override + public String getQuery(int accountId, String uuid, String name) + { + return "SELECT ip FROM twofactor_history WHERE accountId=" + accountId + " AND loginTime >= DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY loginTime DESC;"; + } + }; + } + + public CompletableFuture saveSecret(Player player, String secret) + { + int accountId = _clientManager.Get(player).getAccountId(); + + return CompletableFuture.runAsync(() -> + { + try (Connection connection = _dataSource.getConnection()) + { + PreparedStatement statement = connection.prepareStatement(INSERT_SECRET_KEY); + statement.setInt(1, accountId); + statement.setString(2, secret); + statement.executeUpdate(); + } + catch (SQLException e) + { + throw new CompletionException(e); + } + }); + } + + public CompletableFuture saveLogin(Player player, String ip) + { + int accountId = _clientManager.Get(player).getAccountId(); + + return CompletableFuture.runAsync(() -> + { + try (Connection connection = _dataSource.getConnection()) + { + PreparedStatement statement = connection.prepareStatement(INSERT_LOGIN); + statement.setInt(1, accountId); + statement.setString(2, ip); + statement.executeUpdate(); + } + catch (SQLException e) + { + throw new CompletionException(e); + } + }); + } +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java index d865e5d6e..5c091c8a8 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/Clans.java @@ -1,5 +1,15 @@ package mineplex.game.clans; +import net.minecraft.server.v1_8_R3.MinecraftServer; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.plugin.java.JavaPlugin; +import org.spigotmc.SpigotConfig; + import mineplex.core.CustomTagFix; import mineplex.core.FoodDupeFix; import mineplex.core.TimingsFix; @@ -48,6 +58,7 @@ import mineplex.core.spawn.Spawn; import mineplex.core.stats.StatsManager; import mineplex.core.status.ServerStatusManager; import mineplex.core.teleport.Teleport; +import mineplex.core.twofactor.TwoFactorAuth; import mineplex.core.updater.FileUpdater; import mineplex.core.updater.Updater; import mineplex.core.visibility.VisibilityManager; @@ -60,14 +71,6 @@ import mineplex.game.clans.shop.mining.MiningShop; import mineplex.game.clans.shop.pvp.PvpShop; import mineplex.game.clans.spawn.travel.TravelShop; import mineplex.game.clans.world.WorldManager; -import net.minecraft.server.v1_8_R3.MinecraftServer; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; -import org.bukkit.plugin.java.JavaPlugin; -import org.spigotmc.SpigotConfig; import static mineplex.core.Managers.require; @@ -261,6 +264,8 @@ public class Clans extends JavaPlugin new MiningShop(_clansManager, _clientManager, _donationManager); new WorldManager(this); + require(TwoFactorAuth.class); + // Disable spigot item merging for (World world : getServer().getWorlds()) { diff --git a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java index 04cf7bd71..235791a86 100644 --- a/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java +++ b/Plugins/Mineplex.Hub.Clans/src/mineplex/clanshub/ClansHub.java @@ -1,5 +1,9 @@ package mineplex.clanshub; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.plugin.java.JavaPlugin; + import mineplex.core.CustomTagFix; import mineplex.core.PacketsInteractionFix; import mineplex.core.account.CoreClientManager; @@ -39,6 +43,7 @@ import mineplex.core.preferences.PreferencesManager; import mineplex.core.profileCache.ProfileCacheManager; import mineplex.core.punish.Punish; import mineplex.core.rankGiveaway.eternal.EternalGiveawayManager; +import mineplex.core.rankGiveaway.titangiveaway.TitanGiveawayManager; import mineplex.core.recharge.Recharge; import mineplex.core.resourcepack.ResourcePackManager; import mineplex.core.serverConfig.ServerConfiguration; @@ -47,9 +52,9 @@ import mineplex.core.status.ServerStatusManager; import mineplex.core.task.TaskManager; import mineplex.core.teleport.Teleport; import mineplex.core.thank.ThankManager; -import mineplex.core.rankGiveaway.titangiveaway.TitanGiveawayManager; import mineplex.core.titles.Titles; import mineplex.core.titles.tracks.TrackManager; +import mineplex.core.twofactor.TwoFactorAuth; import mineplex.core.updater.FileUpdater; import mineplex.core.updater.Updater; import mineplex.core.velocity.VelocityFix; @@ -57,9 +62,6 @@ import mineplex.core.visibility.VisibilityManager; import mineplex.minecraft.game.core.combat.CombatManager; import mineplex.minecraft.game.core.condition.ConditionManager; import mineplex.minecraft.game.core.damage.DamageManager; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.plugin.java.JavaPlugin; import static mineplex.core.Managers.require; @@ -175,6 +177,7 @@ public class ClansHub extends JavaPlugin require(TrackManager.class); require(Titles.class); + require(TwoFactorAuth.class); } @Override diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java index cd87eaf8e..492f1fa1f 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java @@ -52,6 +52,7 @@ import mineplex.core.profileCache.ProfileCacheManager; import mineplex.core.projectile.ProjectileManager; import mineplex.core.punish.Punish; import mineplex.core.rankGiveaway.eternal.EternalGiveawayManager; +import mineplex.core.rankGiveaway.titangiveaway.TitanGiveawayManager; import mineplex.core.recharge.Recharge; import mineplex.core.report.ReportManager; import mineplex.core.report.ReportPlugin; @@ -63,7 +64,9 @@ import mineplex.core.status.ServerStatusManager; import mineplex.core.task.TaskManager; import mineplex.core.teleport.Teleport; import mineplex.core.thank.ThankManager; -import mineplex.core.rankGiveaway.titangiveaway.TitanGiveawayManager; +import mineplex.core.titles.Titles; +import mineplex.core.titles.tracks.TrackManager; +import mineplex.core.twofactor.TwoFactorAuth; import mineplex.core.updater.FileUpdater; import mineplex.core.updater.Updater; import mineplex.core.velocity.VelocityFix; @@ -71,8 +74,6 @@ import mineplex.core.visibility.VisibilityManager; import mineplex.hub.modules.BillboardManager; import mineplex.hub.queue.QueueManager; import mineplex.hub.server.ServerManager; -import mineplex.core.titles.Titles; -import mineplex.core.titles.tracks.TrackManager; import mineplex.minecraft.game.classcombat.Class.ClassManager; import mineplex.minecraft.game.classcombat.Condition.SkillConditionManager; import mineplex.minecraft.game.classcombat.Skill.SkillFactory; @@ -232,6 +233,7 @@ public class Hub extends JavaPlugin implements IRelation require(TrackManager.class); require(Titles.class); + require(TwoFactorAuth.class); } @Override diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java b/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java index 5b65fd27a..4a0bec73e 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/HubManager.java @@ -136,7 +136,7 @@ import net.minecraft.server.v1_8_R3.EntityPlayer; public class HubManager extends MiniClientPlugin implements IChatMessageFormatter { // ☃❅ Snowman! - public HubType Type = HubType.Christmas; + public HubType Type = HubType.Normal; private BlockRestore _blockRestore; private CoreClientManager _clientManager; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java index 5f8828c95..dff9c1246 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java @@ -1,36 +1,44 @@ package nautilus.game.arcade; +import java.io.File; +import java.util.HashMap; + +import net.minecraft.server.v1_8_R3.MinecraftServer; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.spigotmc.SpigotConfig; + import mineplex.core.CustomTagFix; import mineplex.core.FoodDupeFix; import mineplex.core.PacketsInteractionFix; import mineplex.core.TimingsFix; -import mineplex.core.antihack.logging.AntihackLogger; -import mineplex.core.chatsnap.SnapshotRepository; -import mineplex.core.customdata.CustomDataManager; -import mineplex.core.chatsnap.SnapshotManager; -import mineplex.core.chatsnap.SnapshotPlugin; -import mineplex.core.globalpacket.GlobalPacketManager; -import net.minecraft.server.v1_8_R3.BiomeBase; -import net.minecraft.server.v1_8_R3.MinecraftServer; import mineplex.core.account.CoreClientManager; import mineplex.core.achievement.AchievementManager; import mineplex.core.antihack.AntiHack; +import mineplex.core.antihack.logging.AntihackLogger; import mineplex.core.blockrestore.BlockRestore; import mineplex.core.blood.Blood; import mineplex.core.boosters.BoosterManager; import mineplex.core.chat.Chat; +import mineplex.core.chatsnap.SnapshotManager; +import mineplex.core.chatsnap.SnapshotPlugin; +import mineplex.core.chatsnap.SnapshotRepository; import mineplex.core.command.CommandCenter; import mineplex.core.common.events.ServerShutdownEvent; import mineplex.core.common.util.FileUtil; import mineplex.core.common.util.UtilServer; import mineplex.core.cosmetic.CosmeticManager; import mineplex.core.creature.Creature; +import mineplex.core.customdata.CustomDataManager; import mineplex.core.disguise.DisguiseManager; import mineplex.core.donation.DonationManager; import mineplex.core.elo.EloManager; import mineplex.core.friend.FriendManager; import mineplex.core.gadget.GadgetManager; import mineplex.core.give.Give; +import mineplex.core.globalpacket.GlobalPacketManager; import mineplex.core.hologram.HologramManager; import mineplex.core.ignore.IgnoreManager; import mineplex.core.incognito.IncognitoManager; @@ -58,8 +66,7 @@ import mineplex.core.stats.StatsManager; import mineplex.core.status.ServerStatusManager; import mineplex.core.teleport.Teleport; import mineplex.core.thank.ThankManager; -import mineplex.core.titles.Titles; -import mineplex.core.titles.tracks.TrackManager; +import mineplex.core.twofactor.TwoFactorAuth; import mineplex.core.updater.FileUpdater; import mineplex.core.updater.Updater; import mineplex.core.velocity.VelocityFix; @@ -69,15 +76,6 @@ import mineplex.minecraft.game.core.damage.DamageManager; import nautilus.game.arcade.anticheatmetadata.GameInfoMetadata; import nautilus.game.arcade.game.GameServerConfig; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.spigotmc.SpigotConfig; - -import java.io.File; -import java.util.HashMap; - import static mineplex.core.Managers.require; public class Arcade extends JavaPlugin @@ -198,6 +196,8 @@ public class Arcade extends JavaPlugin new CustomTagFix(this, packetHandler); new PacketsInteractionFix(this, packetHandler); new FoodDupeFix(this); + + require(TwoFactorAuth.class); //Updates getServer().getScheduler().scheduleSyncRepeatingTask(this, new Updater(this), 1, 1); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java index b41df5c9c..d2864e5e5 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/game/Game.java @@ -292,7 +292,7 @@ public abstract class Game implements Listener public long PrepareTime = 9000; public boolean PlaySoundGameStart = true; - public double XpMult = 2; + public double XpMult = 1; public boolean SpeedMeasurement = false; diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameRewardManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameRewardManager.java index 12d448581..4c8db7903 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameRewardManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameRewardManager.java @@ -44,7 +44,7 @@ public class GameRewardManager implements Listener { ArcadeManager Manager; - boolean DoubleGem = true; + boolean DoubleGem = false; boolean TimeReward = true; public GameRewardManager(ArcadeManager manager) @@ -352,7 +352,7 @@ public class GameRewardManager implements Listener //Double Gem if (DoubleGem && game.GemDoubleEnabled) { - UtilPlayer.message(player, F.elem(C.cGreen + "+" + (earnedGems) + " Gems") + " for " + F.elem(C.cDGreen + "Holiday Double Gems")); + UtilPlayer.message(player, F.elem(C.cGreen + "+" + (earnedGems) + " Gems") + " for " + F.elem(C.cDGreen + "Double Gem Weekend")); totalGems += earnedGems; }