This commit is contained in:
parent
e051167757
commit
d854a9b1ef
@ -1,6 +1,11 @@
|
|||||||
package cn.lunadeer.essentialsd;
|
package cn.lunadeer.essentialsd;
|
||||||
|
|
||||||
import cn.lunadeer.essentialsd.commands.*;
|
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.ConfigManager;
|
||||||
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
import cn.lunadeer.essentialsd.managers.DatabaseManager;
|
||||||
import cn.lunadeer.essentialsd.managers.TeleportManager;
|
import cn.lunadeer.essentialsd.managers.TeleportManager;
|
||||||
@ -27,8 +32,14 @@ public final class EssentialsD extends JavaPlugin {
|
|||||||
scheduler = new Scheduler(this);
|
scheduler = new Scheduler(this);
|
||||||
tpManager = new TeleportManager();
|
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 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 指令
|
// op 指令
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("fly")).setExecutor(new Fly());
|
Objects.requireNonNull(Bukkit.getPluginCommand("fly")).setExecutor(new Fly());
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("god")).setExecutor(new God());
|
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("tpa")).setExecutor(new Tpa());
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("rtp")).setExecutor(new Rtp());
|
Objects.requireNonNull(Bukkit.getPluginCommand("rtp")).setExecutor(new Rtp());
|
||||||
Objects.requireNonNull(Bukkit.getPluginCommand("back")).setExecutor(new Back());
|
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()) {
|
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 cn.lunadeer.essentialsd.utils.XLogger;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.block.Block;
|
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.EssentialsD;
|
||||||
import cn.lunadeer.essentialsd.recipes.Crowbar;
|
|
||||||
import cn.lunadeer.essentialsd.recipes.InvisibleGlowItemFrame;
|
import cn.lunadeer.essentialsd.recipes.InvisibleGlowItemFrame;
|
||||||
import cn.lunadeer.essentialsd.recipes.InvisibleItemFrame;
|
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.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
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.entity.*;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
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.HangingBreakByEntityEvent;
|
||||||
import org.bukkit.event.hanging.HangingPlaceEvent;
|
import org.bukkit.event.hanging.HangingPlaceEvent;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
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.inventory.ItemStack;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Events implements Listener {
|
public class InvisibleItemFrameEvent 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// place an Invisible Item Frame
|
// place an Invisible Item Frame
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void placeItemFrame(HangingPlaceEvent event) {
|
public void placeItemFrame(HangingPlaceEvent event) {
|
||||||
@ -127,80 +97,4 @@ public class Events implements Listener {
|
|||||||
itemFrame.setVisible(true);
|
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_hat = _file.getBoolean("Commands.Hat", true);
|
||||||
_commands_showitem = _file.getBoolean("Commands.ShowItem", true);
|
_commands_showitem = _file.getBoolean("Commands.ShowItem", true);
|
||||||
_commands_skull = _file.getBoolean("Commands.Skull", true);
|
_commands_skull = _file.getBoolean("Commands.Skull", true);
|
||||||
|
_commands_home = _file.getBoolean("Commands.Home", true);
|
||||||
_tp_delay = _file.getInt("Teleport.Delay", 0);
|
_tp_delay = _file.getInt("Teleport.Delay", 0);
|
||||||
_tp_cool_down = _file.getInt("Teleport.CoolDown", 0);
|
_tp_cool_down = _file.getInt("Teleport.CoolDown", 0);
|
||||||
_tp_tpa_expire = _file.getInt("Teleport.TpaExpire", 30);
|
_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_enable = _file.getBoolean("Chair.Enable", true);
|
||||||
_chair_max_width = _file.getInt("Chair.MaxWidth", 4);
|
_chair_max_width = _file.getInt("Chair.MaxWidth", 4);
|
||||||
_chair_sign_check = _file.getBoolean("Chair.SignCheck", true);
|
_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_invisible_item_frame = _file.getBoolean("Recipes.InvisibleItemFrame", true);
|
||||||
_recipes_light_block = _file.getBoolean("Recipes.LightBlock", true);
|
_recipes_light_block = _file.getBoolean("Recipes.LightBlock", true);
|
||||||
_recipes_stacked_enchant_book = _file.getBoolean("Recipes.StackedEnchantBook", 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");
|
_db_type = _file.getString("Database.Type", "sqlite");
|
||||||
if (!_db_type.equals("pgsql") && !_db_type.equals("sqlite")) {
|
if (!_db_type.equals("pgsql") && !_db_type.equals("sqlite")) {
|
||||||
XLogger.err("当前数据库只支持 pgsql 或 sqlite,已重置为 sqlite");
|
XLogger.err("当前数据库只支持 pgsql 或 sqlite,已重置为 sqlite");
|
||||||
@ -107,6 +111,10 @@ public class ConfigManager {
|
|||||||
return _tp_rtp_radius;
|
return _tp_rtp_radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getTpWorldBlackList() {
|
||||||
|
return _tp_world_blacklist;
|
||||||
|
}
|
||||||
|
|
||||||
public Boolean getCommandsTpa() {
|
public Boolean getCommandsTpa() {
|
||||||
return _commands_tpa;
|
return _commands_tpa;
|
||||||
}
|
}
|
||||||
@ -139,6 +147,10 @@ public class ConfigManager {
|
|||||||
return _commands_skull;
|
return _commands_skull;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getCommandsHome() {
|
||||||
|
return _commands_home;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Boolean getChairEnable() {
|
public Boolean getChairEnable() {
|
||||||
return _chair_enable;
|
return _chair_enable;
|
||||||
@ -210,6 +222,14 @@ public class ConfigManager {
|
|||||||
}, _chunk_operate_delay * 20);
|
}, _chunk_operate_delay * 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getHomeLimitAmount() {
|
||||||
|
return _home_limit_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getHomeWorldBlacklist() {
|
||||||
|
return _home_world_blacklist;
|
||||||
|
}
|
||||||
|
|
||||||
public String getDbType() {
|
public String getDbType() {
|
||||||
return _db_type;
|
return _db_type;
|
||||||
}
|
}
|
||||||
@ -269,6 +289,7 @@ public class ConfigManager {
|
|||||||
private Integer _tp_delay;
|
private Integer _tp_delay;
|
||||||
private Integer _tp_cool_down;
|
private Integer _tp_cool_down;
|
||||||
private Integer _tp_rtp_radius;
|
private Integer _tp_rtp_radius;
|
||||||
|
private List<String> _tp_world_blacklist;
|
||||||
private Boolean _chair_enable;
|
private Boolean _chair_enable;
|
||||||
private Integer _chair_max_width;
|
private Integer _chair_max_width;
|
||||||
private Boolean _chair_sign_check;
|
private Boolean _chair_sign_check;
|
||||||
@ -283,12 +304,17 @@ public class ConfigManager {
|
|||||||
private Boolean _commands_hat;
|
private Boolean _commands_hat;
|
||||||
private Boolean _commands_showitem;
|
private Boolean _commands_showitem;
|
||||||
private Boolean _commands_skull;
|
private Boolean _commands_skull;
|
||||||
|
private Boolean _commands_home;
|
||||||
// recipes
|
// recipes
|
||||||
private Boolean _recipes_crowbar;
|
private Boolean _recipes_crowbar;
|
||||||
private Boolean _recipes_invisible_item_frame;
|
private Boolean _recipes_invisible_item_frame;
|
||||||
private Boolean _recipes_light_block;
|
private Boolean _recipes_light_block;
|
||||||
private Boolean _recipes_stacked_enchant_book;
|
private Boolean _recipes_stacked_enchant_book;
|
||||||
|
|
||||||
|
// home limit
|
||||||
|
private Integer _home_limit_amount;
|
||||||
|
private List<String> _home_world_blacklist;
|
||||||
|
|
||||||
// database
|
// database
|
||||||
private String _db_type;
|
private String _db_type;
|
||||||
private String _db_host;
|
private String _db_host;
|
||||||
|
@ -102,10 +102,11 @@ public class DatabaseManager {
|
|||||||
" id SERIAL PRIMARY KEY," +
|
" id SERIAL PRIMARY KEY," +
|
||||||
" uuid VARCHAR(36) NOT NULL," +
|
" uuid VARCHAR(36) NOT NULL," +
|
||||||
" ip VARCHAR(15) NOT NULL," +
|
" ip VARCHAR(15) NOT NULL," +
|
||||||
" name TEXT NOT NULL," +
|
|
||||||
" login_time TIMESTAMP NOT NULL," +
|
" login_time TIMESTAMP NOT NULL," +
|
||||||
" logout_location TEXT," +
|
" logout_location TEXT," +
|
||||||
" logout_time TIMESTAMP" +
|
" logout_time TIMESTAMP," +
|
||||||
|
|
||||||
|
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
|
||||||
");";
|
");";
|
||||||
query(sql);
|
query(sql);
|
||||||
|
|
||||||
@ -114,7 +115,9 @@ public class DatabaseManager {
|
|||||||
" id SERIAL PRIMARY KEY," +
|
" id SERIAL PRIMARY KEY," +
|
||||||
" uuid VARCHAR(36) NOT NULL," +
|
" uuid VARCHAR(36) NOT NULL," +
|
||||||
" name TEXT 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);
|
query(sql);
|
||||||
|
|
||||||
@ -126,7 +129,9 @@ public class DatabaseManager {
|
|||||||
" to_location TEXT NOT NULL," +
|
" to_location TEXT NOT NULL," +
|
||||||
" type TEXT NOT NULL," +
|
" type TEXT NOT NULL," +
|
||||||
" success BOOLEAN 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);
|
query(sql);
|
||||||
|
|
||||||
@ -135,7 +140,9 @@ public class DatabaseManager {
|
|||||||
" id SERIAL PRIMARY KEY," +
|
" id SERIAL PRIMARY KEY," +
|
||||||
" sender_uuid VARCHAR(36) NOT NULL," +
|
" sender_uuid VARCHAR(36) NOT NULL," +
|
||||||
" message TEXT 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);
|
query(sql);
|
||||||
|
|
||||||
@ -144,7 +151,9 @@ public class DatabaseManager {
|
|||||||
" id SERIAL PRIMARY KEY," +
|
" id SERIAL PRIMARY KEY," +
|
||||||
" executor_uuid VARCHAR(36) NOT NULL," +
|
" executor_uuid VARCHAR(36) NOT NULL," +
|
||||||
" command TEXT 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);
|
query(sql);
|
||||||
|
|
||||||
@ -153,7 +162,9 @@ public class DatabaseManager {
|
|||||||
" id SERIAL PRIMARY KEY," +
|
" id SERIAL PRIMARY KEY," +
|
||||||
" uuid VARCHAR(36) NOT NULL," +
|
" uuid VARCHAR(36) NOT NULL," +
|
||||||
" home_name TEXT 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);
|
query(sql);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class TeleportManager {
|
public class TeleportManager {
|
||||||
|
|
||||||
@ -44,14 +45,9 @@ public class TeleportManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDateTime now = LocalDateTime.now();
|
if (EssentialsD.config.getTpWorldBlackList().contains(target.getWorld().getName())) {
|
||||||
LocalDateTime next_time = _next_time_allow_tp.get(initiator.getUniqueId());
|
Notification.error(initiator, "目的地所在世界 " + initiator.getWorld().getName() + " 不允许传送");
|
||||||
if (next_time != null) {
|
return;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TpTask task = new TpTask();
|
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).append(acceptBtn).append(Component.text(" ", main_color)).append(denyBtn));
|
||||||
Notification.info(target, Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color));
|
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) -> {
|
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
||||||
_tasks.remove(task.taskId);
|
_tasks.remove(task.taskId);
|
||||||
}, 20L * EssentialsD.config.getTpTpaExpire());
|
}, 20L * EssentialsD.config.getTpTpaExpire());
|
||||||
@ -110,17 +105,19 @@ public class TeleportManager {
|
|||||||
if (!task.initiator.isOnline() || !task.target.isOnline()) {
|
if (!task.initiator.isOnline() || !task.target.isOnline()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notification.info(task.target, "已接受 " + task.initiator.getName() + " 的传送请求");
|
Notification.info(task.target, "已接受 " + task.initiator.getName() + " 的传送请求");
|
||||||
if (EssentialsD.config.getTpDelay() > 0) {
|
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求");
|
||||||
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求,传送将在 " + EssentialsD.config.getTpDelay() + " 秒后进行");
|
try {
|
||||||
}
|
doTeleportDelayed(task.initiator, task.target.getLocation(), EssentialsD.config.getTpDelay(), () -> {
|
||||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
Notification.info(task.initiator, "正在传送到 " + task.initiator.getName() + " 的位置");
|
||||||
if (task.initiator.isOnline() && task.target.isOnline()) {
|
}, () -> {
|
||||||
doTeleportSafely(task.initiator, task.target.getLocation());
|
Notification.info(task.initiator, "已传送到 " + task.initiator.getName() + " 的位置");
|
||||||
Notification.info(task.initiator, "已传送到 " + task.target.getName() + " 的位置");
|
|
||||||
Notification.info(task.target, "玩家 " + 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) {
|
public void back(Player player) {
|
||||||
@ -128,29 +125,68 @@ public class TeleportManager {
|
|||||||
Notification.error(player, "没有找到可返回的位置");
|
Notification.error(player, "没有找到可返回的位置");
|
||||||
return;
|
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) {
|
if (EssentialsD.config.getTpDelay() > 0) {
|
||||||
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后返回上次传送的位置");
|
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后返回上次传送的位置");
|
||||||
}
|
}
|
||||||
EssentialsD.scheduler.global.runDelayed(EssentialsD.instance, (instance) -> {
|
try {
|
||||||
doTeleportSafely(player, _last_tp_location.get(player.getUniqueId()));
|
doTeleportDelayed(player, target, EssentialsD.config.getTpDelay(), () -> {
|
||||||
Notification.info(player, "已返回上次传送的位置");
|
Notification.info(player, "正在返回上次传送的位置");
|
||||||
}, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay());
|
}, () -> {
|
||||||
|
Notification.info(player, "已返回上次传送的位置");
|
||||||
|
});
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
Notification.error(player, e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rtp(Player player) {
|
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();
|
int radius = EssentialsD.config.getTpRtpRadius();
|
||||||
World world = player.getWorld();
|
World world = player.getWorld();
|
||||||
int x = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getX();
|
int x = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getX();
|
||||||
int z = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getZ();
|
int z = (int) (Math.random() * radius * 2) - radius + (int) player.getLocation().getZ();
|
||||||
XLogger.debug("RTP: " + x + " " + z);
|
XLogger.debug("RTP: " + x + " " + z);
|
||||||
Location location = new Location(world, x + 0.5, player.getY(), z + 0.5);
|
Location location = new Location(world, x + 0.5, player.getY(), z + 0.5);
|
||||||
if (EssentialsD.config.getTpDelay() > 0) {
|
try {
|
||||||
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后传送到随机位置");
|
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);
|
doTeleportSafely(player, location);
|
||||||
Notification.info(player, "已传送到随机位置");
|
after.run();
|
||||||
}, EssentialsD.config.getTpDelay() <= 0 ? 1 : 20L * EssentialsD.config.getTpDelay());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,16 +195,23 @@ public class TeleportManager {
|
|||||||
* @param player 玩家
|
* @param player 玩家
|
||||||
* @param location 位置
|
* @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) -> {
|
location.getWorld().getChunkAtAsyncUrgently(location).thenAccept((chunk) -> {
|
||||||
updateLastTpLocation(player);
|
|
||||||
int max_attempts = 512;
|
int max_attempts = 512;
|
||||||
while (location.getBlock().isPassable()) {
|
while (location.getBlock().isPassable()) {
|
||||||
location.setY(location.getY() - 1);
|
location.setY(location.getY() - 1);
|
||||||
max_attempts--;
|
max_attempts--;
|
||||||
if (max_attempts <= 0) {
|
if (max_attempts <= 0) {
|
||||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Block up1 = location.getBlock().getRelative(BlockFace.UP);
|
Block up1 = location.getBlock().getRelative(BlockFace.UP);
|
||||||
@ -180,15 +223,14 @@ public class TeleportManager {
|
|||||||
up2 = up1.getRelative(BlockFace.UP);
|
up2 = up1.getRelative(BlockFace.UP);
|
||||||
max_attempts--;
|
max_attempts--;
|
||||||
if (max_attempts <= 0) {
|
if (max_attempts <= 0) {
|
||||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
location.setY(location.getY() + 1);
|
location.setY(location.getY() + 1);
|
||||||
if (location.getBlock().getRelative(BlockFace.DOWN).getType() == Material.LAVA) {
|
if (location.getBlock().getRelative(BlockFace.DOWN).getType() == Material.LAVA) {
|
||||||
Notification.error(player, "传送目的地不安全,已取消传送");
|
throw new RuntimeException("传送目的地不安全,已取消传送");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
updateLastTpLocation(player);
|
||||||
player.teleportAsync(location, PlayerTeleportEvent.TeleportCause.PLUGIN);
|
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 {
|
public class Line {
|
||||||
|
private String d = " - ";
|
||||||
private final List<Component> elements = new ArrayList<>();
|
private final List<Component> elements = new ArrayList<>();
|
||||||
|
|
||||||
private final TextComponent divider = Component.text(" - ", ViewStyles.sub_color);
|
|
||||||
|
|
||||||
public Line() {
|
public Line() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextComponent build() {
|
public TextComponent build() {
|
||||||
|
TextComponent divider = Component.text(d, ViewStyles.sub_color);
|
||||||
TextComponent.Builder builder = Component.text();
|
TextComponent.Builder builder = Component.text();
|
||||||
for (int i = 0; i < elements.size(); i++) {
|
for (int i = 0; i < elements.size(); i++) {
|
||||||
builder.append(elements.get(i));
|
builder.append(elements.get(i));
|
||||||
@ -30,11 +30,20 @@ public class Line {
|
|||||||
return new Line();
|
return new Line();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Component> getElements() {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
public Line append(TextComponent component) {
|
public Line append(TextComponent component) {
|
||||||
elements.add(component);
|
elements.add(component);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Line setDivider(String d) {
|
||||||
|
this.d = d;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Line append(Component component) {
|
public Line append(Component component) {
|
||||||
elements.add(component);
|
elements.add(component);
|
||||||
return this;
|
return this;
|
||||||
@ -45,4 +54,4 @@ public class Line {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package cn.lunadeer.essentialsd.utils.STUI;
|
package cn.lunadeer.essentialsd.utils.STUI;
|
||||||
|
|
||||||
import cn.lunadeer.essentialsd.utils.Notification;
|
import cn.lunadeer.essentialsd.utils.Notification;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.TextComponent;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -13,7 +15,7 @@ public class ListView {
|
|||||||
private String command = "";
|
private String command = "";
|
||||||
private final View view = View.create();
|
private final View view = View.create();
|
||||||
|
|
||||||
public ListView(int page_size, String command) {
|
private ListView(int page_size, String command) {
|
||||||
super();
|
super();
|
||||||
this.page_size = page_size;
|
this.page_size = page_size;
|
||||||
this.command = command;
|
this.command = command;
|
||||||
@ -39,6 +41,16 @@ public class ListView {
|
|||||||
return this;
|
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) {
|
public ListView add(Line line) {
|
||||||
lines.add(line);
|
lines.add(line);
|
||||||
return this;
|
return this;
|
||||||
@ -61,11 +73,23 @@ public class ListView {
|
|||||||
}
|
}
|
||||||
for (int i = offset; i < offset + page_size; i++) {
|
for (int i = offset; i < offset + page_size; i++) {
|
||||||
if (i >= lines.size()) {
|
if (i >= lines.size()) {
|
||||||
|
for (int j = 0; j < page_size - lines.size() % page_size; j++) {
|
||||||
|
view.addLine(Line.create());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
view.addLine(lines.get(i));
|
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);
|
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 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 页 [上一页] [下一页]
|
// 第 x/y 页 [上一页] [下一页]
|
||||||
int page_size = 4;
|
|
||||||
int page_count = (int) Math.ceil((double) item_size / page_size);
|
int page_count = (int) Math.ceil((double) item_size / page_size);
|
||||||
if (page_count == 0) {
|
if (page_count == 0) {
|
||||||
page_count = 1;
|
page_count = 1;
|
||||||
@ -26,9 +25,13 @@ public class Pagination {
|
|||||||
componentList.add(Component.text(" 页 ", main_color));
|
componentList.add(Component.text(" 页 ", main_color));
|
||||||
if (page > 1) {
|
if (page > 1) {
|
||||||
componentList.add(Button.create("上一页", command + " " + (page - 1)));
|
componentList.add(Button.create("上一页", command + " " + (page - 1)));
|
||||||
|
} else {
|
||||||
|
componentList.add(Component.text("[上一页]", sub_color));
|
||||||
}
|
}
|
||||||
if (page < page_count) {
|
if (page < page_count) {
|
||||||
componentList.add(Button.create("下一页", command + " " + (page + 1)));
|
componentList.add(Button.create("下一页", command + " " + (page + 1)));
|
||||||
|
} else {
|
||||||
|
componentList.add(Component.text("[下一页]", sub_color));
|
||||||
}
|
}
|
||||||
TextComponent.Builder builder = Component.text();
|
TextComponent.Builder builder = Component.text();
|
||||||
for (Component component : componentList) {
|
for (Component component : componentList) {
|
||||||
|
@ -10,33 +10,25 @@ import java.util.List;
|
|||||||
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.main_color;
|
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.main_color;
|
||||||
|
|
||||||
public class View {
|
public class View {
|
||||||
protected TextComponent title_decorate = Component.text("━", main_color);
|
|
||||||
protected TextComponent space = Component.text(" ");
|
protected TextComponent space = Component.text(" ");
|
||||||
protected TextComponent sub_title_decorate = Component.text("- ", main_color);
|
protected TextComponent sub_title_decorate = Component.text("- ", main_color);
|
||||||
protected TextComponent line_decorate = Component.text("⌗ ", main_color);
|
protected TextComponent line_decorate = Component.text("⌗ ", main_color);
|
||||||
protected TextComponent action_decorate = Component.text("▸ ", main_color);
|
protected TextComponent action_decorate = Component.text("▸ ", main_color);
|
||||||
protected TextComponent title = Component.text(" ");
|
protected TextComponent title = Component.text(" ");
|
||||||
protected TextComponent subtitle = Component.text("");
|
protected TextComponent subtitle = null;
|
||||||
protected List<TextComponent> content_lines = new ArrayList<>();
|
protected List<TextComponent> content_lines = new ArrayList<>();
|
||||||
protected TextComponent actionbar = Component.text(" ");
|
protected TextComponent actionbar = null;
|
||||||
protected TextComponent edge = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
protected TextComponent edge = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||||
protected TextComponent divide_line = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
protected TextComponent divide_line = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
|
||||||
|
|
||||||
public void showOn(Player player) {
|
public void showOn(Player player) {
|
||||||
player.sendMessage(edge);
|
// player.sendMessage(edge);
|
||||||
TextComponent.Builder builder = Component.text();
|
TextComponent.Builder builder = Component.text();
|
||||||
int title_length = title.content().length();
|
builder.append(Component.text("__/", main_color));
|
||||||
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(space).append(title).append(space);
|
builder.append(space).append(title).append(space);
|
||||||
for (int i = 0; i < decorate_count / 2; i++) {
|
builder.append(Component.text("\\__", main_color));
|
||||||
builder.append(title_decorate);
|
|
||||||
}
|
|
||||||
player.sendMessage(builder.build());
|
player.sendMessage(builder.build());
|
||||||
if (subtitle.content().length() > 0) {
|
if (subtitle != null) {
|
||||||
player.sendMessage(divide_line);
|
player.sendMessage(divide_line);
|
||||||
player.sendMessage(Component.text().append(sub_title_decorate).append(subtitle).build());
|
player.sendMessage(Component.text().append(sub_title_decorate).append(subtitle).build());
|
||||||
}
|
}
|
||||||
@ -44,8 +36,10 @@ public class View {
|
|||||||
for (TextComponent content_line : content_lines) {
|
for (TextComponent content_line : content_lines) {
|
||||||
player.sendMessage(Component.text().append(line_decorate).append(content_line).build());
|
player.sendMessage(Component.text().append(line_decorate).append(content_line).build());
|
||||||
}
|
}
|
||||||
player.sendMessage(divide_line);
|
if (actionbar != null) {
|
||||||
player.sendMessage(Component.text().append(action_decorate).append(actionbar).build());
|
player.sendMessage(divide_line);
|
||||||
|
player.sendMessage(Component.text().append(action_decorate).append(actionbar).build());
|
||||||
|
}
|
||||||
player.sendMessage(edge);
|
player.sendMessage(edge);
|
||||||
player.sendMessage(Component.text(" "));
|
player.sendMessage(Component.text(" "));
|
||||||
}
|
}
|
||||||
@ -69,6 +63,19 @@ public class View {
|
|||||||
return this;
|
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) {
|
public View subtitle(TextComponent subtitle) {
|
||||||
this.subtitle = subtitle;
|
this.subtitle = subtitle;
|
||||||
return this;
|
return this;
|
||||||
@ -103,4 +110,4 @@ public class View {
|
|||||||
this.content_lines.add(component.build());
|
this.content_lines.add(component.build());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,13 +37,15 @@ Commands:
|
|||||||
Tpa: true # 传送到其他玩家
|
Tpa: true # 传送到其他玩家
|
||||||
Rtp: true # 随机传送到附近
|
Rtp: true # 随机传送到附近
|
||||||
Back: true # 回到上一个传送位置
|
Back: true # 回到上一个传送位置
|
||||||
|
Home: true # home相关指令 包含 sethome delhome home homes
|
||||||
|
|
||||||
# 传送
|
# 传送
|
||||||
Teleport:
|
Teleport:
|
||||||
Delay: 0 # 传送延迟 秒
|
Delay: 0 # 传送延迟 秒
|
||||||
CoolDown: 0 # 冷却时间 秒
|
CoolDown: 0 # 冷却时间 秒
|
||||||
TpaExpire: 30 # 传送请求有效期 秒
|
TpaExpire: 30 # 传送请求有效期 秒
|
||||||
RtpRadius: 1000 # 随机传送最大半径
|
RtpRadius: 1000 # 随机传送最大半径
|
||||||
|
WorldBlackList: [ ] # 不允许传送的世界
|
||||||
|
|
||||||
# 把楼梯当作椅子使用
|
# 把楼梯当作椅子使用
|
||||||
Chair:
|
Chair:
|
||||||
@ -52,6 +54,11 @@ Chair:
|
|||||||
SignCheck: false
|
SignCheck: false
|
||||||
SitHeight: -0.95
|
SitHeight: -0.95
|
||||||
|
|
||||||
|
# home 相关限制
|
||||||
|
HomeLimit:
|
||||||
|
Amount: 5 # 数量限制
|
||||||
|
WorldBlackList: [ ] # 不允许设置 home 的世界
|
||||||
|
|
||||||
Debug: false
|
Debug: false
|
||||||
|
|
||||||
CheckUpdate: true
|
CheckUpdate: true
|
@ -63,4 +63,16 @@ commands:
|
|||||||
usage: /back
|
usage: /back
|
||||||
inspect:
|
inspect:
|
||||||
description: 检查玩家背包
|
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