GiftPack.java v1.0
新手礼包插件,记录与发放新手累计登录奖励,支持GUI、Vault经济、YML自定义与权限。
命令列表
- giftpack礼包主命令(如/open、/reload、/help)
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(); }
}
});
}
}