Compare commits

..

15 Commits

Author SHA1 Message Date
cd9f4549b2 尝试增加tab列表对齐功能(暂未成功) 2024-08-23 17:53:05 +08:00
6937a15225 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pom.xml
2024-08-23 10:31:49 +08:00
937f9fcd8f 实现了tab papi功能
Some checks failed
Java CI-CD with Maven / build (push) Failing after 4m10s
2024-08-23 10:30:49 +08:00
06aeb33f50 修复了warp在不指定传送点时没有提示而是报错问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 13m24s
2024-08-18 12:25:06 +08:00
6381d51950 测试完成聊天前缀
All checks were successful
Java CI-CD with Maven / build (push) Successful in 11m3s
2024-08-11 12:00:40 +08:00
b44e5a658b Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pom.xml
#	src/main/java/cn/lunadeer/essentialsd/events/ChatPrefixEvent.java
2024-08-11 11:58:41 +08:00
6a7e8b066a 测试了聊天前缀功能
All checks were successful
Java CI-CD with Maven / build (push) Successful in 14m28s
2024-08-11 11:57:19 +08:00
43dc8f0abc 更新 api 版本至 1.21.1 2024-08-11 02:34:39 +08:00
2da5d164d7 更新版本 2024-08-10 23:33:50 +08:00
b71fec6329 实现了prefix功能(未测试) 2024-08-10 20:22:01 +08:00
50c8d8812a 新增 warp 功能
All checks were successful
Java CI-CD with Maven / build (push) Successful in 21m25s
2024-08-09 11:45:32 +08:00
ad8fc39ab8 补充注释 2024-08-08 23:54:53 +08:00
37b773c6c3 新增warp功能 2024-08-08 23:52:40 +08:00
e50f0d035c rtp强制传送到主世界 2024-08-08 22:39:29 +08:00
cbf9718fb0 修复 god fly inspect指令异常问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m15s
2024-08-01 13:45:11 +08:00
32 changed files with 647 additions and 23 deletions

View File

@ -15,10 +15,10 @@ jobs:
fetch-depth: 0
- name: "Set up Maven"
uses: https://ssl.lunadeer.cn:14446/actions/setup-maven@v4
- name: "Set up JDK 17"
- name: "Set up JDK 21"
uses: https://ssl.lunadeer.cn:14446/actions/setup-java@v3
with:
java-version: '17'
java-version: '21'
distribution: 'zulu'
cache: maven
- name: "Build with Maven"

View File

@ -7,7 +7,7 @@ EssentialsX其中D代表Deer。
## 支持版本
- 1.20.1+ (Folia)
- 1.21.1+ (Folia)
## 安装方法

