GiftPack

GiftPack.java v1.0
新手礼包插件,记录与发放新手累计登录奖励,支持GUI、Vault经济、YML自定义与权限。
作者: Scriptirc Engine

命令列表

  • giftpack礼包主命令(如/open、/reload、/help)

权限列表

  • giftpack.user允许玩家领取或查看新手礼包
  • giftpack.admin允许管理员管理并reload礼包
package com.yourdomain.giftpack;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.plugin.RegisteredServiceProvider;
import java.io.File;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import net.milkbowl.vault.economy.Economy;

/**
 * @pluginName GiftPack
 * @author Scriptirc Engine
 * @version 1.0
 * @description 新手礼包插件,记录与发放新手累计登录奖励,支持GUI、Vault经济、YML自定义与权限。
 * [command]giftpack|礼包主命令(如/open、/reload、/help)[/command]
 * [Permission]giftpack.user|允许玩家领取或查看新手礼包[/Permission]
 * [Permission]giftpack.admin|允许管理员管理并reload礼包[/Permission]
 */
public class GiftPack extends JavaPlugin implements Listener {

    private File configFile;
    private FileConfiguration config;
    private Connection conn;
    private Economy economy;

    private final String databaseName = "giftpack.db";
    private final String mainPerm = "giftpack.user";
    private final String adminPerm = "giftpack.admin";
    private final Map<UUID, Long> sessionJoinTime = new ConcurrentHashMap<>(); // 记录玩家本次登录时间戳

    @Override
    public void onEnable() {
        saveDefaultConfigYML();
        loadYamlConfig();
        initDatabase();
        setupEconomy();
        Bukkit.getPluginManager().registerEvents(this, this);
        getLogger().info("GiftPack插件已启动");
    }

    @Override
    public void onDisable() {
        try { if(conn!=null && !conn.isClosed()) conn.close(); }catch(Exception ignored){}
    }

