diff --git a/src/main/java/org/xgqy/survival/AccountManager.java b/src/main/java/org/xgqy/survival/AccountManager.java new file mode 100644 index 0000000..d60cc70 --- /dev/null +++ b/src/main/java/org/xgqy/survival/AccountManager.java @@ -0,0 +1,125 @@ +package org.xgqy.survival; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; + +import java.io.File; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class AccountManager { + private final Survival plugin; + private final File accountsFile; + private final FileConfiguration accountsConfig; + private final Map accounts = new HashMap<>(); + private final Map loggedInPlayers = new HashMap<>(); + + public AccountManager(Survival plugin) { + this.plugin = plugin; + this.accountsFile = new File(plugin.getDataFolder(), "accounts.yml"); + + if (!accountsFile.exists()) { + plugin.getDataFolder().mkdirs(); + try { + accountsFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + this.accountsConfig = YamlConfiguration.loadConfiguration(accountsFile); + loadAccounts(); + } + + private void loadAccounts() { + for (String key : accountsConfig.getKeys(false)) { + try { + UUID uuid = UUID.fromString(key); + PlayerAccount account = (PlayerAccount) accountsConfig.get(key); + if (account != null) { + accounts.put(uuid, account); + } + } catch (IllegalArgumentException e) { + plugin.getLogger().warning("Invalid UUID format: " + key); + } + } + } + + public void saveAccounts() { + for (Map.Entry entry : accounts.entrySet()) { + accountsConfig.set(entry.getKey().toString(), entry.getValue()); + } + + try { + accountsConfig.save(accountsFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean isRegistered(UUID uuid) { + return accounts.containsKey(uuid); + } + + public boolean registerAccount(Player player, String password) { + UUID uuid = player.getUniqueId(); + + if (isRegistered(uuid)) { + return false; + } + + String hashedPassword = hashPassword(password); + PlayerAccount account = new PlayerAccount(player.getName(), hashedPassword); + accounts.put(uuid, account); + saveAccounts(); + return true; + } + + public boolean login(Player player, String password) { + UUID uuid = player.getUniqueId(); + + if (!isRegistered(uuid)) { + return false; + } + + PlayerAccount account = accounts.get(uuid); + String hashedPassword = hashPassword(password); + + if (account.getPasswordHash().equals(hashedPassword)) { + account.setLastLoginTime(System.currentTimeMillis()); + loggedInPlayers.put(uuid, true); + saveAccounts(); + return true; + } + + return false; + } + + public void logout(Player player) { + loggedInPlayers.remove(player.getUniqueId()); + } + + public boolean isLoggedIn(Player player) { + return loggedInPlayers.getOrDefault(player.getUniqueId(), false); + } + + private String hashPassword(String password) { + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] hashedBytes = md.digest(password.getBytes()); + + StringBuilder sb = new StringBuilder(); + for (byte b : hashedBytes) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("SHA-256 algorithm not found", e); + } + } +} diff --git a/src/main/java/org/xgqy/survival/PlayerAccount.java b/src/main/java/org/xgqy/survival/PlayerAccount.java new file mode 100644 index 0000000..b81b53c --- /dev/null +++ b/src/main/java/org/xgqy/survival/PlayerAccount.java @@ -0,0 +1,57 @@ +package org.xgqy.survival; + +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import java.util.HashMap; +import java.util.Map; + +public class PlayerAccount implements ConfigurationSerializable { + private String username; + private String passwordHash; + private long registerTime; + private long lastLoginTime; + + public PlayerAccount(String username, String passwordHash) { + this.username = username; + this.passwordHash = passwordHash; + this.registerTime = System.currentTimeMillis(); + this.lastLoginTime = 0; + } + + public PlayerAccount(Map map) { + this.username = (String) map.get("username"); + this.passwordHash = (String) map.get("passwordHash"); + this.registerTime = (long) map.get("registerTime"); + this.lastLoginTime = (long) map.get("lastLoginTime"); + } + + @Override + public Map serialize() { + Map map = new HashMap<>(); + map.put("username", username); + map.put("passwordHash", passwordHash); + map.put("registerTime", registerTime); + map.put("lastLoginTime", lastLoginTime); + return map; + } + + // Getters and Setters + public String getUsername() { + return username; + } + + public String getPasswordHash() { + return passwordHash; + } + + public long getRegisterTime() { + return registerTime; + } + + public long getLastLoginTime() { + return lastLoginTime; + } + + public void setLastLoginTime(long lastLoginTime) { + this.lastLoginTime = lastLoginTime; + } +} diff --git a/src/main/java/org/xgqy/survival/Survival.java b/src/main/java/org/xgqy/survival/Survival.java index fc07306..c292953 100644 --- a/src/main/java/org/xgqy/survival/Survival.java +++ b/src/main/java/org/xgqy/survival/Survival.java @@ -1,14 +1,18 @@ package org.xgqy.survival; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; import org.xgqy.survival.command.DqshopCommandExecutor; import org.xgqy.survival.command.HandleCommandExecutor; import org.xgqy.survival.command.HelpCommandExecutor; import org.xgqy.survival.command.HubCommandExecutor; +import org.xgqy.survival.command.LoginCommandExecutor; import org.xgqy.survival.command.PvpCommandExecutor; +import org.xgqy.survival.command.RegCommandExecutor; import org.xgqy.survival.command.ReportCommandExecutor; import org.xgqy.survival.command.SetTagCommandExecutor; import org.xgqy.survival.command.TagCommandExecutor; @@ -18,13 +22,17 @@ import org.xgqy.survival.command.TpFinCommandExecutor; import org.xgqy.survival.event.ChatEvent; import org.xgqy.survival.event.ChooseTagEvent; import org.xgqy.survival.event.JoinEvent; +import org.xgqy.survival.event.LoginEvent; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; public final class Survival extends JavaPlugin { private PlayerTags playerTags; + private AccountManager accountManager; // 新增账号管理器 public Map krt = new HashMap<>(); public Map banlist = new HashMap<>(); public Map banreason = new HashMap<>(); @@ -34,16 +42,50 @@ public final class Survival extends JavaPlugin { public Map teleportp = new HashMap<>(); public Map isteleport = new HashMap<>(); public Map lasttp = new HashMap<>(); + public Map area = new HashMap<>(); + private List msg = new ArrayList<>(); @Override public void onEnable() { + // 初始化账号管理器 + accountManager = new AccountManager(this); + + msg.add(ChatColor.GREEN+"可以用 /help 命令来查看命令列表"); + msg.add(ChatColor.GREEN+"如果遇到作弊玩家可以用 /report <玩家名> <原因> 来举报!管理员会很快处理的"); + msg.add(ChatColor.GREEN+"想传送到玩家怎么办? 用 /teleport <玩家名> 命令!"); + msg.add(ChatColor.GREEN+"更换IP但没有更换账号导致的封禁不能找管理员解决"); + msg.add(ChatColor.GREEN+"星阁钱语的名称其实叫星阁浅语"); + msg.add(ChatColor.RED+"作弊会导致账号封禁!请不要作弊"); + msg.add(ChatColor.RED+"在服务器内说不文明用语会导致账号被封禁,请不要这样做"); + msg.add(ChatColor.GREEN+"今天签到了吗?快输入 /qd 签到吧!"); + msg.add(ChatColor.GREEN+"其实可以输入 /pvp 来开启/关闭自己的pvp模式"); + msg.add(ChatColor.RED+"你不可以把别人的家毁掉!这样你将会受到处罚"); + msg.add(ChatColor.GOLD+"能给我捐点钱吗"); + + new BukkitRunnable(){ + @Override + public void run() { + for(Player plr : Bukkit.getOnlinePlayers()){ + // 只向已登录玩家发送提示 + if (accountManager.isLoggedIn(plr)) { + plr.sendMessage(ChatColor.LIGHT_PURPLE+"小提示 "+ChatColor.WHITE+" | "+msg.get((int)(Math.random()*10000)%msg.size())); + } + } + } + }.runTaskLater(this,20*60); + // Plugin startup logic playerTags = new PlayerTags(this); playerTags.loadTags(); + + // 注册事件监听器,包括新的登录事件 Bukkit.getPluginManager().registerEvents(new JoinEvent(this), this); Bukkit.getPluginManager().registerEvents(new ChatEvent(this), this); Bukkit.getPluginManager().registerEvents(new ChooseTagEvent(this), this); + Bukkit.getPluginManager().registerEvents(new LoginEvent(this), this); // 新增登录事件监听器 //Bukkit.getPluginManager().registerEvents(new AntiXray(this),this); + + // 注册命令执行器,包括新的注册和登录命令 getCommand("report").setExecutor(new ReportCommandExecutor(this)); getCommand("handle").setExecutor(new HandleCommandExecutor(this)); getCommand("pvp").setExecutor(new PvpCommandExecutor(this)); @@ -56,15 +98,23 @@ public final class Survival extends JavaPlugin { getCommand("tpacc").setExecutor(new TpAccCommandExecutor(this)); getCommand("tpfin").setExecutor(new TpFinCommandExecutor(this)); getCommand("shop").setExecutor(new DqshopCommandExecutor(this)); + getCommand("reg").setExecutor(new RegCommandExecutor(this)); // 新增注册命令 + getCommand("login").setExecutor(new LoginCommandExecutor(this)); // 新增登录命令 } @Override public void onDisable() { playerTags.saveTags(); + accountManager.saveAccounts(); // 保存账号信息 // Plugin shutdown logic } public PlayerTags getPlayerTags() { return playerTags; } + + // 新增获取账号管理器的方法 + public AccountManager getAccountManager() { + return accountManager; + } } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 1d1a0f1..d09a624 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -42,6 +42,12 @@ commands: shop: description: to open the shop usage: / + reg: + description: to register an account + usage: / + login: + description: to login + usage: / permissions: permission.settag: description: Allows setting player tags