18
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId>
<artifactId>EssentialsD</artifactId>
<version>2.0.1</version>
<version>2.3.1</version>
<packaging>jar</packaging>
<name>EssentialsD</name>
@ -70,13 +70,17 @@
<id>lunadeer-repo</id>
<url>https://ssl.lunadeer.cn:14454/repository/maven-snapshots/</url>
</repository>
<repository>
<id>placeholderapi</id>
<url>https://repo.extendedclip.com/content/repositories/placeholderapi/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>dev.folia</groupId>
<artifactId>folia-api</artifactId>
<version>1.20.1-R0.1-SNAPSHOT</version>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
@ -90,5 +94,11 @@
<version>1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
<version>2.11.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -5,9 +5,24 @@ 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.commands.time.Day;
import cn.lunadeer.essentialsd.commands.time.Night;
import cn.lunadeer.essentialsd.commands.time.Noon;
import cn.lunadeer.essentialsd.commands.tp.Back;
import cn.lunadeer.essentialsd.commands.tp.Rtp;
import cn.lunadeer.essentialsd.commands.tp.Tpa;
import cn.lunadeer.essentialsd.commands.tp.TpaHere;
import cn.lunadeer.essentialsd.commands.warp.DelWarp;
import cn.lunadeer.essentialsd.commands.warp.SetWarp;
import cn.lunadeer.essentialsd.commands.warp.Warp;
import cn.lunadeer.essentialsd.commands.warp.Warps;
import cn.lunadeer.essentialsd.commands.weather.Rain;
import cn.lunadeer.essentialsd.commands.weather.Storm;
import cn.lunadeer.essentialsd.commands.weather.Sun;
import cn.lunadeer.essentialsd.events.*;
import cn.lunadeer.essentialsd.managers.ConfigManager;
import cn.lunadeer.essentialsd.managers.DatabaseTables;
import cn.lunadeer.essentialsd.managers.TabListUpdater;
import cn.lunadeer.essentialsd.managers.TeleportManager;
import cn.lunadeer.essentialsd.recipes.*;
import cn.lunadeer.minecraftpluginutils.*;
@ -24,7 +39,6 @@ public final class EssentialsD extends JavaPlugin {
instance = this;
new XLogger(instance);
config = new ConfigManager(instance);
XLogger.setDebug(config.isDebug());
new Notification(instance);
database = new DatabaseManager(this,
DatabaseManager.TYPE.valueOf(config.getDbType().toUpperCase()),
@ -37,6 +51,16 @@ public final class EssentialsD extends JavaPlugin {
new Scheduler(this);
tpManager = new TeleportManager();
if (config.getPrefixEnable()) {
if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
Bukkit.getPluginManager().registerEvents(new ChatPrefixEvent(), this);
new TabListUpdater(); // 更新 TabList
} else {
XLogger.warn("未找到 PlaceholderAPI 插件, 无法使用聊天前缀功能, 已自动关闭前缀功能");
config.setPrefixEnable(false);
}
}
Bukkit.getPluginManager().registerEvents(new InvisibleItemFrameEvent(), this);
Bukkit.getPluginManager().registerEvents(new ChairEvent(), this);
Bukkit.getPluginManager().registerEvents(new ArmorStandHandsEvent(), this);
@ -64,14 +88,21 @@ public final class EssentialsD extends JavaPlugin {
Objects.requireNonNull(Bukkit.getPluginCommand("hat")).setExecutor(new Hat());
Objects.requireNonNull(Bukkit.getPluginCommand("showitem")).setExecutor(new ShowItem());
Objects.requireNonNull(Bukkit.getPluginCommand("skull")).setExecutor(new Skull());
// tp
Objects.requireNonNull(Bukkit.getPluginCommand("tpa")).setExecutor(new Tpa());
Objects.requireNonNull(Bukkit.getPluginCommand("tpahere")).setExecutor(new TpaHere());
Objects.requireNonNull(Bukkit.getPluginCommand("rtp")).setExecutor(new Rtp());
Objects.requireNonNull(Bukkit.getPluginCommand("back")).setExecutor(new Back());
// home
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());
// warp
Objects.requireNonNull(Bukkit.getPluginCommand("setwarp")).setExecutor(new SetWarp());
Objects.requireNonNull(Bukkit.getPluginCommand("delwarp")).setExecutor(new DelWarp());
Objects.requireNonNull(Bukkit.getPluginCommand("warp")).setExecutor(new Warp());
Objects.requireNonNull(Bukkit.getPluginCommand("warps")).setExecutor(new Warps());
if (config.getRecipesCrowbar()) {

View File

@ -19,6 +19,14 @@ public class Apis {
* @return 如果指定了玩家则返回玩家对象否则返回命令发送者
*/
public static Player getPlayerFromArg(CommandSender sender, String[] args, int pos) {
if (args.length <= pos) {
if (sender instanceof Player) {
return (Player) sender;
} else {
Notification.error(sender, "以控制台身份执行时,必须指定玩家");
return null;
}
}
Player target = EssentialsD.instance.getServer().getPlayer(args[pos]);
if (target == null) {
Notification.warn(sender, "玩家 %s 不在线", args[0]);

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -0,0 +1,38 @@
package cn.lunadeer.essentialsd.commands.warp;
import cn.lunadeer.essentialsd.dtos.WarpPoint;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class DelWarp implements TabExecutor {
/**
* /delwarp <name>
*/
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (strings.length != 1) {
Notification.error(commandSender, "用法: /delwarp <name>");
return true;
}
WarpPoint point = WarpPoint.selectByName(strings[0]);
if (point == null) {
Notification.error(commandSender, "传送点 %s 不存在", strings[0]);
return true;
}
WarpPoint.delete(point);
Notification.info(commandSender, "传送点 %s 已删除", strings[0]);
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return WarpPoint.selectAllNames();
}
}

View File

@ -0,0 +1,86 @@
package cn.lunadeer.essentialsd.commands.warp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.dtos.WarpPoint;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
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 SetWarp implements TabExecutor {
/**
* /setwarp <name>
* /setwarp <name> <world> <x> <y> <z>
*/
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (strings.length != 1 && strings.length != 5) {
Notification.error(commandSender, "用法: /setwarp <name> 或 /setwarp <name> <world> <x> <y> <z>");
return true;
}
String name = strings[0];
Location location;
if (strings.length == 1) {
if (commandSender instanceof Player) {
location = ((Player) commandSender).getLocation();
} else {
Notification.error(commandSender, "请指定坐标 /setwarp <name> <world> <x> <y> <z>");
return true;
}
} else {
try {
double x = Double.parseDouble(strings[1]);
double y = Double.parseDouble(strings[2]);
double z = Double.parseDouble(strings[3]);
World world = EssentialsD.instance.getServer().getWorld(strings[0]);
if (world == null) {
Notification.error(commandSender, "世界 %s 不存在", strings[0]);
return true;
}
location = new Location(world, x, y, z);
} catch (NumberFormatException e) {
Notification.error(commandSender, "坐标必须是数字");
return true;
}
}
WarpPoint existing = WarpPoint.selectByName(name);
if (existing != null) {
Notification.error(commandSender, "传送点 %s 已存在", name);
return true;
}
WarpPoint point = new WarpPoint(name, location);
WarpPoint.insert(point);
Notification.info(commandSender, "传送点 %s 已设置", name);
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
List<String> res = new ArrayList<>();
if (args.length == 1) {
res.add("传送点名称");
}
if (args.length == 2) {
res.add("世界名称");
}
if (args.length == 3) {
res.add("x");
}
if (args.length == 4) {
res.add("y");
}
if (args.length == 5) {
res.add("z");
}
return res;
}
}

View File

@ -0,0 +1,52 @@
package cn.lunadeer.essentialsd.commands.warp;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.dtos.WarpPoint;
import cn.lunadeer.minecraftpluginutils.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 Warp implements TabExecutor {
/**
* /warp <name>
*/
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (!(commandSender instanceof Player)) {
Notification.warn(commandSender, "只有玩家可以使用此命令");
return true;
}
Player player = (Player) commandSender;
if (strings.length != 1) {
Notification.error(commandSender, "用法: /warp <name>");
return true;
}
WarpPoint point = WarpPoint.selectByName(strings[0]);
if (point == null) {
Notification.error(commandSender, "传送点 %s 不存在", strings[0]);
return true;
}
try {
EssentialsD.tpManager.doTeleportDelayed(player, point.getLocation(), EssentialsD.config.getTpDelay(), () -> {
Notification.info(player, "正在传送到 %s", strings[0]);
}, () -> {
Notification.info(player, "已传送到 %s", strings[0]);
});
} catch (RuntimeException e) {
Notification.error(player, e.getMessage());
}
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return WarpPoint.selectAllNames();
}
}

View File

@ -0,0 +1,15 @@
package cn.lunadeer.essentialsd.commands.warp;
import cn.lunadeer.essentialsd.tuis.WarpList;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class Warps implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
WarpList.show(commandSender, strings);
return true;
}
}

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -1,4 +1,4 @@
package cn.lunadeer.essentialsd.commands;
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;

View File

@ -0,0 +1,100 @@
package cn.lunadeer.essentialsd.dtos;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.utils.LocUtil;
import org.bukkit.Location;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class WarpPoint {
private Integer id;
private final String name;
private final Location location;
public WarpPoint(Integer id, String name, Location location) {
this.id = id;
this.name = name;
this.location = location;
}
public WarpPoint(String name, Location location) {
this.name = name;
this.location = location;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public Location getLocation() {
return location;
}
public static void insert(WarpPoint point) {
String sql = "INSERT INTO warp_point (warp_name, location) VALUES (?, ?);";
try (ResultSet rs = EssentialsD.database.query(sql, point.getName(), LocUtil.toString(point.getLocation()))) {
if (rs == null) return;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("插入传送点失败", e, sql);
}
}
public static void delete(WarpPoint point) {
String sql = "DELETE FROM warp_point WHERE warp_name = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, point.getName())) {
if (rs == null) return;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("删除传送点失败", e, sql);
}
}
public static WarpPoint selectByName(String name) {
String sql = "SELECT * FROM warp_point WHERE warp_name = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, name)) {
if (rs == null) return null;
if (rs.next()) {
return new WarpPoint(rs.getInt("id"), rs.getString("warp_name"), LocUtil.fromString(rs.getString("location")));
}
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("查询传送点失败", e, sql);
return null;
}
return null;
}
public static List<String> selectAllNames() {
List<String> names = new ArrayList<>();
String sql = "SELECT DISTINCT warp_name FROM warp_point;";
try (ResultSet rs = EssentialsD.database.query(sql)) {
if (rs == null) return names;
while (rs.next()) {
names.add(rs.getString("warp_name"));
}
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("查询传送点名字失败", e, sql);
return names;
}
return names;
}
public static List<WarpPoint> selectAll() {
List<WarpPoint> points = new ArrayList<>();
String sql = "SELECT * FROM warp_point;";
try (ResultSet rs = EssentialsD.database.query(sql)) {
if (rs == null) return points;
while (rs.next()) {
points.add(new WarpPoint(rs.getInt("id"), rs.getString("warp_name"), LocUtil.fromString(rs.getString("location"))));
}
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("查询传送点失败", e, sql);
return points;
}
return points;
}
}