    // 保存默认YML配置(自动生成示例):
    private void saveDefaultConfigYML() {
        configFile = new File(getDataFolder(), "giftpack.yml");
        if(!configFile.exists()) {
            getDataFolder().mkdirs();
            try {
                configFile.createNewFile();
                YamlConfiguration yml = new YamlConfiguration();
                yml.set("rewards.1.desc", "第1天奖励:石头x10和100金币");
                yml.set("rewards.1.items", Arrays.asList("STONE:10"));
                yml.set("rewards.1.money", 100);
                yml.set("rewards.1.permission", "");
                yml.set("rewards.2.desc", "第2天奖励:铁锭x5和150金币");
                yml.set("rewards.2.items", Arrays.asList("IRON_INGOT:5"));
                yml.set("rewards.2.money", 150);
                yml.set("rewards.2.permission", "");
                // ...... 以此类推
                yml.save(configFile);
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 加载YML配置
    private void loadYamlConfig() {
        config = YamlConfiguration.loadConfiguration(configFile);
    }

    // 初始化数据库,表结构:uuid、first_join_time、total_play_seconds、login_days、login_count、rewarded(7格bit)
    private void initDatabase() {
        try {
            File dbFile = new File(getDataFolder(), databaseName);
            getDataFolder().mkdirs();
            conn = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
            Statement st = conn.createStatement();
            st.executeUpdate("CREATE TABLE IF NOT EXISTS player_giftpack (uuid TEXT PRIMARY KEY, first_join_time INTEGER, total_play_seconds INTEGER, login_days INTEGER, login_count INTEGER, rewarded INTEGER)");
            st.close();
        }catch (Exception e){ e.printStackTrace(); }
    }

    // Vault经济钩子
    private boolean setupEconomy() {
        if(getServer().getPluginManager().getPlugin("Vault") == null){
            getLogger().warning("未检测到Vault,金币奖励功能无法使用!");
            return false;
        }
        RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
        if(rsp == null){
            getLogger().warning("Vault经济服务未找到!");
            return false;
        }
        economy = rsp.getProvider();
        return (economy != null);
    }

    // 统计玩家数据,如果UUID不存在则插入,否则只更新登录日期和登录次数
    private void refreshPlayerData(Player p) {
        try {
            String uuid = p.getUniqueId().toString();
            long now = System.currentTimeMillis();
            PreparedStatement getps = conn.prepareStatement("SELECT * FROM player_giftpack WHERE uuid = ?");
            getps.setString(1, uuid);
            ResultSet rs = getps.executeQuery();
            boolean dayAdd = false;
            int rewarded = 0;
            if(rs.next()) {
                long lastJoin = rs.getLong("first_join_time");
                int loginDays = rs.getInt("login_days");
                int loginCount = rs.getInt("login_count");
                // 跨天判断
                if(!isSameDay(lastJoin, now)){
                    loginDays++;
                    dayAdd = true;
                }
                // 更新数据
                PreparedStatement up = conn.prepareStatement("UPDATE player_giftpack SET first_join_time=?, login_days=?, login_count=? WHERE uuid = ?");
                up.setLong(1, now);
                up.setInt(2, loginDays);
                up.setInt(3, loginCount+1);
                up.setString(4, uuid);
                up.executeUpdate();
                up.close();
                rewarded = rs.getInt("rewarded");
            }else{
                PreparedStatement ins = conn.prepareStatement("INSERT INTO player_giftpack (uuid, first_join_time, total_play_seconds, login_days, login_count, rewarded) VALUES (?, ?, ?, ?, ?, ?) ");
                ins.setString(1, uuid);
                ins.setLong(2, now);
                ins.setInt(3, 0);
                ins.setInt(4, 1);
                ins.setInt(5, 1);
                ins.setInt(6, 0); // 7bit奖励领取
                ins.executeUpdate();
                ins.close();
                dayAdd = true;
            }
            rs.close();
            getps.close();
        }catch(Exception e){ e.printStackTrace(); }
    }

    // 玩家进入,刷新登录统计并开始计时
    @EventHandler
    public void onJoin(PlayerJoinEvent e) {
        Player p = e.getPlayer();
        Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
            refreshPlayerData(p);
        });
        sessionJoinTime.put(p.getUniqueId(), System.currentTimeMillis());
    }
    // 玩家退出,累计在线时长
    @EventHandler
    public void onQuit(PlayerQuitEvent e) {
        Player p = e.getPlayer();
        UUID uid = p.getUniqueId();
        long quit = System.currentTimeMillis();
        Long join = sessionJoinTime.get(uid);
        if(join != null){
            long sess = (quit - join) / 1000L;
            Bukkit.getScheduler().runTaskAsynchronously(this, () -> accumulatePlayTime(uid, sess));
            sessionJoinTime.remove(uid);
        }
    }
    // 累计时长入库
    private void accumulatePlayTime(UUID uid, long sessionSec){
        try {
            PreparedStatement ps = conn.prepareStatement("UPDATE player_giftpack SET total_play_seconds = total_play_seconds + ? WHERE uuid = ?");
            ps.setLong(1, sessionSec);
            ps.setString(2, uid.toString());
            ps.executeUpdate();
            ps.close();
        }catch(Exception ex){ ex.printStackTrace(); }
    }

    // 判断是否同一天(00:00以后算新一天,按服务器本地)
    private boolean isSameDay(long t1, long t2){
        Calendar c1 = Calendar.getInstance();
        c1.setTimeInMillis(t1);
        Calendar c2 = Calendar.getInstance();
        c2.setTimeInMillis(t2);
        return (c1.get(Calendar.YEAR)==c2.get(Calendar.YEAR)) && (c1.get(Calendar.DAY_OF_YEAR)==c2.get(Calendar.DAY_OF_YEAR));
    }

    // 命令实现
    @Override
    public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
        if(!(sender instanceof Player)){
            sender.sendMessage("[GiftPack] 仅限玩家操作本命令");
            return true;
        }
        Player p = (Player) sender;
        if(args.length == 0 || args[0].equalsIgnoreCase("open")){
            if(p.hasPermission(mainPerm)){
                openGui(p);
                return true;
            }else{
                p.sendMessage(ChatColor.RED+"你没有权限访问新手礼包!");
                return true;
            }
        }else if(args[0].equalsIgnoreCase("help")){
            sendHelp(p);
            return true;
        }else if(args[0].equalsIgnoreCase("reload")){
            if(p.hasPermission(adminPerm)){
                loadYamlConfig();
                p.sendMessage(ChatColor.GREEN+"[GiftPack] 礼包配置与奖励YML已重载");
            }else{
                p.sendMessage(ChatColor.RED+"你没有管理权限");
            }
            return true;
        }
        // 若管理员后续加更多命令,可以补充
        return false;
    }

