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.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.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import java.io.File;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @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 {

    // Vault类与接口适配
    public interface Economy {
        boolean depositPlayer(Player player, double amount);
    }
    private static class VaultEconomy implements Economy {
        private final Object econ;
        private final java.lang.reflect.Method depositPlayerMethod;
        public VaultEconomy(Object econ) throws Exception {
            this.econ = econ;
            this.depositPlayerMethod = econ.getClass().getMethod("depositPlayer", OfflinePlayer.class, double.class);
        }
        @Override
        public boolean depositPlayer(Player player, double amount) {
            try {
                Object response = depositPlayerMethod.invoke(econ, player, amount);
                // success=true, 根据Vault实际实现,通常可直接认为调用成功
                return true;
            } catch (Exception e) { return false; }
        }
    }

    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经济钩子 仅在有Vault情况下加载
    private boolean setupEconomy() {
        try {
            if(getServer().getPluginManager().getPlugin("Vault") == null){
                getLogger().warning("未检测到Vault,金币奖励功能无法使用!");
                return false;
            }
            RegisteredServiceProvider<?> rsp = getServer().getServicesManager().getRegistration(Class.forName("net.milkbowl.vault.economy.Economy"));
            if(rsp == null){
                getLogger().warning("Vault经济服务未找到!");
                return false;
            }
            Object econ = rsp.getProvider();
            this.economy = new VaultEconomy(econ);
            return true;
        }catch(Exception e){
            getLogger().warning("Vault兼容失败: "+e.getMessage());
            return false;
        }
    }

    // 统计玩家数据,如果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;
            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();
            }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) {
        final Player p = e.getPlayer();
        Bukkit.getScheduler().runTaskAsynchronously(this, new Runnable() {
            @Override
            public void run() {
                refreshPlayerData(p);
            }
        });
        sessionJoinTime.put(p.getUniqueId(), System.currentTimeMillis());
    }
    // 玩家退出,累计在线时长
    @EventHandler
    public void onQuit(PlayerQuitEvent e) {
        final Player p = e.getPlayer();
        final UUID uid = p.getUniqueId();
        final long quit = System.currentTimeMillis();
        final Long join = sessionJoinTime.get(uid);
        if(join != null){
            final long sess = (quit - join) / 1000L;
            Bukkit.getScheduler().runTaskAsynchronously(this, new Runnable(){
                public void run(){
                    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) {
        final GiftPack plugin = this;
        Bukkit.getScheduler().runTaskAsynchronously(this, new Runnable(){
            public void run(){
                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();
                    final int f_total_seconds = total_seconds;
                    final int f_login_days = login_days;
                    final int f_login_count = login_count;
                    final int f_rewarded = rewarded;
                    Bukkit.getScheduler().runTask(plugin, new Runnable(){
                        public void run() {
                            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+"累计在线时长: "+(f_total_seconds/3600)+"小时", Arrays.asList("§7登录天数: "+f_login_days,"§7累计登录: "+f_login_count+"次")));
                            int rewardRow = 2*9+2;
                            for(int i=1;i<=7;i++){
                                Reward rew = rewards.get(i);
                                if(rew == null) continue;
                                boolean got = (f_rewarded&(1<<(i-1)))!=0;
                                boolean avail = f_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;
    }

    @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);
        final Player p = (Player) e.getWhoClicked();
        final 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;
        }
        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(final Player p, final int day) {
        final GiftPack plugin = this;
        Bukkit.getScheduler().runTaskAsynchronously(this, new Runnable(){
            public void run(){
                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(plugin, new Runnable(){
                        public void run(){
                            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){
                                boolean ok = economy.depositPlayer(p, r.money);
                                if(ok) p.sendMessage(ChatColor.GREEN+"已获得金币: "+r.money);
                            }
                            Bukkit.getScheduler().runTaskAsynchronously(plugin, new Runnable(){
                                public void run(){
                                    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(); }
            }
        });
    }
}

上一篇: GiftPack下一篇: BackHome

举报内容

意见反馈