View File

@ -16,11 +16,11 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDismountEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.util.Vector;
import org.spigotmc.event.entity.EntityDismountEvent;
public class ChairEvent implements Listener {

View File

@ -0,0 +1,19 @@
package cn.lunadeer.essentialsd.events;
import cn.lunadeer.essentialsd.EssentialsD;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
public class ChatPrefixEvent implements Listener {
@EventHandler
public void onChat(AsyncPlayerChatEvent event) {
event.setCancelled(true);
String formated = PlaceholderAPI.setPlaceholders(event.getPlayer(), EssentialsD.config.getPrefixChatFormat());
formated += event.getMessage();
EssentialsD.instance.getServer().broadcastMessage(formated);
}
}

View File

@ -23,6 +23,7 @@ public class ConfigManager {
_plugin.reloadConfig();
_file = _plugin.getConfig();
_debug = _file.getBoolean("Debug", false);
XLogger.setDebug(isDebug());
_check_update = _file.getBoolean("CheckUpdate", true);
_exp_bottle_ratio = (float) _file.getDouble("ExpBottleRatio", 1.0);
_combine_exp_orbs_enable = _file.getBoolean("CombineExpOrbs.Enable", false);
@ -55,6 +56,46 @@ public class ConfigManager {
_db_name = _file.getString("Database.Name", "dominion");
_db_user = _file.getString("Database.User", "postgres");
_db_pass = _file.getString("Database.Pass", "postgres");
_prefix_enable = _file.getBoolean("Prefix.Enable", true);
_prefix_chat_format = _file.getString("Prefix.ChatFormat", "<%player_name%> ");
_prefix_tab_format = _file.getString("Prefix.TabFormat", "%player_name%");
saveAll(); // save all to make sure all values are valid
}
private void saveAll() {
_file.set("Debug", _debug);
_file.set("CheckUpdate", _check_update);
_file.set("ExpBottleRatio", _exp_bottle_ratio);
_file.set("CombineExpOrbs.Enable", _combine_exp_orbs_enable);
_file.set("CombineExpOrbs.Radius", _combine_exp_orbs_radius);
_file.set("NoExpCoolDown", _no_exp_cool_down);
_file.set("ForceLoadChunks", _force_load_chunks);
_file.set("ChunkOperateDelay", _chunk_operate_delay);
_file.set("Teleport.Delay", _tp_delay);
_file.set("Teleport.CoolDown", _tp_cool_down);
_file.set("Teleport.TpaExpire", _tp_tpa_expire);
_file.set("Teleport.RtpRadius", _tp_rtp_radius);
_file.set("Teleport.WorldBlackList", _tp_world_blacklist);
_file.set("Chair.Enable", _chair_enable);
_file.set("Chair.MaxWidth", _chair_max_width);
_file.set("Chair.SignCheck", _chair_sign_check);
_file.set("Chair.SitHeight", _chair_sit_height);
_file.set("Recipes.CrowBar", _recipes_crowbar);
_file.set("Recipes.InvisibleItemFrame", _recipes_invisible_item_frame);
_file.set("Recipes.LightBlock", _recipes_light_block);
_file.set("Recipes.StackedEnchantBook", _recipes_stacked_enchant_book);
_file.set("HomeLimit.Amount", _home_limit_amount);
_file.set("HomeLimit.WorldBlacklist", _home_world_blacklist);
_file.set("Database.Type", _db_type);
_file.set("Database.Host", _db_host);
_file.set("Database.Port", _db_port);
_file.set("Database.Name", _db_name);
_file.set("Database.User", _db_user);
_file.set("Database.Pass", _db_pass);
_file.set("Prefix.Enable", _prefix_enable);
_file.set("Prefix.ChatFormat", _prefix_chat_format);
_file.set("Prefix.TabFormat", _prefix_tab_format);
_plugin.saveConfig();
}
public Boolean isDebug() {
@ -274,6 +315,36 @@ public class ConfigManager {
return _db_pass;
}
public Boolean getPrefixEnable() {
return _prefix_enable;
}
public void setPrefixEnable(Boolean enable) {
_prefix_enable = enable;
_file.set("Prefix.Enable", enable);
_plugin.saveConfig();
}
public String getPrefixChatFormat() {
return _prefix_chat_format;
}
public void setPrefixChatFormat(String format) {
_prefix_chat_format = format;
_file.set("Prefix.Format", format);
_plugin.saveConfig();
}
public String getPrefixTabFormat() {
return _prefix_tab_format;
}
public void setPrefixTabFormat(String format) {
_prefix_tab_format = format;
_file.set("Prefix.TabFormat", format);
_plugin.saveConfig();
}
private final EssentialsD _plugin;
private FileConfiguration _file;
@ -311,4 +382,9 @@ public class ConfigManager {
private String _db_user;
private String _db_pass;
private String _db_name;
// prefix
private Boolean _prefix_enable;
private String _prefix_chat_format;
private String _prefix_tab_format;
}

View File

@ -84,5 +84,13 @@ public class DatabaseTables {
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
");";
EssentialsD.database.query(sql);
// warp info
sql = "CREATE TABLE IF NOT EXISTS warp_point (" +
" id SERIAL PRIMARY KEY," +
" warp_name TEXT NOT NULL," +
" location TEXT NOT NULL" +
");";
EssentialsD.database.query(sql);
}
}

View File

@ -0,0 +1,67 @@
package cn.lunadeer.essentialsd.managers;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class TabListUpdater {
public static TabListUpdater instance;
public TabListUpdater() {
instance = this;
Scheduler.runTaskRepeatAsync(this::update, 0, 40);
}
private void update() {
Collection<? extends Player> players = Bukkit.getOnlinePlayers();
Map<UUID, String> formatedNames = new HashMap<>();
int longestFormatedStringLength = 0;
for (Player player : players) {
String formated = PlaceholderAPI.setPlaceholders(player, EssentialsD.config.getPrefixTabFormat());
if (length(formated) > longestFormatedStringLength) {
longestFormatedStringLength = length(formated);
}
formatedNames.put(player.getUniqueId(), formated);
}
// <span> 将会被替换为填充空格 " " 用于保证长度一致
for (Player player : players) {
String formated = formatedNames.get(player.getUniqueId());
int formatedLength = length(formated);
int spaceLength = longestFormatedStringLength - formatedLength;
StringBuilder space = new StringBuilder();
for (int i = 0; i < spaceLength; i++) {
space.append(" ");
}
player.setPlayerListName(formated.replace("<span>", space.toString()));
}
}
private static int length(String value) {
int valueLength = 0;
String chinese = "[\u0391-\uFFE5]";
/* 获取字段值的长度如果含中文字符则每个中文字符长度为2否则为1 */
for (int i = 0; i < value.length(); i++) {
/* 获取一个字符 */
String temp = value.substring(i, i + 1);
/* 判断是否为中文字符 */
if (temp.matches(chinese)) {
/* 中文字符长度为2 */
valueLength += 2;
} else {
/* 其他字符长度为1 */
valueLength += 1;
}
}
return valueLength;
}
}

View File

@ -199,7 +199,18 @@ public class TeleportManager {
}
if (CoolingDown(player)) return;
int radius = EssentialsD.config.getTpRtpRadius();
World world = player.getWorld();
// get main world
World world = null;
for (World w : EssentialsD.instance.getServer().getWorlds()) {
if (w.getEnvironment() == World.Environment.NORMAL) {
world = w;
break;
}
}
if (world == null) {
Notification.error(player, "未找到主世界");
return;
}
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);

View File

@ -1,6 +1,7 @@
package cn.lunadeer.essentialsd.recipes;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.XLogger;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;

View File

@ -19,7 +19,7 @@ public class HomeList {
}
Player player = (Player) sender;
List<HomeInfo> homes = HomeInfo.getHomesOf(((Player) sender).getUniqueId());
if (homes.size() == 0) {
if (homes.isEmpty()) {
Notification.warn(player, "你还没有设置家");
return;
}

View File

@ -0,0 +1,45 @@
package cn.lunadeer.essentialsd.tuis;
import cn.lunadeer.essentialsd.dtos.HomeInfo;
import cn.lunadeer.essentialsd.dtos.WarpPoint;
import cn.lunadeer.essentialsd.utils.LocUtil;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.stui.ListView;
import cn.lunadeer.minecraftpluginutils.stui.components.Button;
import cn.lunadeer.minecraftpluginutils.stui.components.Line;
import net.kyori.adventure.text.Component;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
public class WarpList {
public static void show(CommandSender sender, String[] args) {
if (!(sender instanceof Player)) {
Notification.warn(sender, "只有玩家可以使用此命令");
return;
}
Player player = (Player) sender;
List<WarpPoint> points = WarpPoint.selectAll();
if (points.isEmpty()) {
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, "/warps");
view.title("Warp 列表");
for (WarpPoint point : points) {
Line line = Line.create()
.append(Component.text(point.getName()).hoverEvent(Component.text(LocUtil.toString(point.getLocation()))))
.append(Button.create("传送").setExecuteCommand("/warp " + point.getName()).build());
view.add(line);
}
view.showOn(player, page);
}
}

View File

@ -0,0 +1,23 @@
package cn.lunadeer.essentialsd.utils;
import org.bukkit.Location;
public class LocUtil {
public static String toString(Location loc) {
return String.format("[%s, %.2f, %.2f, %.2f, %.2f, %.2f]", loc.getWorld().getName(), loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
}
public static Location fromString(String str) {
String[] parts = str.substring(1, str.length() - 1).split(", ");
return new Location(
org.bukkit.Bukkit.getWorld(parts[0]),
Double.parseDouble(parts[1]),
Double.parseDouble(parts[2]),
Double.parseDouble(parts[3]),
Float.parseFloat(parts[4]),
Float.parseFloat(parts[5])
);
}
}

View File

@ -55,6 +55,12 @@ HomeLimit:
Amount: 5 # 数量限制
WorldBlackList: [ ] # 不允许设置 home 的世界
# prefix (需要 PlaceholderAPI 支持)
Prefix:
Enable: false
ChatFormat: '<%player_name%> '
TabFormat: '%player_name%'
Debug: false
CheckUpdate: true

View File

@ -1,13 +1,14 @@
name: EssentialsD
version: '${project.version}'
main: cn.lunadeer.essentialsd.EssentialsD
api-version: '1.20'
api-version: '1.21'
description: Deer's Essentials
website: https://lunadeer.cn
load: STARTUP
folia-supported: true
softdepend:
- LuckPerms
- PlaceholderAPI
permissions:
essd.*:
default: op
@ -45,6 +46,13 @@ permissions:
default: op
essd.home:
default: true
essd.setwarp:
default: op
essd.delwarp:
default: op
essd.warp:
default: true
commands:
suicide:
@ -166,4 +174,24 @@ commands:
description: 删除家
usage: /delhome <名称>
permission: essd.home
permission-message: 你没有权限使用home。
permission-message: 你没有权限使用home。
setwarp:
description: 设置传送点
usage: /setwarp <名称>
permission: essd.setwarp
permission-message: 你没有权限设置传送点。
delwarp:
description: 删除传送点
usage: /delwarp <名称>
permission: essd.delwarp
permission-message: 你没有权限删除传送点。
warp:
description: 传送到传送点
usage: /warp <名称>
permission: essd.warp
permission-message: 你没有权限传送到传送点。
warps:
description: 查看传送点列表
usage: /warps
permission: essd.warp
permission-message: 你没有权限查看传送点列表。