    // 指令帮助文档
    private void sendHelp(Player p) {
        p.sendMessage(ChatColor.YELLOW+"-- 新手礼包系统指令帮助 --");
        p.sendMessage(ChatColor.AQUA+"/giftpack open   打开礼包界面");
        p.sendMessage(ChatColor.AQUA+"/giftpack reload [管理员] 重载礼包配置");
        p.sendMessage(ChatColor.AQUA+"/giftpack help   查看帮助文档");
    }

    // 解析奖励配置,支持item:amount、money、desc、permission
    public class Reward {
        public int day;
        public String desc;
        public List<String> items;
        public double money;
        public String perm;
        public Reward(int day, String desc, List<String> items, double money, String perm){
            this.day = day; this.desc=desc; this.items=items; this.money=money; this.perm=perm;}
    }
    public Map<Integer,Reward> parseRewardList(){
        Map<Integer,Reward> map = new HashMap<>();
        if(config==null) loadYamlConfig();
        if(config.contains("rewards")){
            for(String i : config.getConfigurationSection("rewards").getKeys(false)){
                int day = 0;
                try{day = Integer.parseInt(i);}catch(Exception ignore){}
                if(day <= 0 || day>7) continue;
                String desc = config.getString("rewards."+i+".desc","奖励");
                List<String> items = config.getStringList("rewards."+i+".items");
                double money = config.getDouble("rewards."+i+".money",0);
                String perm = config.getString("rewards."+i+".permission","");
                map.put(day, new Reward(day,desc,items,money,perm));
            }
        }
        return map;
    }

