This commit is contained in:
parent
e051167757
commit
d854a9b1ef
@ -1,6 +1,11 @@
|
||||
package cn.lunadeer.essentialsd;
|
||||
|
||||
import cn.lunadeer.essentialsd.commands.*;
|
||||
import cn.lunadeer.essentialsd.commands.home.DelHome;
|
||||
import cn.lunadeer.essentialsd.commands.home.Home;
|
||||
import cn.lunadeer.essentialsd.commands.home.Homes;
|
||||
import cn.lunadeer.essentialsd.commands.home.SetHome;
|
||||
import cn.lunadeer.essentialsd.events.*;
|
||||
import cn.lunadeer.essentialsd.managers.ConfigManager;
|
||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||
import cn.lunadeer.essentialsd.managers.TeleportManager;
|
||||
@ -27,8 +32,14 @@ public final class EssentialsD extends JavaPlugin {
|
||||
scheduler = new Scheduler(this);
|
||||
tpManager = new TeleportManager();
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new Events(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new InvisibleItemFrameEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ChairEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ArmorStandHandsEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new CrowEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ExpBottleEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new ShowItemEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new TeleportEvent(), this);
|
||||
Bukkit.getPluginManager().registerEvents(new PlayerRecordEvent(), this);
|
||||
// op 指令
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("fly")).setExecutor(new Fly());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("god")).setExecutor(new God());
|
||||
@ -50,6 +61,10 @@ public final class EssentialsD extends JavaPlugin {
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("tpa")).setExecutor(new Tpa());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("rtp")).setExecutor(new Rtp());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("back")).setExecutor(new Back());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("home")).setExecutor(new Home());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("homes")).setExecutor(new Homes());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("sethome")).setExecutor(new SetHome());
|
||||
Objects.requireNonNull(Bukkit.getPluginCommand("delhome")).setExecutor(new DelHome());
|
||||
|
||||
|
||||
if (config.getRecipesCrowbar()) {
|
||||
|
@ -0,0 +1,62 @@
|
||||
package cn.lunadeer.essentialsd.commands.home;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.dtos.HomeInfo;
|
||||
import cn.lunadeer.essentialsd.tuis.HomeList;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DelHome implements TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
Notification.warn(sender, "只有玩家可以使用此命令");
|
||||
return true;
|
||||
}
|
||||
if (!EssentialsD.config.getCommandsHome()) {
|
||||
Notification.error(sender, "这个命令已被管理员禁用");
|
||||
return false;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
String homeName;
|
||||
if (args.length == 0) {
|
||||
homeName = "default";
|
||||
} else {
|
||||
homeName = args[0];
|
||||
}
|
||||
boolean res = HomeInfo.deleteHome(player.getUniqueId(), homeName);
|
||||
if (res) {
|
||||
Notification.info(player, "成功删除家 " + homeName);
|
||||
} else {
|
||||
Notification.error(player, "删除家 " + homeName + " 失败, 请联系管理员");
|
||||
}
|
||||
if (args.length == 2) {
|
||||
try {
|
||||
int page = Integer.parseInt(args[1]);
|
||||
String[] newArgs = new String[1];
|
||||
newArgs[0] = String.valueOf(page);
|
||||
HomeList.show(sender, newArgs);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
List<HomeInfo> homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId());
|
||||
List<String> res = new ArrayList<>();
|
||||
for (HomeInfo home : homes) {
|
||||
res.add(home.homeName);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package cn.lunadeer.essentialsd.commands.home;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.dtos.HomeInfo;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Home implements TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
Notification.warn(sender, "只有玩家可以使用此命令");
|
||||
return true;
|
||||
}
|
||||
if (!EssentialsD.config.getCommandsHome()) {
|
||||
Notification.error(sender, "这个命令已被管理员禁用");
|
||||
return false;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
String homeName;
|
||||
if (args.length == 0) {
|
||||
homeName = "default";
|
||||
} else {
|
||||
homeName = args[0];
|
||||
}
|
||||
HomeInfo home = HomeInfo.getHome(player.getUniqueId(), homeName);
|
||||
if (home == null) {
|
||||
Notification.error(player, "不存在名为 " + homeName + " 的家");
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
EssentialsD.tpManager.doTeleportDelayed(player, home.location, EssentialsD.config.getTpDelay(), () -> {
|
||||
Notification.info(player, "正在传送到家 " + homeName);
|
||||
}, () -> {
|
||||
Notification.info(player, "成功传送到家 " + homeName);
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
Notification.error(player, "传送到家 " + homeName + " 失败: " + e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
List<HomeInfo> homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId());
|
||||
List<String> res = new ArrayList<>();
|
||||
for (HomeInfo home : homes) {
|
||||
res.add(home.homeName);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.lunadeer.essentialsd.commands.home;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.dtos.HomeInfo;
|
||||
import cn.lunadeer.essentialsd.tuis.HomeList;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.Button;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.Line;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.ListView;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Homes implements TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!EssentialsD.config.getCommandsHome()) {
|
||||
Notification.error(sender, "这个命令已被管理员禁用");
|
||||
return false;
|
||||
}
|
||||
HomeList.show(sender, args);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package cn.lunadeer.essentialsd.commands.home;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.dtos.HomeInfo;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SetHome implements TabExecutor {
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
Notification.warn(sender, "只有玩家可以使用此命令");
|
||||
return true;
|
||||
}
|
||||
if (!EssentialsD.config.getCommandsHome()) {
|
||||
Notification.error(sender, "这个命令已被管理员禁用");
|
||||
return false;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
List<HomeInfo> homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId());
|
||||
if (homes.size() > EssentialsD.config.getHomeLimitAmount()) {
|
||||
Notification.error(player, "你的家数量已达上限");
|
||||
return true;
|
||||
}
|
||||
HomeInfo info = new HomeInfo();
|
||||
info.uuid = player.getUniqueId();
|
||||
if (args.length == 0) {
|
||||
info.homeName = "default";
|
||||
} else {
|
||||
info.homeName = args[0];
|
||||
}
|
||||
info.location = player.getLocation();
|
||||
HomeInfo exist = HomeInfo.getHome(player.getUniqueId(), info.homeName);
|
||||
if (exist != null) {
|
||||
Notification.error(player, "已经存在名为 " + info.homeName + " 的家");
|
||||
return true;
|
||||
}
|
||||
boolean res = HomeInfo.newHome(info);
|
||||
if (res) {
|
||||
Notification.info(player, "成功设置家 " + info.homeName);
|
||||
} else {
|
||||
Notification.error(player, "设置家 " + info.homeName + " 失败, 请联系管理员");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
return null;
|
||||
}
|
||||
}
|
85
src/main/java/cn/lunadeer/essentialsd/dtos/HomeInfo.java
Normal file
85
src/main/java/cn/lunadeer/essentialsd/dtos/HomeInfo.java
Normal file
@ -0,0 +1,85 @@
|
||||
package cn.lunadeer.essentialsd.dtos;
|
||||
|
||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||
import cn.lunadeer.essentialsd.utils.LocationUtils;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class HomeInfo {
|
||||
/*
|
||||
"CREATE TABLE IF NOT EXISTS home_info (" +
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" home_name TEXT NOT NULL," +
|
||||
" location TEXT NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");"
|
||||
*/
|
||||
|
||||
public UUID uuid;
|
||||
public String homeName;
|
||||
public Location location;
|
||||
|
||||
public static boolean newHome(HomeInfo info) {
|
||||
String sql = "INSERT INTO home_info (uuid, home_name, location) " +
|
||||
"VALUES " +
|
||||
"('" + info.uuid.toString() + "', '" + info.homeName + "', '" + LocationUtils.Serialize(info.location) + "')";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean deleteHome(UUID uuid, String homeName) {
|
||||
String sql = "DELETE FROM home_info WHERE uuid = '" + uuid.toString() + "' AND home_name = '" + homeName + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<HomeInfo> getHomesOf(UUID uuid) {
|
||||
List<HomeInfo> homes = new ArrayList<>();
|
||||
String sql = "SELECT * FROM home_info WHERE uuid = '" + uuid.toString() + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
if (rs == null) return homes;
|
||||
while (rs.next()) {
|
||||
HomeInfo home = new HomeInfo();
|
||||
home.uuid = UUID.fromString(rs.getString("uuid"));
|
||||
home.homeName = rs.getString("home_name");
|
||||
home.location = LocationUtils.Deserialize(rs.getString("location"));
|
||||
homes.add(home);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
}
|
||||
return homes;
|
||||
}
|
||||
|
||||
public static HomeInfo getHome(UUID uuid, String homeName) {
|
||||
String sql = "SELECT * FROM home_info WHERE uuid = '" + uuid.toString() + "' AND home_name = '" + homeName + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
if (rs == null) return null;
|
||||
if (rs.next()) {
|
||||
HomeInfo home = new HomeInfo();
|
||||
home.uuid = UUID.fromString(rs.getString("uuid"));
|
||||
home.homeName = rs.getString("home_name");
|
||||
home.location = LocationUtils.Deserialize(rs.getString("location"));
|
||||
return home;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
48
src/main/java/cn/lunadeer/essentialsd/dtos/LoginRecord.java
Normal file
48
src/main/java/cn/lunadeer/essentialsd/dtos/LoginRecord.java
Normal file
@ -0,0 +1,48 @@
|
||||
package cn.lunadeer.essentialsd.dtos;
|
||||
|
||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||
import cn.lunadeer.essentialsd.utils.LocationUtils;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LoginRecord {
|
||||
/*
|
||||
"CREATE TABLE IF NOT EXISTS login_record (" +
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" ip VARCHAR(15) NOT NULL," +
|
||||
" name TEXT NOT NULL," +
|
||||
" login_time TIMESTAMP NOT NULL," +
|
||||
" logout_location TEXT," +
|
||||
" logout_time TIMESTAMP," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");"
|
||||
*/
|
||||
|
||||
public static void newLoginRecord(Player player) {
|
||||
UUID uuid = player.getUniqueId();
|
||||
InetSocketAddress address = player.getAddress();
|
||||
String ip;
|
||||
if (address == null) {
|
||||
ip = "unknown";
|
||||
} else {
|
||||
ip = address.getAddress().getHostAddress();
|
||||
}
|
||||
long login_time = player.getLastLogin();
|
||||
long logout_time = System.currentTimeMillis();
|
||||
String logout_location = LocationUtils.Serialize(player.getLocation());
|
||||
String sql = "INSERT INTO login_record (uuid, ip, login_time, logout_location, logout_time) " +
|
||||
"VALUES " +
|
||||
"('" + uuid.toString() + "', '" + ip + "', '" + login_time + "', '" + logout_location + "', '" + logout_time + "')";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
if (rs == null) return;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
64
src/main/java/cn/lunadeer/essentialsd/dtos/NameRecord.java
Normal file
64
src/main/java/cn/lunadeer/essentialsd/dtos/NameRecord.java
Normal file
@ -0,0 +1,64 @@
|
||||
package cn.lunadeer.essentialsd.dtos;
|
||||
|
||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class NameRecord {
|
||||
/*
|
||||
"CREATE TABLE IF NOT EXISTS name_record (" +
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" name TEXT NOT NULL," +
|
||||
" time TIMESTAMP NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");"
|
||||
*/
|
||||
public UUID uuid;
|
||||
public String name;
|
||||
public Long time;
|
||||
public String timeString;
|
||||
|
||||
public static boolean newNameRecord(Player player){
|
||||
UUID uuid = player.getUniqueId();
|
||||
String name = player.getName();
|
||||
String sql = "INSERT INTO name_record (uuid, name, time) VALUES ('" + uuid.toString() + "', '" + name + "', '" + System.currentTimeMillis() + "')";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<NameRecord> get5NameHistoryOf(UUID uuid) {
|
||||
return getNameHistoryOf(uuid, 5);
|
||||
}
|
||||
|
||||
public static List<NameRecord> getNameHistoryOf(UUID uuid, Integer limit) {
|
||||
List<NameRecord> records = new ArrayList<>();
|
||||
String sql = "SELECT * FROM name_record WHERE uuid = '" + uuid.toString() + "' ORDER BY time DESC LIMIT " + limit;
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
if (rs == null) return records;
|
||||
while (rs.next()) {
|
||||
NameRecord record = new NameRecord();
|
||||
record.uuid = UUID.fromString(rs.getString("uuid"));
|
||||
record.name = rs.getString("name");
|
||||
record.time = rs.getTimestamp("time").getTime();
|
||||
record.timeString = rs.getTimestamp("time").toString();
|
||||
records.add(record);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
}
|
||||
return records;
|
||||
}
|
||||
}
|
42
src/main/java/cn/lunadeer/essentialsd/dtos/PlayerName.java
Normal file
42
src/main/java/cn/lunadeer/essentialsd/dtos/PlayerName.java
Normal file
@ -0,0 +1,42 @@
|
||||
package cn.lunadeer.essentialsd.dtos;
|
||||
|
||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerName {
|
||||
public static String getName(UUID uuid) {
|
||||
String sql = "SELECT last_known_name FROM player_name WHERE uuid = '" + uuid.toString() + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
if (rs == null) return null;
|
||||
if (rs.next()) {
|
||||
return rs.getString("last_known_name");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean setName(UUID uuid, String name) {
|
||||
String sql = "INSERT INTO player_name (uuid, last_known_name) VALUES ('" + uuid.toString() + "', '" + name + "') ON CONFLICT (uuid) DO UPDATE SET last_known_name = '" + name + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean updateName(UUID uuid, String name) {
|
||||
String sql = "UPDATE player_name SET last_known_name = '" + name + "' WHERE uuid = '" + uuid.toString() + "'";
|
||||
try (ResultSet rs = DatabaseManager.query(sql)) {
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
XLogger.err("Database query failed: " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class ArmorStandHandsEvent implements Listener {
|
||||
// put stick as arms for an ArmorStand
|
||||
@EventHandler
|
||||
public void onAddArmsForArmStand(EntityDamageByEntityEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof ArmorStand)) {
|
||||
return;
|
||||
}
|
||||
if (!(event.getDamager() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) event.getDamager();
|
||||
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
||||
if (mainHand.getType() != Material.STICK) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
if (armorStand.hasArms()) {
|
||||
return;
|
||||
}
|
||||
armorStand.setArms(true);
|
||||
mainHand.setAmount(mainHand.getAmount() - 1);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package cn.lunadeer.essentialsd;
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
57
src/main/java/cn/lunadeer/essentialsd/events/CrowEvent.java
Normal file
57
src/main/java/cn/lunadeer/essentialsd/events/CrowEvent.java
Normal file
@ -0,0 +1,57 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.recipes.Crowbar;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Rail;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class CrowEvent implements Listener {
|
||||
// change Rail's state with Crowbar
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onCrowbarUse(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
return;
|
||||
}
|
||||
if (mainHand.getType() != Crowbar.getItemStack().getType()) {
|
||||
return;
|
||||
}
|
||||
if (!Objects.requireNonNull(mainHand.getItemMeta()).getPersistentDataContainer().has(new NamespacedKey(EssentialsD.instance, "this_is_crowbar"), PersistentDataType.BYTE)) {
|
||||
return;
|
||||
}
|
||||
if (event.getClickedBlock() == null) {
|
||||
return;
|
||||
}
|
||||
Block block = event.getClickedBlock();
|
||||
if (block.getType() == Material.POWERED_RAIL || block.getType() == Material.DETECTOR_RAIL || block.getType() == Material.ACTIVATOR_RAIL) {
|
||||
return;
|
||||
}
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Rail)) {
|
||||
return;
|
||||
}
|
||||
Rail rail = (Rail) blockData;
|
||||
if (!Crowbar.changeable(rail.getShape())) {
|
||||
Notification.warn(player, "无法使用撬棍修改此铁轨的方向");
|
||||
return;
|
||||
}
|
||||
rail.setShape(Crowbar.changeToNext(rail.getShape()));
|
||||
block.setBlockData(rail);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class ExpBottleEvent implements Listener {
|
||||
// on throw ExpBottle set multiplier for ExpBottle
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onExpBottleUsage(org.bukkit.event.entity.ExpBottleEvent event) {
|
||||
int exp = event.getExperience();
|
||||
if (exp < 0) {
|
||||
event.setExperience(0);
|
||||
}
|
||||
event.setExperience((int) (exp * EssentialsD.config.getExpBottleRatio()));
|
||||
}
|
||||
}
|
@ -1,53 +1,23 @@
|
||||
package cn.lunadeer.essentialsd;
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.commands.ShowItem;
|
||||
import cn.lunadeer.essentialsd.recipes.Crowbar;
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.recipes.InvisibleGlowItemFrame;
|
||||
import cn.lunadeer.essentialsd.recipes.InvisibleItemFrame;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import cn.lunadeer.essentialsd.utils.XLogger;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Rail;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.ExpBottleEvent;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
import org.bukkit.event.hanging.HangingPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Events implements Listener {
|
||||
// cancel click ShowItem
|
||||
@EventHandler
|
||||
public void onShowItemClick(InventoryClickEvent event) {
|
||||
Inventory inv = event.getClickedInventory();
|
||||
if (inv == null) {
|
||||
return;
|
||||
}
|
||||
InventoryView view = event.getView();
|
||||
if (!ShowItem.cache.containsKey(view.getOriginalTitle())) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
public class InvisibleItemFrameEvent implements Listener {
|
||||
// place an Invisible Item Frame
|
||||
@EventHandler
|
||||
public void placeItemFrame(HangingPlaceEvent event) {
|
||||
@ -127,80 +97,4 @@ public class Events implements Listener {
|
||||
itemFrame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
// put stick as arms for an ArmorStand
|
||||
@EventHandler
|
||||
public void onAddArmsForArmStand(EntityDamageByEntityEvent event) {
|
||||
Entity entity = event.getEntity();
|
||||
if (!(entity instanceof ArmorStand)) {
|
||||
return;
|
||||
}
|
||||
if (!(event.getDamager() instanceof Player)) {
|
||||
return;
|
||||
}
|
||||
Player player = (Player) event.getDamager();
|
||||
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
||||
if (mainHand.getType() != Material.STICK) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
ArmorStand armorStand = (ArmorStand) entity;
|
||||
if (armorStand.hasArms()) {
|
||||
return;
|
||||
}
|
||||
armorStand.setArms(true);
|
||||
mainHand.setAmount(mainHand.getAmount() - 1);
|
||||
}
|
||||
|
||||
// change Rail's state with Crowbar
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onCrowbarUse(PlayerInteractEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
ItemStack mainHand = player.getInventory().getItemInMainHand();
|
||||
if (event.getHand() == EquipmentSlot.OFF_HAND) {
|
||||
return;
|
||||
}
|
||||
if (mainHand.getType() != Crowbar.getItemStack().getType()) {
|
||||
return;
|
||||
}
|
||||
if (!Objects.requireNonNull(mainHand.getItemMeta()).getPersistentDataContainer().has(new NamespacedKey(EssentialsD.instance, "this_is_crowbar"), PersistentDataType.BYTE)) {
|
||||
return;
|
||||
}
|
||||
if (event.getClickedBlock() == null) {
|
||||
return;
|
||||
}
|
||||
Block block = event.getClickedBlock();
|
||||
if (block.getType() == Material.POWERED_RAIL || block.getType() == Material.DETECTOR_RAIL || block.getType() == Material.ACTIVATOR_RAIL) {
|
||||
return;
|
||||
}
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Rail)) {
|
||||
return;
|
||||
}
|
||||
Rail rail = (Rail) blockData;
|
||||
if (!Crowbar.changeable(rail.getShape())) {
|
||||
Notification.warn(player, "无法使用撬棍修改此铁轨的方向");
|
||||
return;
|
||||
}
|
||||
rail.setShape(Crowbar.changeToNext(rail.getShape()));
|
||||
block.setBlockData(rail);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
// on throw ExpBottle set multiplier for ExpBottle
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onExpBottleUsage(ExpBottleEvent event) {
|
||||
int exp = event.getExperience();
|
||||
if (exp < 0) {
|
||||
event.setExperience(0);
|
||||
}
|
||||
event.setExperience((int) (exp * EssentialsD.config.getExpBottleRatio()));
|
||||
}
|
||||
|
||||
// on player death update tpManager
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
Player player = event.getEntity();
|
||||
EssentialsD.tpManager.updateLastTpLocation(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.dtos.LoginRecord;
|
||||
import cn.lunadeer.essentialsd.dtos.NameRecord;
|
||||
import cn.lunadeer.essentialsd.dtos.PlayerName;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
public class PlayerRecordEvent implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
String last_name = PlayerName.getName(player.getUniqueId());
|
||||
if (last_name == null) {
|
||||
PlayerName.setName(player.getUniqueId(), player.getName());
|
||||
NameRecord.newNameRecord(player);
|
||||
} else if (!last_name.equals(player.getName())) {
|
||||
PlayerName.updateName(player.getUniqueId(), player.getName());
|
||||
NameRecord.newNameRecord(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerLogout(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
LoginRecord.newLoginRecord(player);
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.commands.ShowItem;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
|
||||
public class ShowItemEvent implements Listener {
|
||||
// cancel click ShowItem
|
||||
@EventHandler
|
||||
public void onShowItemClick(InventoryClickEvent event) {
|
||||
Inventory inv = event.getClickedInventory();
|
||||
if (inv == null) {
|
||||
return;
|
||||
}
|
||||
InventoryView view = event.getView();
|
||||
if (!ShowItem.cache.containsKey(view.getOriginalTitle())) {
|
||||
return;
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.lunadeer.essentialsd.events;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
|
||||
public class TeleportEvent implements Listener {
|
||||
// on player death update tpManager
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerDeath(PlayerDeathEvent event) {
|
||||
Player player = event.getEntity();
|
||||
EssentialsD.tpManager.updateLastTpLocation(player);
|
||||
}
|
||||
}
|
@ -33,10 +33,12 @@ public class ConfigManager {
|
||||
_commands_hat = _file.getBoolean("Commands.Hat", true);
|
||||
_commands_showitem = _file.getBoolean("Commands.ShowItem", true);
|
||||
_commands_skull = _file.getBoolean("Commands.Skull", true);
|
||||
_commands_home = _file.getBoolean("Commands.Home", true);
|
||||
_tp_delay = _file.getInt("Teleport.Delay", 0);
|
||||
_tp_cool_down = _file.getInt("Teleport.CoolDown", 0);
|
||||
_tp_tpa_expire = _file.getInt("Teleport.TpaExpire", 30);
|
||||
_tp_rtp_radius = _file.getInt("Teleport.RtpRadius", 10000);
|
||||
_tp_rtp_radius = _file.getInt("Teleport.RtpRadius", 1000);
|
||||
_tp_world_blacklist = _file.getStringList("Teleport.WorldBlackList");
|
||||
_chair_enable = _file.getBoolean("Chair.Enable", true);
|
||||
_chair_max_width = _file.getInt("Chair.MaxWidth", 4);
|
||||
_chair_sign_check = _file.getBoolean("Chair.SignCheck", true);
|
||||
@ -45,6 +47,8 @@ public class ConfigManager {
|
||||
_recipes_invisible_item_frame = _file.getBoolean("Recipes.InvisibleItemFrame", true);
|
||||
_recipes_light_block = _file.getBoolean("Recipes.LightBlock", true);
|
||||
_recipes_stacked_enchant_book = _file.getBoolean("Recipes.StackedEnchantBook", true);
|
||||
_home_limit_amount = _file.getInt("HomeLimit.Amount", 5);
|
||||
_home_world_blacklist = _file.getStringList("HomeLimit.WorldBlacklist");
|
||||
_db_type = _file.getString("Database.Type", "sqlite");
|
||||
if (!_db_type.equals("pgsql") && !_db_type.equals("sqlite")) {
|
||||
XLogger.err("当前数据库只支持 pgsql 或 sqlite,已重置为 sqlite");
|
||||
@ -107,6 +111,10 @@ public class ConfigManager {
|
||||
return _tp_rtp_radius;
|
||||
}
|
||||
|
||||
public List<String> getTpWorldBlackList() {
|
||||
return _tp_world_blacklist;
|
||||
}
|
||||
|
||||
public Boolean getCommandsTpa() {
|
||||
return _commands_tpa;
|
||||
}
|
||||
@ -139,6 +147,10 @@ public class ConfigManager {
|
||||
return _commands_skull;
|
||||
}
|
||||
|
||||
public Boolean getCommandsHome() {
|
||||
return _commands_home;
|
||||
}
|
||||
|
||||
|
||||
public Boolean getChairEnable() {
|
||||
return _chair_enable;
|
||||
@ -210,6 +222,14 @@ public class ConfigManager {
|
||||
}, _chunk_operate_delay * 20);
|
||||
}
|
||||
|
||||
public Integer getHomeLimitAmount() {
|
||||
return _home_limit_amount;
|
||||
}
|
||||
|
||||
public List<String> getHomeWorldBlacklist() {
|
||||
return _home_world_blacklist;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return _db_type;
|
||||
}
|
||||
@ -269,6 +289,7 @@ public class ConfigManager {
|
||||
private Integer _tp_delay;
|
||||
private Integer _tp_cool_down;
|
||||
private Integer _tp_rtp_radius;
|
||||
private List<String> _tp_world_blacklist;
|
||||
private Boolean _chair_enable;
|
||||
private Integer _chair_max_width;
|
||||
private Boolean _chair_sign_check;
|
||||
@ -283,12 +304,17 @@ public class ConfigManager {
|
||||
private Boolean _commands_hat;
|
||||
private Boolean _commands_showitem;
|
||||
private Boolean _commands_skull;
|
||||
private Boolean _commands_home;
|
||||
// recipes
|
||||
private Boolean _recipes_crowbar;
|
||||
private Boolean _recipes_invisible_item_frame;
|
||||
private Boolean _recipes_light_block;
|
||||
private Boolean _recipes_stacked_enchant_book;
|
||||
|
||||
// home limit
|
||||
private Integer _home_limit_amount;
|
||||
private List<String> _home_world_blacklist;
|
||||
|
||||
// database
|
||||
private String _db_type;
|
||||
private String _db_host;
|
||||
|
@ -102,10 +102,11 @@ public class DatabaseManager {
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" ip VARCHAR(15) NOT NULL," +
|
||||
" name TEXT NOT NULL," +
|
||||
" login_time TIMESTAMP NOT NULL," +
|
||||
" logout_location TEXT," +
|
||||
" logout_time TIMESTAMP" +
|
||||
" logout_time TIMESTAMP," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
|
||||
@ -114,7 +115,9 @@ public class DatabaseManager {
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" name TEXT NOT NULL," +
|
||||
" time TIMESTAMP NOT NULL" +
|
||||
" time TIMESTAMP NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
|
||||
@ -126,7 +129,9 @@ public class DatabaseManager {
|
||||
" to_location TEXT NOT NULL," +
|
||||
" type TEXT NOT NULL," +
|
||||
" success BOOLEAN NOT NULL," +
|
||||
" time TIMESTAMP NOT NULL" +
|
||||
" time TIMESTAMP NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (initiator_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
|
||||
@ -135,7 +140,9 @@ public class DatabaseManager {
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" sender_uuid VARCHAR(36) NOT NULL," +
|
||||
" message TEXT NOT NULL," +
|
||||
" time TIMESTAMP NOT NULL" +
|
||||
" time TIMESTAMP NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (sender_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
|
||||
@ -144,7 +151,9 @@ public class DatabaseManager {
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" executor_uuid VARCHAR(36) NOT NULL," +
|
||||
" command TEXT NOT NULL," +
|
||||
" time TIMESTAMP NOT NULL" +
|
||||
" time TIMESTAMP NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (executor_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
|
||||
@ -153,7 +162,9 @@ public class DatabaseManager {
|
||||
" id SERIAL PRIMARY KEY," +
|
||||
" uuid VARCHAR(36) NOT NULL," +
|
||||
" home_name TEXT NOT NULL," +
|
||||
" location TEXT NOT NULL" +
|
||||
" location TEXT NOT NULL," +
|
||||
|
||||
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||
");";
|
||||
query(sql);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class TeleportManager {
|
||||
|
||||
@ -44,14 +45,9 @@ public class TeleportManager {
|
||||
return;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime next_time = _next_time_allow_tp.get(initiator.getUniqueId());
|
||||
if (next_time != null) {
|
||||
if (now.isBefore(next_time)) {
|
||||
long secs_until_next = now.until(next_time, java.time.temporal.ChronoUnit.SECONDS);
|
||||
Notification.error(initiator, "请等待 " + secs_until_next + " 秒后再次传送");
|
||||
return;
|
||||
}
|
||||
if (EssentialsD.config.getTpWorldBlackList().contains(target.getWorld().getName())) {
|
||||
Notification.error(initiator, "目的地所在世界 " + initiator.getWorld().getName() + " 不允许传送");
|
||||
return;
|
||||
}
|
||||
|
||||
TpTask task = new TpTask();
|
||||
@ -70,7 +66,6 @@ public class TeleportManager {
|
||||
Notification.info(target, Component.text("| ", main_color).append(acceptBtn).append(Component.text(" ", main_color)).append(denyBtn));
|
||||
Notification.info(target, Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color));
|
||||
|
||||
_next_time_allow_tp.put(initiator.getUniqueId(), now.plusSeconds(EssentialsD.config.getTpCoolDown()));
|
||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||
_tasks.remove(task.taskId);
|
||||
}, 20L * EssentialsD.config.getTpTpaExpire());
|
||||
@ -110,17 +105,19 @@ public class TeleportManager {
|
||||
if (!task.initiator.isOnline() || !task.target.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Notification.info(task.target, "已接受 " + task.initiator.getName() + " 的传送请求");
|
||||
if (EssentialsD.config.getTpDelay() > 0) {
|
||||
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求,传送将在 " + EssentialsD.config.getTpDelay() + " 秒后进行");
|
||||
}
|
||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||
if (task.initiator.isOnline() && task.target.isOnline()) {
|
||||
doTeleportSafely(task.initiator, task.target.getLocation());
|
||||
Notification.info(task.initiator, "已传送到 " + task.target.getName() + " 的位置");
|
||||
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求");
|
||||
try {
|
||||
doTeleportDelayed(task.initiator, task.target.getLocation(), EssentialsD.config.getTpDelay(), () -> {
|
||||
Notification.info(task.initiator, "正在传送到 " + task.initiator.getName() + " 的位置");
|
||||
}, () -> {
|
||||
Notification.info(task.initiator, "已传送到 " + task.initiator.getName() + " 的位置");
|
||||
Notification.info(task.target, "玩家 " + task.initiator.getName() + " 已传送到你的位置");
|
||||
}
|
||||
}, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay());
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
Notification.error(player, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void back(Player player) {
|
||||
@ -128,29 +125,68 @@ public class TeleportManager {
|
||||
Notification.error(player, "没有找到可返回的位置");
|
||||
return;
|
||||
}
|
||||
Location target = _last_tp_location.get(player.getUniqueId());
|
||||
if (EssentialsD.config.getTpWorldBlackList().contains(target.getWorld().getName())) {
|
||||
Notification.error(player, "目的地所在世界 " + target.getWorld().getName() + " 不允许传送");
|
||||
return;
|
||||
}
|
||||
if (EssentialsD.config.getTpDelay() > 0) {
|
||||
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后返回上次传送的位置");
|
||||
}
|
||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||
doTeleportSafely(player, _last_tp_location.get(player.getUniqueId()));
|
||||
Notification.info(player, "已返回上次传送的位置");
|
||||
}, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay());
|
||||
try {
|
||||
doTeleportDelayed(player, target, EssentialsD.config.getTpDelay(), () -> {
|
||||
Notification.info(player, "正在返回上次传送的位置");
|
||||
}, () -> {
|
||||
Notification.info(player, "已返回上次传送的位置");
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
Notification.error(player, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void rtp(Player player) {
|
||||
if (EssentialsD.config.getTpWorldBlackList().contains(player.getWorld().getName())) {
|
||||
Notification.error(player, "此世界 " + player.getWorld().getName() + " 不允许传送");
|
||||
return;
|
||||
}
|
||||
int radius = EssentialsD.config.getTpRtpRadius();
|
||||
World world = player.getWorld();
|
||||
int x = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getX();
|
||||
int z = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getZ();
|
||||
XLogger.debug("RTP: " + x + " " + z);
|
||||
Location location = new Location(world, x + 0.5, player.getY(), z + 0.5);
|
||||
if (EssentialsD.config.getTpDelay() > 0) {
|
||||
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后传送到随机位置");
|
||||
try {
|
||||
doTeleportDelayed(player, location, EssentialsD.config.getTpDelay(), () -> {
|
||||
Notification.info(player, "正在传送到随机位置");
|
||||
}, () -> {
|
||||
Notification.info(player, "已传送到随机位置");
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
Notification.error(player, e.getMessage());
|
||||
}
|
||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||
}
|
||||
|
||||
public void doTeleportDelayed(Player player, Location location, Integer delay, Runnable before, Runnable after) {
|
||||
doTeleportDelayed(player, location, delay.longValue(), before, after);
|
||||
}
|
||||
|
||||
public void doTeleportDelayed(Player player, Location location, Long delay, Runnable before, Runnable after) throws RuntimeException {
|
||||
if (EssentialsD.config.getTpWorldBlackList().contains(location.getWorld().getName())) {
|
||||
Notification.error(player, "目的地所在世界 " + location.getWorld().getName() + " 不允许传送");
|
||||
return;
|
||||
}
|
||||
if (delay > 0) {
|
||||
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后执行传送");
|
||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||
before.run();
|
||||
doTeleportSafely(player, location);
|
||||
after.run();
|
||||
}, 20L * delay);
|
||||
} else {
|
||||
before.run();
|
||||
doTeleportSafely(player, location);
|
||||
Notification.info(player, "已传送到随机位置");
|
||||
}, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay());
|
||||
after.run();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,16 +195,23 @@ public class TeleportManager {
|
||||
* @param player 玩家
|
||||
* @param location 位置
|
||||
*/
|
||||
public void doTeleportSafely(Player player, Location location) {
|
||||
public void doTeleportSafely(Player player, Location location) throws RuntimeException {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime next_time = _next_time_allow_tp.get(player.getUniqueId());
|
||||
if (next_time != null) {
|
||||
if (now.isBefore(next_time)) {
|
||||
long secs_until_next = now.until(next_time, java.time.temporal.ChronoUnit.SECONDS);
|
||||
throw new RuntimeException("请等待 " + secs_until_next + " 秒后再次传送");
|
||||
}
|
||||
}
|
||||
_next_time_allow_tp.put(player.getUniqueId(), now.plusSeconds(EssentialsD.config.getTpCoolDown()));
|
||||
location.getWorld().getChunkAtAsyncUrgently(location).thenAccept((chunk) -> {
|
||||
updateLastTpLocation(player);
|
||||
int max_attempts = 512;
|
||||
while (location.getBlock().isPassable()) {
|
||||
location.setY(location.getY() - 1);
|
||||
max_attempts--;
|
||||
if (max_attempts <= 0) {
|
||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
||||
return;
|
||||
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||
}
|
||||
}
|
||||
Block up1 = location.getBlock().getRelative(BlockFace.UP);
|
||||
@ -180,15 +223,14 @@ public class TeleportManager {
|
||||
up2 = up1.getRelative(BlockFace.UP);
|
||||
max_attempts--;
|
||||
if (max_attempts <= 0) {
|
||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
||||
return;
|
||||
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||
}
|
||||
}
|
||||
location.setY(location.getY() + 1);
|
||||
if (location.getBlock().getRelative(BlockFace.DOWN).getType() == Material.LAVA) {
|
||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
||||
return;
|
||||
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||
}
|
||||
updateLastTpLocation(player);
|
||||
player.teleportAsync(location, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
});
|
||||
}
|
||||
|
44
src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java
Normal file
44
src/main/java/cn/lunadeer/essentialsd/tuis/HomeList.java
Normal file
@ -0,0 +1,44 @@
|
||||
package cn.lunadeer.essentialsd.tuis;
|
||||
|
||||
import cn.lunadeer.essentialsd.EssentialsD;
|
||||
import cn.lunadeer.essentialsd.dtos.HomeInfo;
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.Button;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.Line;
|
||||
import cn.lunadeer.essentialsd.utils.STUI.ListView;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HomeList {
|
||||
public static void show(CommandSender sender, String[] args) {
|
||||
if (!(sender instanceof Player)) {
|
||||
Notification.warn(sender, "只有玩家可以使用此命令");
|
||||
return;
|
||||
}
|
||||
Player player = (Player) sender;
|
||||
List<HomeInfo> homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId());
|
||||
if (homes.size() == 0) {
|
||||
Notification.warn(player, "你还没有设置家");
|
||||
return;
|
||||
}
|
||||
int page = 1;
|
||||
if (args.length == 1) {
|
||||
try {
|
||||
page = Integer.parseInt(args[0]);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
ListView view = ListView.create(5, "/homes");
|
||||
view.title("Home 列表");
|
||||
for (HomeInfo home : homes) {
|
||||
Line line = Line.create()
|
||||
.append(home.homeName)
|
||||
.append(Button.create("传送", "/home " + home.homeName))
|
||||
.append(Button.createRed("删除", "/delhome " + home.homeName + " " + page));
|
||||
view.add(line);
|
||||
}
|
||||
view.showOn(player, page);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.lunadeer.essentialsd.utils;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
public class LocationUtils {
|
||||
public static String Serialize(Location loc) {
|
||||
return loc.getWorld().getName() + "," + loc.getX() + "," + loc.getY() + "," + loc.getZ() + "," + loc.getYaw() + "," + loc.getPitch();
|
||||
}
|
||||
|
||||
public static Location Deserialize(String loc) {
|
||||
String[] parts = loc.split(",");
|
||||
World world = org.bukkit.Bukkit.getWorld(parts[0]);
|
||||
double x = Double.parseDouble(parts[1]);
|
||||
double y = Double.parseDouble(parts[2]);
|
||||
double z = Double.parseDouble(parts[3]);
|
||||
float yaw = Float.parseFloat(parts[4]);
|
||||
float pitch = Float.parseFloat(parts[5]);
|
||||
return new Location(world, x, y, z, yaw, pitch);
|
||||
}
|
||||
}
|
@ -8,14 +8,14 @@ import java.util.List;
|
||||
|
||||
|
||||
public class Line {
|
||||
private String d = " - ";
|
||||
private final List<Component> elements = new ArrayList<>();
|
||||
|
||||
private final TextComponent divider = Component.text(" - ", ViewStyles.sub_color);
|
||||
|
||||
public Line() {
|
||||
}
|
||||
|
||||
public TextComponent build() {
|
||||
TextComponent divider = Component.text(d, ViewStyles.sub_color);
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
builder.append(elements.get(i));
|
||||
@ -30,11 +30,20 @@ public class Line {
|
||||
return new Line();
|
||||
}
|
||||
|
||||
List<Component> getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public Line append(TextComponent component) {
|
||||
elements.add(component);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Line setDivider(String d) {
|
||||
this.d = d;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Line append(Component component) {
|
||||
elements.add(component);
|
||||
return this;
|
||||
@ -45,4 +54,4 @@ public class Line {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package cn.lunadeer.essentialsd.utils.STUI;
|
||||
|
||||
import cn.lunadeer.essentialsd.utils.Notification;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -13,7 +15,7 @@ public class ListView {
|
||||
private String command = "";
|
||||
private final View view = View.create();
|
||||
|
||||
public ListView(int page_size, String command) {
|
||||
private ListView(int page_size, String command) {
|
||||
super();
|
||||
this.page_size = page_size;
|
||||
this.command = command;
|
||||
@ -39,6 +41,16 @@ public class ListView {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListView subtitle(TextComponent subtitle) {
|
||||
view.subtitle(subtitle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListView subtitle(Line line) {
|
||||
view.subtitle(line);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListView add(Line line) {
|
||||
lines.add(line);
|
||||
return this;
|
||||
@ -61,11 +73,23 @@ public class ListView {
|
||||
}
|
||||
for (int i = offset; i < offset + page_size; i++) {
|
||||
if (i >= lines.size()) {
|
||||
for (int j = 0; j < page_size - lines.size() % page_size; j++) {
|
||||
view.addLine(Line.create());
|
||||
}
|
||||
break;
|
||||
}
|
||||
view.addLine(lines.get(i));
|
||||
}
|
||||
view.actionBar(Pagination.create(page, lines.size(), this.command));
|
||||
view.actionBar(Pagination.create(page, lines.size(), page_size, this.command));
|
||||
view.showOn(player);
|
||||
}
|
||||
}
|
||||
|
||||
public ListView navigator(Line line) {
|
||||
Line nav = Line.create().setDivider("->").append(Component.text("导航", ViewStyles.main_color));
|
||||
for (Component component : line.getElements()) {
|
||||
nav.append(component);
|
||||
}
|
||||
view.subtitle(nav);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -11,9 +11,8 @@ import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.sub_color;
|
||||
|
||||
|
||||
public class Pagination {
|
||||
public static TextComponent create(int page, int item_size, String command) {
|
||||
public static TextComponent create(int page, int item_size, int page_size, String command) {
|
||||
// 第 x/y 页 [上一页] [下一页]
|
||||
int page_size = 4;
|
||||
int page_count = (int) Math.ceil((double) item_size / page_size);
|
||||
if (page_count == 0) {
|
||||
page_count = 1;
|
||||
@ -26,9 +25,13 @@ public class Pagination {
|
||||
componentList.add(Component.text(" 页 ", main_color));
|
||||
if (page > 1) {
|
||||
componentList.add(Button.create("上一页", command + " " + (page - 1)));
|
||||
} else {
|
||||
componentList.add(Component.text("[上一页]", sub_color));
|
||||
}
|
||||
if (page < page_count) {
|
||||
componentList.add(Button.create("下一页", command + " " + (page + 1)));
|
||||
} else {
|
||||
componentList.add(Component.text("[下一页]", sub_color));
|
||||
}
|
||||
TextComponent.Builder builder = Component.text();
|
||||
for (Component component : componentList) {
|
||||
|
@ -10,33 +10,25 @@ import java.util.List;
|
||||
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.main_color;
|
||||
|
||||
public class View {
|
||||
protected TextComponent title_decorate = Component.text("━", main_color);
|
||||
protected TextComponent space = Component.text(" ");
|
||||
protected TextComponent sub_title_decorate = Component.text("- ", main_color);
|
||||
protected TextComponent line_decorate = Component.text("⌗ ", main_color);
|
||||
protected TextComponent action_decorate = Component.text("▸ ", main_color);
|
||||
protected TextComponent title = Component.text(" ");
|
||||
protected TextComponent subtitle = Component.text("");
|
||||
protected TextComponent subtitle = null;
|
||||
protected List<TextComponent> content_lines = new ArrayList<>();
|
||||
protected TextComponent actionbar = Component.text(" ");
|
||||
protected TextComponent edge = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||
protected TextComponent divide_line = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||
protected TextComponent actionbar = null;
|
||||
protected TextComponent edge = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||
protected TextComponent divide_line = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||
|
||||
public void showOn(Player player) {
|
||||
player.sendMessage(edge);
|
||||
// player.sendMessage(edge);
|
||||
TextComponent.Builder builder = Component.text();
|
||||
int title_length = title.content().length();
|
||||
int title_width = title_length * 2 + 2;
|
||||
int decorate_count = divide_line.content().length() - title_width;
|
||||
for (int i = 0; i < decorate_count / 2; i++) {
|
||||
builder.append(title_decorate);
|
||||
}
|
||||
builder.append(Component.text("__/", main_color));
|
||||
builder.append(space).append(title).append(space);
|
||||
for (int i = 0; i < decorate_count / 2; i++) {
|
||||
builder.append(title_decorate);
|
||||
}
|
||||
builder.append(Component.text("\\__", main_color));
|
||||
player.sendMessage(builder.build());
|
||||
if (subtitle.content().length() > 0) {
|
||||
if (subtitle != null) {
|
||||
player.sendMessage(divide_line);
|
||||
player.sendMessage(Component.text().append(sub_title_decorate).append(subtitle).build());
|
||||
}
|
||||
@ -44,8 +36,10 @@ public class View {
|
||||
for (TextComponent content_line : content_lines) {
|
||||
player.sendMessage(Component.text().append(line_decorate).append(content_line).build());
|
||||
}
|
||||
player.sendMessage(divide_line);
|
||||
player.sendMessage(Component.text().append(action_decorate).append(actionbar).build());
|
||||
if (actionbar != null) {
|
||||
player.sendMessage(divide_line);
|
||||
player.sendMessage(Component.text().append(action_decorate).append(actionbar).build());
|
||||
}
|
||||
player.sendMessage(edge);
|
||||
player.sendMessage(Component.text(" "));
|
||||
}
|
||||
@ -69,6 +63,19 @@ public class View {
|
||||
return this;
|
||||
}
|
||||
|
||||
public View subtitle(Line line) {
|
||||
this.subtitle = line.build();
|
||||
return this;
|
||||
}
|
||||
|
||||
public View navigator(Line line) {
|
||||
Line nav = Line.create().setDivider("->").append(Component.text("导航", ViewStyles.main_color));
|
||||
for (Component component : line.getElements()) {
|
||||
nav.append(component);
|
||||
}
|
||||
return this.subtitle(nav);
|
||||
}
|
||||
|
||||
public View subtitle(TextComponent subtitle) {
|
||||
this.subtitle = subtitle;
|
||||
return this;
|
||||
@ -103,4 +110,4 @@ public class View {
|
||||
this.content_lines.add(component.build());
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -37,13 +37,15 @@ Commands:
|
||||
Tpa: true # 传送到其他玩家
|
||||
Rtp: true # 随机传送到附近
|
||||
Back: true # 回到上一个传送位置
|
||||
Home: true # home相关指令 包含 sethome delhome home homes
|
||||
|
||||
# 传送
|
||||
Teleport:
|
||||
Delay: 0 # 传送延迟 秒
|
||||
CoolDown: 0 # 冷却时间 秒
|
||||
TpaExpire: 30 # 传送请求有效期 秒
|
||||
RtpRadius: 1000 # 随机传送最大半径
|
||||
Delay: 0 # 传送延迟 秒
|
||||
CoolDown: 0 # 冷却时间 秒
|
||||
TpaExpire: 30 # 传送请求有效期 秒
|
||||
RtpRadius: 1000 # 随机传送最大半径
|
||||
WorldBlackList: [ ] # 不允许传送的世界
|
||||
|
||||
# 把楼梯当作椅子使用
|
||||
Chair:
|
||||
@ -52,6 +54,11 @@ Chair:
|
||||
SignCheck: false
|
||||
SitHeight: -0.95
|
||||
|
||||
# home 相关限制
|
||||
HomeLimit:
|
||||
Amount: 5 # 数量限制
|
||||
WorldBlackList: [ ] # 不允许设置 home 的世界
|
||||
|
||||
Debug: false
|
||||
|
||||
CheckUpdate: true
|
@ -63,4 +63,16 @@ commands:
|
||||
usage: /back
|
||||
inspect:
|
||||
description: 检查玩家背包
|
||||
usage: /inspect <player>
|
||||
usage: /inspect <player>
|
||||
home:
|
||||
description: 回家
|
||||
usage: /home [名称]
|
||||
homes:
|
||||
description: 查看家列表
|
||||
usage: /homes
|
||||
sethome:
|
||||
description: 设置家
|
||||
usage: /sethome [名称]
|
||||
delhome:
|
||||
description: 删除家
|
||||
usage: /delhome <名称>
|
Loading…
Reference in New Issue
Block a user