    // 打开GUI礼包主界面
    private void openGui(Player p) {
        Bukkit.getScheduler().runTaskAsynchronously(this, ()->{
            try {
                // 拉取奖励配置
                Map<Integer,Reward> rewards = parseRewardList();
                PreparedStatement ps = conn.prepareStatement("SELECT * FROM player_giftpack WHERE uuid = ?");
                ps.setString(1, p.getUniqueId().toString());
                ResultSet rs = ps.executeQuery();
                int total_seconds = 0;
                int login_days = 0;
                int login_count = 0;
                int rewarded = 0;
                if(rs.next()){
                    total_seconds = rs.getInt("total_play_seconds");
                    login_days   = rs.getInt("login_days");
                    login_count  = rs.getInt("login_count");
                    rewarded     = rs.getInt("rewarded");
                }
                rs.close(); ps.close();
                // GUI 9x6 创造
                Bukkit.getScheduler().runTask(this, ()->{
                    Inventory inv = Bukkit.createInventory(null, 9*6, ChatColor.GOLD+"新手7日累计登录奖励");
                    // 边缘格子为灰玻璃/功能
                    ItemStack border = new ItemStack(Material.GRAY_STAINED_GLASS_PANE,1);
                    ItemMeta bm = border.getItemMeta();
                    bm.setDisplayName(ChatColor.DARK_GRAY+"——");
                    border.setItemMeta(bm);
                    for(int r=0;r<6;r++) for(int c=0;c<9;c++){
                        if(r==0||r==5||c==0||c==8) inv.setItem(r*9+c, border);
                    }
                    // 边缘下方帮助/刷新/状态
                    inv.setItem(0, makeButton(Material.BOOK, ChatColor.YELLOW+"帮助", Arrays.asList("§7鼠标右键: 查看奖励说明")));
                    inv.setItem(8, makeButton(Material.REDSTONE, ChatColor.RED+"刷新", Arrays.asList("§7点我刷新界面")));
                    inv.setItem(9*5, makeButton(Material.CLOCK, ChatColor.AQUA+"累计在线时长: "+(total_seconds/3600)+"小时", Arrays.asList("§7登录天数: "+login_days,"§7累计登录: "+login_count+"次")));
                    // 中心格子安排7日奖励横向排列  [22~28]
                    int rewardRow = 2*9+2;
                    for(int i=1;i<=7;i++){
                        Reward rew = rewards.get(i);
                        if(rew == null) continue;
                        boolean got = (rewarded&(1<<(i-1)))!=0;
                        boolean avail = login_days>=i;
                        boolean rightPerm = rew.perm==null||rew.perm.isEmpty()||p.hasPermission(rew.perm);
                        ItemStack icon;
                        String title;
                        List<String> lore = new ArrayList<>();
                        if(got) { // 已领奖
                            icon = new ItemStack(Material.EMERALD_BLOCK);
                            title = ChatColor.GREEN+"已领取: 第"+i+"天";
                        }else if(avail&&rightPerm) { // 可领
                            icon = new ItemStack(Material.CHEST);
                            title = ChatColor.GOLD+"可领取: 第"+i+"天";
                            lore.add(ChatColor.YELLOW+rew.desc);
                            lore.add(ChatColor.GRAY+"左键领取,右键查看奖品详情");
                        } else { // 未解锁
                            icon = new ItemStack(Material.BARRIER);
                            title = ChatColor.GRAY+"未达成: 第"+i+"天";
                        }
                        if(!rightPerm)
                            lore.add(ChatColor.RED+"没有礼包权限(管理员可配置)");
                        inv.setItem(rewardRow+i-1, makeButton(icon.getType(), title, lore));
                    }
                    // 打开界面
                    p.openInventory(inv);
                });
            }catch(Exception ex){ ex.printStackTrace(); }
        });
    }

    private ItemStack makeButton(Material mat, String title, List<String> lore) {
        ItemStack is = new ItemStack(mat, 1);
        ItemMeta im = is.getItemMeta();
        im.setDisplayName(title);
        im.setLore(lore);
        is.setItemMeta(im);
        return is;
    }

    // GUI点击事件
    @EventHandler
    public void onGuiClick(InventoryClickEvent e) {
        if(!(e.getWhoClicked() instanceof Player)) return;
        if(e.getInventory()==null||e.getView().getTitle()==null) return;
        if(!e.getView().getTitle().contains("新手7日累计登录奖励")) return;
        e.setCancelled(true);
        Player p = (Player) e.getWhoClicked();
        int slot = e.getRawSlot();
        if(slot < 0 || slot >= 54) return;

        // 边缘功能
        if(slot == 0){ // 帮助
            if(e.isRightClick()) sendHelp(p);
            return;
        }
        if(slot == 8){ // 刷新
            if(e.isLeftClick()) openGui(p);
            return;
        }
        // 7日奖励主界面: 20~26
        int day = slot - (2*9+2) + 1;
        if(day >= 1 && day <= 7) {
            if(e.isRightClick()){
                // 查看奖励内容
                showRewardDetail(p, day);
                return;
            } else if(e.isLeftClick()){
                // 尝试领取奖励
                getRewardForDay(p, day);
                return;
            }
        }
    }

    // 查看某日奖励详情
    public void showRewardDetail(Player p, int day){
        Map<Integer,Reward> rewards = parseRewardList();
        Reward r = rewards.get(day);
        if(r == null){ p.sendMessage(ChatColor.RED+"奖励未配置。"); return; }
        p.sendMessage(ChatColor.AQUA+"——第"+day+"天 新手奖励内容——");
        p.sendMessage(ChatColor.YELLOW+r.desc);
        if(r.items!=null && r.items.size()>0)
            p.sendMessage(ChatColor.GRAY+"物品奖励: "+r.items);
        if(r.money > 0)
            p.sendMessage(ChatColor.GRAY+"金币奖励: "+r.money);
        if(r.perm != null && !r.perm.isEmpty())
            p.sendMessage(ChatColor.GRAY+"领取此礼包需权限: "+r.perm);
    }

    // 领取指定天数奖励
    private void getRewardForDay(Player p, int day) {
        Bukkit.getScheduler().runTaskAsynchronously(this, ()->{
            try {
                Map<Integer,Reward> rewards = parseRewardList();
                Reward r = rewards.get(day);
                if(r == null){
                    p.sendMessage(ChatColor.RED+"该天礼包奖励不存在!");
                    return;
                }
                String uuid = p.getUniqueId().toString();
                PreparedStatement ps = conn.prepareStatement("SELECT * FROM player_giftpack WHERE uuid = ?");
                ps.setString(1, uuid);
                ResultSet rs = ps.executeQuery();
                int login_days = 0;
                int rewarded   = 0;
                if(rs.next()){
                    login_days = rs.getInt("login_days");
                    rewarded   = rs.getInt("rewarded");
                }
                rs.close(); ps.close();
                if(login_days < day){
                    p.sendMessage(ChatColor.RED+"累计登录数不足,无法领取第"+day+"天奖励!");
                    return;
                }
                if( (rewarded&(1<<(day-1))) != 0 ){
                    p.sendMessage(ChatColor.YELLOW+"本日奖励已领取!");
                    return;
                }
                if(r.perm != null && !r.perm.isEmpty() && !p.hasPermission(r.perm)){
                    p.sendMessage(ChatColor.RED+"无领取权限: "+r.perm);
                    return;
                }
                // 发放内容(主线程)
                Bukkit.getScheduler().runTask(this, ()->{
                    // 物品奖励
                    if(r.items!=null){
                        for(String it : r.items){
                            String[] args = it.split(":");
                            try{
                                Material m = Material.matchMaterial(args[0]);
                                int num = args.length>1 ? Integer.parseInt(args[1]) : 1;
                                if(m!=null && num>0){
                                    ItemStack stack = new ItemStack(m, num);
                                    p.getInventory().addItem(stack);
                                }
                            }catch(Exception ignore){}
                        }
                    }
                    // 金币奖励
                    if(r.money > 0 && economy != null){
                        economy.depositPlayer(p, r.money);
                        p.sendMessage(ChatColor.GREEN+"已获得金币: "+r.money);
                    }
                    // 标记已领奖
                    Bukkit.getScheduler().runTaskAsynchronously(this, ()->{
                        try{
                            PreparedStatement upd = conn.prepareStatement("UPDATE player_giftpack SET rewarded = rewarded | ? WHERE uuid = ?");
                            upd.setInt(1, 1<<(day-1));
                            upd.setString(2, uuid);
                            upd.executeUpdate();
                            upd.close();
                        }catch(Exception e){ e.printStackTrace(); }
                    });
                    p.sendMessage(ChatColor.AQUA+"恭喜领取第"+day+"天新手奖励!请查看背包和账户");
                    openGui(p);
                });

            }catch(Exception e){ e.printStackTrace(); }
        });
    }
}

上一篇: FriendBox下一篇: RPGItemBinder

举报内容

意见反馈