Compare commits

...

78 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
f19d8de23d 修复了tpahere无法接受请求的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 8m23s
2024-07-18 20:09:12 +08:00
440c4c9fa6 新增权限节点支持,移除配置文件的commands
All checks were successful
Java CI-CD with Maven / build (push) Successful in 7m14s
2024-07-16 14:16:29 +08:00
cb9716e7b0 修复登录记录数据库错误问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 7m29s
2024-06-17 14:51:43 +08:00
af7223c27f 升级工具库版本
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m40s
2024-06-17 11:37:54 +08:00
aa8dc8aecf Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pom.xml
2024-05-22 15:57:36 +08:00
6354d04755 重构底层代码,优化数据结构
All checks were successful
Java CI-CD with Maven / build (push) Successful in 11m52s
2024-05-22 15:55:50 +08:00
79fb780745 修复了经验设置不生效问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 12m18s
2024-05-17 19:49:21 +08:00
ff05bb0317 新增经验球合并与经验吸收冷却关闭选项
All checks were successful
Java CI-CD with Maven / build (push) Successful in 8m49s
2024-05-17 18:25:25 +08:00
d854a9b1ef 实现了 Homes 相关指令
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m55s
2024-05-13 16:57:09 +08:00
e051167757 新建了部分数据库表 2024-05-13 01:43:34 +08:00
87d0436821 优化项目结构 2024-05-13 00:31:55 +08:00
6facb9d2db Merge remote-tracking branch 'origin/master' 2024-05-13 00:02:25 +08:00
5def80739c 引入数据库以用于存储关键信息 2024-05-13 00:02:15 +08:00
a9406be53c 引入数据库以用于存储关键信息 2024-05-12 23:54:00 +08:00
2d10ead566 优化了传送逻辑
All checks were successful
Java CI-CD with Maven / build (push) Successful in 10m17s
2024-05-12 01:05:41 +08:00
45d3c8aaa8 修复了传送到洞穴中时位置错误的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 13m29s
2024-05-12 00:29:40 +08:00
b828ef1f7a 修复了 back 逻辑可能存在错误的问题
Some checks failed
Java CI-CD with Maven / build (push) Has been cancelled
2024-05-12 00:06:42 +08:00
c4e22963d6 实现了rtp功能
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m58s
2024-05-11 17:40:02 +08:00
aa88ee6014 新增更新检查与数据统计 2024-05-11 00:22:51 +08:00
04e333e444 更新 CI-CD 脚本 2024-05-11 00:17:27 +08:00
8b258f5d1e 丰富配置文件内容
提供更多自定义能力
新增 rtp back 功能
2024-05-11 00:14:23 +08:00
76f06d4e99 修复了玩家坐椅子时可能会卡在地下的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 38m55s
2024-04-26 22:35:33 +08:00
75dbefb02a 修复了玩家离线时如果坐在椅子上下次上线可能会被卡在方块里的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 4m16s
2024-04-22 09:26:53 +08:00
87dd2983f2 修复了tp延迟设置为0可能会报错的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 28m42s
2024-04-21 18:33:39 +08:00
9b042c2de9 补充inspect 的文档 2024-04-19 17:01:11 +08:00
fd13d20676 移除了战利品倍率掉落
All checks were successful
Java CI-CD with Maven / build (push) Successful in 13m5s
2024-04-19 16:57:51 +08:00
b976339687 补充log 2024-04-19 15:26:36 +08:00
76ad5e2d85 当设置战利品倍率时禁止生物拾取物品
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m14s
避免利用此机制刷物品
2024-04-19 15:21:24 +08:00
18d9018796 修改了隐形发光展示框合成表
All checks were successful
Java CI-CD with Maven / build (push) Successful in 5m33s
2024-04-19 09:55:36 +08:00
9a678ea736 修复了下线不自动起身的bug
All checks were successful
Java CI-CD with Maven / build (push) Successful in 8m51s
2024-04-17 22:30:42 +08:00
e3544bcc17 新增椅子功能 2024-04-17 21:57:56 +08:00
cf5c9df1f3 新增椅子功能
All checks were successful
Java CI-CD with Maven / build (push) Successful in 15m21s
2024-04-17 21:53:49 +08:00
42ff27ae2a 新增越权时记录后台日志
All checks were successful
Java CI-CD with Maven / build (push) Successful in 24m43s
2024-04-15 19:48:56 +08:00
69920192df 新增战利品掉落倍率设置
All checks were successful
Java CI-CD with Maven / build (push) Successful in 30m25s
2024-04-14 09:42:07 +08:00
5b51dc7f99 补充readme 2024-04-11 15:50:32 +08:00
cbc49b3ac0 新增传送请求有效期可配置
All checks were successful
Java CI-CD with Maven / build (push) Successful in 4m53s
2024-04-11 15:49:21 +08:00
1e5bf8fde3 新增了传送功能
All checks were successful
Java CI-CD with Maven / build (push) Successful in 5m31s
2024-04-11 15:43:34 +08:00
b6ea705fd6 修复了区块强加前的清理操作因为世界未加载完成导致报错的问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 3m44s
2024-03-26 16:00:21 +08:00
9f617e046e Collection<Chunk> chunks = world.getForceLoadedChunks(); have problem 2024-03-26 01:42:52 +08:00
9885c62232 Collection<Chunk> chunks = world.getForceLoadedChunks(); have problem 2024-03-26 01:06:24 +08:00
f97823af79 clear force load chunks before load
Some checks failed
Java CI-CD with Maven / build (push) Failing after 1h5m27s
2024-03-26 00:40:02 +08:00
7d673906cf 修复了先前由于多线程问题不可用的指令以及特性
Some checks failed
Java CI-CD with Maven / build (push) Failing after 4m27s
2024-03-25 11:34:21 +08:00
e8ce830c05 修改CI-CD go为国内镜像 2024-03-25 11:07:51 +08:00
47ded62aa5 新增光源方块合成
Some checks failed
Java CI-CD with Maven / build (push) Failing after 53m53s
2024-03-23 21:16:25 +08:00
c46973a57b 新增强加载配置
但是由于folia暂时不提供异步线程的同步方法,因此无法将设置应用到区块
2024-03-19 15:56:44 +08:00
ca5e2d943f 新增附魔书堆叠
Some checks failed
Java CI-CD with Maven / build (push) Failing after 1h5m42s
2024-03-19 00:29:53 +08:00
1040899676 新增快速末影箱
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m56s
2024-03-11 10:17:41 +08:00
5abed6fb8a 新增more命令 day noon night sun rain storm 由于无法从玩家线程获取全局世界暂时无法使用
All checks were successful
Java CI-CD with Maven / build (push) Successful in 8m24s
2024-03-11 01:22:55 +08:00
137728a8d3 修复了新增命令错误问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 7m24s
2024-03-01 16:10:38 +08:00
0fc57e7fc3 补充文档 2024-02-28 15:27:18 +08:00
b3da32c0ac 新增提高附魔瓶经验倍率修改
Some checks failed
Java CI-CD with Maven / build (push) Failing after 4m32s
2024-02-28 15:18:01 +08:00
7eb40f4612 修复飞行权限失效问题
All checks were successful
Java CI-CD with Maven / build (push) Successful in 6m36s
2024-02-26 00:19:57 +08:00
a4c279015b 新增时间修改指令
All checks were successful
Java CI-CD with Maven / build (push) Successful in 13m18s
2024-02-22 15:54:00 +08:00
87ee6642dd 修复了控制台motd错误
All checks were successful
Java CI-CD with Maven / build (push) Successful in 13m6s
2024-02-16 12:54:58 +08:00
2c5f203f94 add fly god
All checks were successful
Java CI-CD with Maven / build (push) Successful in 8m11s
2024-01-26 22:08:17 +08:00
ecea2f673d Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pom.xml
2024-01-26 22:08:06 +08:00
72b0375548 add fly god
All checks were successful
Java CI-CD with Maven / build (push) Successful in 9m38s
2024-01-26 22:06:41 +08:00
cf83f9217a try to add custom skull 2024-01-23 00:35:23 +08:00
822b7dd2ee fix may wrong rail type passed in
All checks were successful
Java CI-CD with Maven / build (push) Successful in 11m55s
2024-01-19 10:53:24 +08:00
3d70612b5b fix item frame
All checks were successful
Java CI-CD with Maven / build (push) Successful in 15m2s
2024-01-18 20:43:18 +08:00
bbd6c4e256 add crowbar
All checks were successful
Java CI-CD with Maven / build (push) Successful in 11m8s
2024-01-18 17:44:50 +08:00
9ed936a610 fix show items
All checks were successful
Java CI-CD with Maven / build (push) Successful in 10m16s
2024-01-17 13:05:32 +08:00
f5c89801ab modify CI-CD 2024-01-17 09:40:15 +08:00
71 changed files with 3417 additions and 623 deletions

View File

@ -1,4 +1,4 @@
name: Java CI with Maven
name: Java CI-CD with Maven
on:
push:
@ -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"
@ -30,13 +30,14 @@ jobs:
echo "done!"
- name: "setup go for release script"
run: |
wget --no-check-certificate https://go.dev/dl/go1.21.6.linux-amd64.tar.gz
wget --no-check-certificate https://golang.google.cn/dl/go1.21.6.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.6.linux-amd64.tar.gz
ln -s /usr/local/go/bin/go /usr/bin/go
go version
- name: "Release"
uses: https://ssl.lunadeer.cn:14446/actions/release-action@main
uses: https://ssl.lunadeer.cn:14446/zhangyuheng/release-action@main
with:
note: " - 带 `original-` 前缀的文件无法用于运行,请下载不带此前缀的版本。"
files: |-
staging/*.jar
api_key: '${{secrets.RELEASE_TOKEN}}'

View File

@ -2,11 +2,12 @@
## 说明
主要是实现对 EssentialsX 的平替,同时用来实现一些玩家想要的千奇百怪的功能。由于 EssentialsX 持续不对Folia进行更新支持因此使用此插件代替 EssentialsX其中D代表Deer。
主要是实现对 EssentialsX 的平替,同时用来实现一些玩家想要的千奇百怪的功能。由于 EssentialsX 持续不对Folia进行更新支持因此使用此插件代替
EssentialsX其中D代表Deer。
## 支持版本
- 1.20.1+ (Paper、Folia)
- 1.21.1+ (Folia)
## 安装方法
@ -15,64 +16,4 @@
3. 在 `plugins/EssentialsD/config.yml` 中配置
4. 重启服务器
## 玩家使用方法
### 1. 隐形(发光)展示框
可以通过`八个木棍`+`一个玻璃板`合成隐形展示框![](https://ssl.lunadeer.cn:14437/i/2024/01/16/65a62829e167b.png)
或者`八个烈焰棒`+`一个玻璃板`合成隐形发光展示框![](https://ssl.lunadeer.cn:14437/i/2024/01/16/65a628356722d.png)
当隐形展示框中没有东西时和普通展示框没有区别,**只有在将要展示的物品放置在隐形展示框中时展示框才会自动隐形**。取下展示框中的物品后展示框会自动恢复到现形状态,避免找不到隐形的空展示框。
### 2. 带手的盔甲架
使用 `木棍` 对着普通盔甲架单击 `鼠标左键`,即可给盔甲架装上手臂。
![](https://ssl.lunadeer.cn:14437/i/2024/01/16/65a62d9d94d8f.gif)
> 由于游戏特性,盔甲架被打掉后手臂会自动消失,因此每次防止盔甲架都需要重新安装手臂。
### 3. 自杀指令
使用 `/suicide` 即可自杀,避免因为特殊情况被卡在门中或误入禁区无法动弹。
### 4. 帽子
使用 `/hat` 可将主手持(一般为右手)的任意物品放到头上,如果头上有东西
### 5. 展示物品
使用 `/showItem` 可以向服务器内的所有玩家展示你主手持(一般为右手)的物品。
### 6. 头颅
使用 `/skull` 可将背包中的一个头颅交换为自己的头颅,注意:需要你的背包中有任意一个除玩家之外生物的头颅(苦力怕、凋零、小白等都可以)。
## 管理员指南
暂无
## 指令
### 玩家指令
`/suicide` 自杀
`/hat` 将主手持的物品放在头部
`/showItem` 展示主手持的物品
`/skull` 使用任意头颅交换获得一个自己的头颅
### 管理员指令
暂无
## 配置文件参考
```yaml
Debug: false
```
## TODO

47
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>cn.lunadeer</groupId>
<artifactId>EssentialsD</artifactId>
<version>1.0.0</version>
<version>2.3.1</version>
<packaging>jar</packaging>
<name>EssentialsD</name>
@ -62,14 +62,43 @@
<id>papermc</id>
<url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<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>
<scope>provided</scope>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>cn.lunadeer</groupId>
<artifactId>MinecraftPluginUtils</artifactId>
<version>1.3.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<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

@ -1,10 +1,31 @@
package cn.lunadeer.essentialsd;
import cn.lunadeer.essentialsd.commands.*;
import cn.lunadeer.essentialsd.recipes.InvisibleGlowItemFrame;
import cn.lunadeer.essentialsd.recipes.InvisibleItemFrame;
import cn.lunadeer.essentialsd.utils.ConfigManager;
import cn.lunadeer.essentialsd.utils.XLogger;
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.*;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@ -16,27 +37,108 @@ public final class EssentialsD extends JavaPlugin {
public void onEnable() {
// Plugin startup logic
instance = this;
new XLogger(instance);
config = new ConfigManager(instance);
new Notification(instance);
database = new DatabaseManager(this,
DatabaseManager.TYPE.valueOf(config.getDbType().toUpperCase()),
config.getDbHost(),
config.getDbPort(),
config.getDbName(),
config.getDbUser(),
config.getDbPass());
DatabaseTables.migrate();
new Scheduler(this);
tpManager = new TeleportManager();
Bukkit.getPluginManager().registerEvents(new Events(), this);
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);
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);
Bukkit.getPluginManager().registerEvents(new Experience(), this);
// op 指令
Objects.requireNonNull(Bukkit.getPluginCommand("fly")).setExecutor(new Fly());
Objects.requireNonNull(Bukkit.getPluginCommand("god")).setExecutor(new God());
Objects.requireNonNull(Bukkit.getPluginCommand("day")).setExecutor(new Day());
Objects.requireNonNull(Bukkit.getPluginCommand("noon")).setExecutor(new Noon());
Objects.requireNonNull(Bukkit.getPluginCommand("night")).setExecutor(new Night());
Objects.requireNonNull(Bukkit.getPluginCommand("save")).setExecutor(new Save());
Objects.requireNonNull(Bukkit.getPluginCommand("more")).setExecutor(new More());
Objects.requireNonNull(Bukkit.getPluginCommand("sun")).setExecutor(new Sun());
Objects.requireNonNull(Bukkit.getPluginCommand("rain")).setExecutor(new Rain());
Objects.requireNonNull(Bukkit.getPluginCommand("storm")).setExecutor(new Storm());
Objects.requireNonNull(Bukkit.getPluginCommand("inspect")).setExecutor(new Inspect());
// 普通指令
Objects.requireNonNull(Bukkit.getPluginCommand("enderchest")).setExecutor(new EnderChest());
Objects.requireNonNull(Bukkit.getPluginCommand("suicide")).setExecutor(new Suicide());
Objects.requireNonNull(Bukkit.getPluginCommand("hat")).setExecutor(new Hat());
Objects.requireNonNull(Bukkit.getPluginCommand("showItem")).setExecutor(new ShowItem());
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());
this.getServer().addRecipe(InvisibleItemFrame.getRecipe());
this.getServer().addRecipe(InvisibleGlowItemFrame.getRecipe());
String logo = "EssentialsD 已加载 版本: " + getPluginMeta().getVersion() + "\n";
if (config.getRecipesCrowbar()) {
this.getServer().addRecipe(Crowbar.getRecipe());
}
if (config.getRecipesInvisibleItemFrame()) {
this.getServer().addRecipe(InvisibleItemFrame.getRecipe());
this.getServer().addRecipe(InvisibleGlowItemFrame.getRecipe());
}
if (config.getRecipesStackedEnchantBook()) {
this.getServer().addRecipe(StackedEnchantBook.getRecipe());
}
if (config.getRecipesLightBlock()) {
this.getServer().addRecipe(LightBlock.getRecipe());
}
bStatsMetrics metrics = new bStatsMetrics(this, 21861);
if (config.getCheckUpdate()) {
releaseCheck = new GiteaReleaseCheck(this,
"https://ssl.lunadeer.cn:14446",
"zhangyuheng",
"EssentialsD");
}
config.ApplyForceLoadChunks(); // 应用强加载区块
XLogger.info("EssentialsD 已加载");
XLogger.info("版本: " + getPluginMeta().getVersion());
// https://patorjk.com/software/taag/#p=display&f=Big&t=EssentialsD
logo += " ______ _ _ _ _____\n";
logo += " | ____| | | (_) | | | __ \\\n";
logo += " | |__ ___ ___ ___ _ __ | |_ _ __ _| |___| | | |\n";
logo += " | __| / __/ __|/ _ \\ '_ \\| __| |/ _` | / __| | | |\n";
logo += " | |____\\__ \\__ \\ __/ | | | |_| | (_| | \\__ \\ |__| |\n";
logo += " |______|___/___/\\___|_| |_|\\__|_|\\__,_|_|___/_____/\n";
logo += "\n";
XLogger.info(logo);
XLogger.info(" ______ _ _ _ _____");
XLogger.info(" | ____| | | (_) | | | __ \\");
XLogger.info(" | |__ ___ ___ ___ _ __ | |_ _ __ _| |___| | | |");
XLogger.info(" | __| / __/ __|/ _ \\ '_ \\| __| |/ _` | / __| | | |");
XLogger.info(" | |____\\__ \\__ \\ __/ | | | |_| | (_| | \\__ \\ |__| |");
XLogger.info(" |______|___/___/\\___|_| |_|\\__|_|\\__,_|_|___/_____/");
XLogger.info("");
}
@Override
@ -46,4 +148,8 @@ public final class EssentialsD extends JavaPlugin {
public static EssentialsD instance;
public static ConfigManager config;
public static TeleportManager tpManager;
public static DatabaseManager database;
private GiteaReleaseCheck releaseCheck;
}

View File

@ -0,0 +1,52 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.stream.Collectors;
public class Apis {
/**
* 获取命令操作的玩家 如果没有指定玩家则返回命令发送者
*
* @param sender 命令发送者
* @param args 命令参数
* @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]);
return null;
}
return target;
}
public static List<String> playerNames() {
return EssentialsD.instance.getServer().getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList());
}
public static void setOverWorldTime(CommandSender sender, long time) {
Scheduler.runTask(() -> {
EssentialsD.instance.getServer().getWorlds().forEach(world -> {
if (world.getEnvironment() == World.Environment.NORMAL) {
world.setTime(time);
Notification.info(sender, "设置 %s 时间为 %d", world.getName(), time);
}
});
});
}
}

View File

@ -0,0 +1,33 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.jetbrains.annotations.NotNull;
public class EnderChest implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) {
Notification.error(sender, "只有玩家才能使用这个命令");
return false;
}
// 打开玩家的末影箱
Player player = (Player) sender;
Inventory chest = player.getEnderChest();
InventoryView view = player.openInventory(chest);
if (view == null) {
Notification.error(sender, "无法打开末影箱");
return false;
}
InventoryOpenEvent event = new InventoryOpenEvent(view);
EssentialsD.instance.getServer().getPluginManager().callEvent(event);
return true;
}
}

View File

@ -0,0 +1,37 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.getPlayerFromArg;
public class Fly implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player) && args.length < 1) {
Notification.error(sender, "以控制台身份执行时,必须指定玩家:/fly <player>");
return false;
}
Scheduler.runTask(() -> {
Player target = getPlayerFromArg(sender, args, 0);
if (target == null) {
return;
}
if (target.getAllowFlight()) {
target.setAllowFlight(false);
Notification.info(sender, "已关闭玩家 %s 的飞行模式", target.getName());
Notification.info(target, "已关闭飞行模式");
} else {
target.setAllowFlight(true);
Notification.info(sender, "已开启玩家 %s 的飞行模式", target.getName());
Notification.info(target, "已开启飞行模式");
}
});
return true;
}
}

View File

@ -0,0 +1,37 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.getPlayerFromArg;
public class God implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player) && args.length < 1) {
Notification.error(sender, "以控制台身份执行时,必须指定玩家:/god <player>");
return false;
}
Scheduler.runTask(() -> {
Player target = getPlayerFromArg(sender, args, 0);
if (target == null) {
return;
}
if (target.isInvulnerable()) {
target.setInvulnerable(false);
Notification.info(sender, "已关闭玩家 %s 的无敌模式", target.getName());
Notification.info(target, "已关闭无敌模式");
} else {
target.setInvulnerable(true);
Notification.info(sender, "已开启玩家 %s 的无敌模式", target.getName());
Notification.info(target, "已开启无敌模式");
}
});
return true;
}
}

View File

@ -1,6 +1,6 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.utils.Notification;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
public class Hat implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)){
if (!(sender instanceof Player)) {
Notification.warn(sender, "只有玩家可以使用此命令");
return true;
}

View File

@ -0,0 +1,44 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.getPlayerFromArg;
public class Inspect implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command
* (if defined) will be sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) {
Notification.error(sender, "只有玩家才能使用这个命令");
return false;
}
Player op = (Player) sender;
Scheduler.runTask(() -> {
Player target = getPlayerFromArg(op, args, 0);
if (target == null) {
return;
}
Inventory inv = target.getInventory();
op.openInventory(inv);
});
return true;
}
}

View File

@ -0,0 +1,47 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class More implements CommandExecutor {
@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;
}
Player player = (Player) sender;
int amount = 63;
if (args.length > 0) {
try {
amount = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
Notification.error(sender, "参数错误");
return false;
}
}
ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType().isAir()) {
Notification.error(sender, "你手上没有物品");
return false;
}
int failed_add_count = 0;
for (int i = 0; i < amount; i++) {
Map<Integer, ItemStack> res = player.getInventory().addItem(new ItemStack(item.getType()));
if (!res.isEmpty()) {
failed_add_count++;
}
}
if (failed_add_count != 0) {
Notification.warn(sender, "背包已满,有 %d 个物品未能添加", failed_add_count);
}
return true;
}
}

View File

@ -0,0 +1,35 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class Save implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command
* (if defined) will be sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
// 保存服务器存档
Notification.info(sender, "正在保存服务器存档...");
EssentialsD.instance.getServer().savePlayers();
EssentialsD.instance.getServer().getWorlds().forEach(World::save);
Notification.info(sender, "服务器存档已保存");
return true;
}
}

View File

@ -1,10 +1,10 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.utils.Notification;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.stui.components.Button;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -13,7 +13,6 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
@ -24,7 +23,7 @@ import java.util.UUID;
public class ShowItem implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)){
if (!(sender instanceof Player)) {
Notification.warn(sender, "只有玩家可以使用此命令");
return true;
}
@ -34,28 +33,26 @@ public class ShowItem implements CommandExecutor {
return true;
}
PlayerInventory backpack = player.getInventory();
ItemStack item = backpack.getItemInMainHand();
ItemStack item = backpack.getItemInMainHand().clone();
if (item.getType().isAir()) {
Notification.warn(player, "你的主手为空");
return true;
}
Component name = item.displayName();
String name_str = item.getType().name();
if (item.getItemMeta().hasDisplayName()) {
name_str = ((TextComponent) item.getItemMeta().displayName()).content();
}
UUID uuid = UUID.randomUUID();
TextComponent name_builder = Component.text()
.append(Component.text("[", show_color))
.append(name)
.append(Component.text("]", show_color)).build();
Component show = name_builder.hoverEvent(Component.text("点击查看物品信息"))
.clickEvent(ClickEvent.runCommand("/showItem " + uuid));
Button show = Button.create(name_str).setExecuteCommand("/showitem " + uuid).setHoverText("点击查看物品信息");
TextComponent title = Component.text(uuid.toString());
TextComponent title = Component.text("物品展示").hoverEvent(Component.text(uuid.toString())).color(show_color);
Inventory inv = EssentialsD.instance.getServer().createInventory(null, 54, title);
inv.setItem(22, item);
cache.put(uuid.toString(), inv);
player.getServer().sendMessage(Component.text("玩家 " + player.getName() + " 展示了物品 ").append(show));
player.getServer().sendMessage(Component.text("玩家 " + player.getName() + " 展示了物品 ").append(show.build()));
return true;
}

View File

@ -1,6 +1,6 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.utils.Notification;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -36,7 +36,7 @@ public class Skull implements CommandExecutor {
skulls.putAll(zombie_skulls);
skulls.putAll(dragon_skulls);
skulls.putAll(wither_skulls);
if (skulls.size() == 0) {
if (skulls.isEmpty()) {
Notification.warn(player, "你的背包中没有可以用来交换的头颅");
return true;
}

View File

@ -1,6 +1,6 @@
package cn.lunadeer.essentialsd.commands;
import cn.lunadeer.essentialsd.utils.Notification;
import cn.lunadeer.minecraftpluginutils.Notification;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -11,7 +11,7 @@ public class Suicide implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)){
if (!(sender instanceof Player)) {
Notification.warn(sender, "只有玩家可以使用此命令");
return true;
}

View File

@ -0,0 +1,57 @@
package cn.lunadeer.essentialsd.commands.home;
import cn.lunadeer.essentialsd.dtos.HomeInfo;
import cn.lunadeer.essentialsd.tuis.HomeList;
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.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;
}
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, "成功删除家 %s", homeName);
} else {
Notification.error(player, "删除家 %s 失败, 请联系管理员", 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;
}
}

View File

@ -0,0 +1,61 @@
package cn.lunadeer.essentialsd.commands.home;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.dtos.HomeInfo;
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.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;
}
Player player = (Player) sender;
List<HomeInfo> homes = HomeInfo.getHomesOf(player.getUniqueId());
String homeName;
if (args.length == 0) {
if (homes.size() == 0) {
Notification.error(player, "你还没有设置家");
return true;
}
homeName = homes.get(0).homeName;
} else {
homeName = args[0];
}
HomeInfo home = HomeInfo.getHome(player.getUniqueId(), homeName);
if (home == null) {
Notification.error(player, "不存在名为 %s 的家", homeName);
return true;
}
try {
EssentialsD.tpManager.doTeleportDelayed(player, home.location, EssentialsD.config.getTpDelay(), () -> {
Notification.info(player, "正在传送到家 %s", homeName);
}, () -> {
Notification.info(player, "成功传送到家 %s", homeName);
});
} catch (RuntimeException e) {
Notification.error(player, "传送到家 %s 失败: %s", 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;
}
}

View File

@ -0,0 +1,23 @@
package cn.lunadeer.essentialsd.commands.home;
import cn.lunadeer.essentialsd.tuis.HomeList;
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 Homes implements TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
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;
}
}

View File

@ -0,0 +1,58 @@
package cn.lunadeer.essentialsd.commands.home;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.dtos.HomeInfo;
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.Collections;
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;
}
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, "已经存在名为 %s 的家", info.homeName);
return true;
}
boolean res = HomeInfo.newHome(info);
if (res) {
Notification.info(player, "成功设置家 %s", info.homeName);
} else {
Notification.error(player, "设置家 %s 失败, 请联系管理员", info.homeName);
}
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 1) {
return Collections.singletonList("[home名称]");
}
return null;
}
}

View File

@ -0,0 +1,30 @@
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.setOverWorldTime;
public class Day implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command
* (if defined) will be sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
// set time to 1000
setOverWorldTime(sender, 1000);
return true;
}
}

View File

@ -0,0 +1,28 @@
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.setOverWorldTime;
public class Night implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command
* (if defined) will be sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
setOverWorldTime(sender, 13000);
return true;
}
}

View File

@ -0,0 +1,29 @@
package cn.lunadeer.essentialsd.commands.time;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import static cn.lunadeer.essentialsd.commands.Apis.setOverWorldTime;
public class Noon implements CommandExecutor {
/**
* Executes the given command, returning its success.
* <br>
* If false is returned, then the "usage" plugin.yml entry for this command
* (if defined) will be sent to the player.
*
* @param sender Source of the command
* @param command Command which was executed
* @param label Alias of the command which was used
* @param args Passed command arguments
* @return true if a valid command, otherwise false
*/
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
setOverWorldTime(sender, 6000);
return true;
}
}

View File

@ -0,0 +1,30 @@
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
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 Back 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;
}
Player player = (Player) sender;
EssentialsD.tpManager.back(player);
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return null;
}
}

View File

@ -0,0 +1,30 @@
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
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 Rtp 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;
}
Player player = (Player) sender;
EssentialsD.tpManager.rtp(player);
return true;
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return null;
}
}

View File

@ -0,0 +1,61 @@
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
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.Collection;
import java.util.List;
import java.util.UUID;
public class Tpa 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;
}
Player player = (Player) sender;
if (args.length == 1) {
Player target = EssentialsD.instance.getServer().getPlayer(args[0]);
if (target == null) {
Notification.warn(player, "玩家 %s 不在线", args[0]);
return true;
}
EssentialsD.tpManager.tpaRequest(player, target);
return true;
} else if (args.length == 2) {
if (args[0].equals("accept")) {
EssentialsD.tpManager.accept(player, UUID.fromString(args[1]));
return true;
} else if (args[0].equals("deny")) {
EssentialsD.tpManager.deny(player, UUID.fromString(args[1]));
return true;
} else {
Notification.error(player, "参数错误");
return false;
}
} else {
Notification.error(player, "参数错误");
return false;
}
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 1) {
Collection<? extends Player> players = EssentialsD.instance.getServer().getOnlinePlayers();
List<String> result = new java.util.ArrayList<>();
for (Player player : players) {
result.add(player.getName());
}
return result;
}
return null;
}
}

View File

@ -0,0 +1,49 @@
package cn.lunadeer.essentialsd.commands.tp;
import cn.lunadeer.essentialsd.EssentialsD;
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.Collection;
import java.util.List;
public class TpaHere 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;
}
Player player = (Player) sender;
if (args.length == 1) {
Player target = EssentialsD.instance.getServer().getPlayer(args[0]);
if (target == null) {
Notification.warn(player, "玩家 %s 不在线", args[0]);
return true;
}
EssentialsD.tpManager.tpahereRequest(player, target);
return true;
} else {
Notification.error(player, "参数错误");
return false;
}
}
@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (args.length == 1) {
Collection<? extends Player> players = EssentialsD.instance.getServer().getOnlinePlayers();
List<String> result = new java.util.ArrayList<>();
for (Player player : players) {
result.add(player.getName());
}
return result;
}
return null;
}
}

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

@ -0,0 +1,27 @@
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class Rain implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Scheduler.runTask(() -> {
EssentialsD.instance.getServer().getWorlds().forEach(world -> {
if (world.getEnvironment() == World.Environment.NORMAL) {
world.setStorm(true);
world.setThundering(false);
Notification.info(sender, "设置 %s 天气为雨天", world.getName());
}
});
});
return true;
}
}

View File

@ -0,0 +1,27 @@
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class Storm implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Scheduler.runTask(() -> {
EssentialsD.instance.getServer().getWorlds().forEach(world -> {
if (world.getEnvironment() == World.Environment.NORMAL) {
world.setStorm(true);
world.setThundering(true);
Notification.info(sender, "设置 %s 天气为雷雨", world.getName());
}
});
});
return true;
}
}

View File

@ -0,0 +1,27 @@
package cn.lunadeer.essentialsd.commands.weather;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class Sun implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
Scheduler.runTask(() -> {
EssentialsD.instance.getServer().getWorlds().forEach(world -> {
if (world.getEnvironment() == World.Environment.NORMAL) {
world.setStorm(false);
world.setThundering(false);
Notification.info(sender, "设置 %s 天气为晴朗", world.getName());
}
});
});
return true;
}
}

View File

@ -0,0 +1,83 @@
package cn.lunadeer.essentialsd.dtos;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.LocationUtils;
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 (?, ?, ?);";
try (ResultSet rs = EssentialsD.database.query(sql, info.uuid, info.homeName, LocationUtils.Serialize(info.location))) {
return true;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("创建Home失败", e, sql);
return false;
}
}
public static boolean deleteHome(UUID uuid, String homeName) {
String sql = "DELETE FROM home_info WHERE uuid = ? AND home_name = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString(), homeName)) {
return true;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("删除Home失败", e, sql);
return false;
}
}
public static List<HomeInfo> getHomesOf(UUID uuid) {
List<HomeInfo> homes = new ArrayList<>();
String sql = "SELECT * FROM home_info WHERE uuid = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString())) {
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) {
EssentialsD.database.handleDatabaseError("获取Home列表失败", e, sql);
}
return homes;
}
public static HomeInfo getHome(UUID uuid, String homeName) {
String sql = "SELECT * FROM home_info WHERE uuid = ? AND home_name = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString(), homeName)) {
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) {
EssentialsD.database.handleDatabaseError("获取Home失败", e, sql);
}
return null;
}
}

View File

@ -0,0 +1,47 @@
package cn.lunadeer.essentialsd.dtos;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.LocationUtils;
import org.bukkit.entity.Player;
import java.net.InetSocketAddress;
import java.sql.ResultSet;
import java.sql.Timestamp;
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();
}
Timestamp login_time = new Timestamp(player.getLastLogin());
Timestamp logout_time = new Timestamp(System.currentTimeMillis());
String logout_location = LocationUtils.Serialize(player.getLocation());
String sql = "INSERT INTO login_record (uuid, ip, login_time, logout_location, logout_time) " +
"VALUES (?, ?, ?, ?, ?);";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString(), ip, login_time, logout_location, logout_time)) {
if (rs == null) return;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("创建登录记录失败", e, sql);
}
}
}

View File

@ -0,0 +1,61 @@
package cn.lunadeer.essentialsd.dtos;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.entity.Player;
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 (?, ?, CURRENT_TIMESTAMP);";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString(), name)) {
return true;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("创建名字记录失败", e, sql);
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 = ? ORDER BY time DESC LIMIT " + limit + ";";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString())) {
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) {
EssentialsD.database.handleDatabaseError("获取名字记录失败", e, sql);
}
return records;
}
}

View File

@ -0,0 +1,42 @@
package cn.lunadeer.essentialsd.dtos;
import cn.lunadeer.essentialsd.EssentialsD;
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 = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString())) {
if (rs == null) return null;
if (rs.next()) {
return rs.getString("last_known_name");
}
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("获取玩家名字失败", e, sql);
}
return null;
}
public static boolean setName(UUID uuid, String name) {
String sql = "INSERT INTO player_name (uuid, last_known_name) " +
"VALUES (?, ?) ON CONFLICT (uuid) DO NOTHING;";
try (ResultSet rs = EssentialsD.database.query(sql, uuid.toString(), name)) {
return true;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("设置玩家名字失败", e, sql);
return false;
}
}
public static boolean updateName(UUID uuid, String name) {
String sql = "UPDATE player_name SET last_known_name = ? WHERE uuid = ?;";
try (ResultSet rs = EssentialsD.database.query(sql, name, uuid.toString())) {
return true;
} catch (Exception e) {
EssentialsD.database.handleDatabaseError("更新玩家名字失败", e, sql);
return false;
}
}
}

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

@ -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);
}
}

View File

@ -0,0 +1,232 @@
package cn.lunadeer.essentialsd.events;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.XLogger;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.type.Stairs;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
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;
public class ChairEvent implements Listener {
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (!EssentialsD.config.getChairEnable()) {
return;
}
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
Block block = event.getClickedBlock();
if (block == null) {
return;
}
Player player = event.getPlayer();
if (!(block.getState().getBlockData() instanceof Stairs)) {
return;
}
Stairs stairs = (Stairs) block.getState().getBlockData();
int chair_width = 1;
// Check if block beneath chair is solid.
if (block.getRelative(BlockFace.DOWN).isEmpty())
return;
// Check if player is sitting.
if (!player.isSneaking() && player.getVehicle() != null) {
player.getVehicle().remove();
return;
}
// Check for distance between player and chair.
if (player.getLocation().distance(block.getLocation().add(0.5, 0, 0.5)) > 2)
return;
// Check for signs.
if (EssentialsD.config.getChairSignCheck()) {
boolean sign1 = false;
boolean sign2 = false;
if (stairs.getFacing() == BlockFace.NORTH || stairs.getFacing() == BlockFace.SOUTH) {
sign1 = checkSign(block, BlockFace.EAST);
sign2 = checkSign(block, BlockFace.WEST);
} else if (stairs.getFacing() == BlockFace.EAST || stairs.getFacing() == BlockFace.WEST) {
sign1 = checkSign(block, BlockFace.NORTH);
sign2 = checkSign(block, BlockFace.SOUTH);
}
if (!(sign1 && sign2))
return;
}
// Check for maximal chair width.
if (EssentialsD.config.getChairMaxWidth() > 0) {
if (stairs.getFacing() == BlockFace.NORTH || stairs.getFacing() == BlockFace.SOUTH) {
chair_width += getChairWidth(block, BlockFace.EAST);
chair_width += getChairWidth(block, BlockFace.WEST);
} else if (stairs.getFacing() == BlockFace.EAST || stairs.getFacing() == BlockFace.WEST) {
chair_width += getChairWidth(block, BlockFace.NORTH);
chair_width += getChairWidth(block, BlockFace.SOUTH);
}
if (chair_width > EssentialsD.config.getChairMaxWidth())
return;
}
// Sit-down process.
if (player.getVehicle() != null)
player.getVehicle().remove();
ArmorStand drop = dropSeat(block);
// Changing the drop material is only necessary for the item merge feature of CB++
// The client won't update the material, though.
if (!drop.addPassenger(player)) {
XLogger.debug("Failed to make player " + player.getName() + " sit on a chair.");
} else {
XLogger.debug("Player " + player.getName() + " is sitting on a chair.");
}
// Cancel BlockPlaceEvent Result, if player is rightclicking with a block in his hand.
event.setUseInteractedBlock(Event.Result.DENY);
}
@EventHandler
public void onPassengerLeave(EntityDismountEvent event) {
if (!EssentialsD.config.getChairEnable()) {
return;
}
Entity vehicle = event.getDismounted();
Entity passenger = event.getEntity();
if (!(vehicle instanceof ArmorStand)) {
return;
}
if (!(passenger instanceof Player)) {
return;
}
vehicle.remove();
passenger.teleportAsync(passenger.getLocation().add(0, EssentialsD.config.getChairSitHeight() * -1, 0));
}
@EventHandler
public void onPlayerTeleport(PlayerTeleportEvent event) {
if (!EssentialsD.config.getChairEnable()) {
return;
}
Entity vehicle = event.getPlayer().getVehicle();
if (vehicle == null) {
return;
}
if (!(vehicle instanceof ArmorStand)) {
return;
}
event.setTo(event.getTo().add(0, EssentialsD.config.getChairSitHeight() * -1, 0));
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if (!EssentialsD.config.getChairEnable()) {
return;
}
if (!(event.getBlock().getState().getBlockData() instanceof Stairs)) {
return;
}
clearSeat(event.getBlock());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
if (!EssentialsD.config.getChairEnable()) {
return;
}
Entity vehicle = event.getPlayer().getVehicle();
// Let players stand up when leaving the server.
if (vehicle instanceof ArmorStand) {
vehicle.remove();
event.getPlayer().teleportAsync(event.getPlayer().getLocation().add(0, EssentialsD.config.getChairSitHeight() * -1, 0));
}
}
private ArmorStand dropSeat(Block chair) {
clearSeat(chair);
Location location = chair.getLocation().add(0.5, (EssentialsD.config.getChairSitHeight() + 0.5), 0.5);
switch (((Stairs) chair.getState().getBlockData()).getFacing()) {
case SOUTH:
location.setDirection(new Vector(0, 0, -1));
break;
case WEST:
location.setDirection(new Vector(1, 0, 0));
break;
case NORTH:
location.setDirection(new Vector(0, 0, 1));
break;
case EAST:
location.setDirection(new Vector(-1, 0, 0));
break;
}
ArmorStand armorStand = (ArmorStand) chair.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
if (!EssentialsD.config.isDebug()) {
armorStand.setVisible(false);
}
armorStand.setGravity(false);
armorStand.setInvulnerable(true);
armorStand.setSmall(true);
XLogger.debug("Chair dropped at " + location.toString());
return armorStand;
}
private void clearSeat(Block chair) {
Location location = chair.getLocation().add(0.5, (EssentialsD.config.getChairSitHeight() + 0.5), 0.5);
for (Entity e : location.getWorld().getNearbyEntities(location, 0.4, 0.4, 0.4)) {
if (e instanceof ArmorStand) {
e.remove();
}
}
}
private int getChairWidth(Block block, BlockFace face) {
int width = 0;
// Go through the blocks next to the clicked block and check if there are any further stairs.
for (int i = 1; i <= EssentialsD.config.getChairMaxWidth(); i++) {
Block relative = block.getRelative(face, i);
if (!(relative.getState().getBlockData() instanceof Stairs)) {
break;
}
if (((Stairs) relative.getState().getBlockData()).getFacing() == ((Stairs) block.getState().getBlockData()).getFacing())
width++;
else
break;
}
return width;
}
private boolean checkSign(Block block, BlockFace face) {
// Go through the blocks next to the clicked block and check if are signs on the end.
for (int i = 1; i <= EssentialsD.config.getChairMaxWidth(); i++) {
Block relative = block.getRelative(face, i);
if (relative.getState().getBlockData() instanceof Stairs) {
continue;
}
return relative.getState().getBlockData() instanceof WallSign;
}
return false;
}
}

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

@ -0,0 +1,57 @@
package cn.lunadeer.essentialsd.events;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.recipes.Crowbar;
import cn.lunadeer.minecraftpluginutils.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);
}
}

View File

@ -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()));
}
}

View File

@ -0,0 +1,48 @@
package cn.lunadeer.essentialsd.events;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ExperienceOrb;
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.EntitySpawnEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import java.util.Collection;
public class Experience implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public void onExpOrbSpawn(EntitySpawnEvent event) {
if (!EssentialsD.config.getCombineExpOrbs()) {
return;
}
Entity entity = event.getEntity();
if (entity.getType() != EntityType.EXPERIENCE_ORB) {
return;
}
ExperienceOrb orb = (ExperienceOrb) entity;
Location loc = entity.getLocation();
double radius = EssentialsD.config.getCombineExpOrbsRadius();
Collection<Entity> entities = loc.getNearbyEntities(radius, radius, radius);
for (Entity e : entities) {
if (e.getType() != EntityType.EXPERIENCE_ORB) {
continue;
}
orb.setExperience(orb.getExperience() + ((ExperienceOrb) e).getExperience());
e.remove();
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLogin(PlayerLoginEvent event) {
Player player = event.getPlayer();
if (EssentialsD.config.getNoExpCoolDown()) {
player.setExpCooldown(0);
}
}
}

View File

@ -1,46 +1,24 @@
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.InvisibleGlowItemFrame;
import cn.lunadeer.essentialsd.recipes.InvisibleItemFrame;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.*;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.Objects;
public class Events implements Listener {
@EventHandler
public void onShowItemClick(InventoryClickEvent event) {
Inventory inv = event.getClickedInventory();
if (inv == null) {
return;
}
InventoryView view = event.getView();
TextComponent title = Component.text().append(view.title()).build();
if (!ShowItem.cache.containsKey(title.content())) {
return;
}
event.setCancelled(true);
}
public class InvisibleItemFrameEvent implements Listener {
// place an Invisible Item Frame
@EventHandler
public void placeItemFrame(HangingPlaceEvent event) {
Entity entity = event.getEntity();
@ -60,6 +38,7 @@ public class Events implements Listener {
}
}
// break an Invisible Item Frame
@EventHandler
public void removeItemFrame(HangingBreakByEntityEvent event) {
Entity entity = event.getEntity();
@ -72,19 +51,20 @@ public class Events implements Listener {
ItemFrame itemFrame = (ItemFrame) entity;
if (entity.getType() == EntityType.ITEM_FRAME) {
ItemStack item = InvisibleItemFrame.getItemStack();
itemFrame.getWorld().dropItem(itemFrame.getLocation(), item);
itemFrame.getWorld().dropItemNaturally(itemFrame.getLocation(), item);
} else if (entity.getType() == EntityType.GLOW_ITEM_FRAME) {
ItemStack item = InvisibleItemFrame.getItemStack();
itemFrame.getWorld().dropItem(itemFrame.getLocation(), item);
ItemStack item = InvisibleGlowItemFrame.getItemStack();
itemFrame.getWorld().dropItemNaturally(itemFrame.getLocation(), item);
}
itemFrame.remove();
event.setCancelled(true);
}
// put something on an Invisible Item Frame
@EventHandler
public void putSomeOnItemFrame(PlayerInteractEntityEvent event) {
Entity entity = event.getRightClicked();
if(!(entity instanceof ItemFrame)) {
if (!(entity instanceof ItemFrame)) {
return;
}
if (event.getPlayer().getInventory().getItemInMainHand().getType() == Material.AIR) {
@ -99,6 +79,7 @@ public class Events implements Listener {
}
}
// remove something on an Invisible Item Frame
@EventHandler
public void removeSomeOnItemFrame(EntityDamageByEntityEvent event) {
Entity entity = event.getEntity();
@ -116,28 +97,4 @@ public class Events implements Listener {
itemFrame.setVisible(true);
}
}
@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);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,39 @@
package cn.lunadeer.essentialsd.events;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.commands.ShowItem;
import cn.lunadeer.minecraftpluginutils.XLogger;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.HoverEvent;
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();
Component title = view.title();
HoverEvent<?> hoverEvent = title.hoverEvent();
if (hoverEvent == null) {
return;
}
if (!(hoverEvent.value() instanceof TextComponent)) {
return;
}
TextComponent hoverEventValue = (TextComponent) hoverEvent.value();
XLogger.debug("ShowItemEvent: " + hoverEventValue.content());
if (!ShowItem.cache.containsKey(hoverEventValue.content())) {
return;
}
event.setCancelled(true);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,390 @@
package cn.lunadeer.essentialsd.managers;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import cn.lunadeer.minecraftpluginutils.XLogger;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import java.util.Collection;
import java.util.List;
public class ConfigManager {
public ConfigManager(EssentialsD plugin) {
_plugin = plugin;
_plugin.saveDefaultConfig();
reload();
_plugin.saveConfig();
}
public void reload() {
_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);
_combine_exp_orbs_radius = (float) _file.getDouble("CombineExpOrbs.Radius", 1.5);
_no_exp_cool_down = _file.getBoolean("NoExpCoolDown", false);
_force_load_chunks = _file.getStringList("ForceLoadChunks");
_chunk_operate_delay = _file.getInt("ChunkOperateDelay", 10);
_tp_delay = _file.getInt("Teleport.Delay", 0);
_tp_cool_down = _file.getInt("Teleport.CoolDown", 0);
_tp_tpa_expire = _file.getInt("Teleport.TpaExpire", 30);
_tp_rtp_radius = _file.getInt("Teleport.RtpRadius", 1000);
_tp_world_blacklist = _file.getStringList("Teleport.WorldBlackList");
_chair_enable = _file.getBoolean("Chair.Enable", true);
_chair_max_width = _file.getInt("Chair.MaxWidth", 4);
_chair_sign_check = _file.getBoolean("Chair.SignCheck", true);
_chair_sit_height = (float) _file.getDouble("Chair.SitHeight", -0.95);
_recipes_crowbar = _file.getBoolean("Recipes.CrowBar", true);
_recipes_invisible_item_frame = _file.getBoolean("Recipes.InvisibleItemFrame", true);
_recipes_light_block = _file.getBoolean("Recipes.LightBlock", true);
_recipes_stacked_enchant_book = _file.getBoolean("Recipes.StackedEnchantBook", true);
_home_limit_amount = _file.getInt("HomeLimit.Amount", 5);
_home_world_blacklist = _file.getStringList("HomeLimit.WorldBlacklist");
_db_type = _file.getString("Database.Type", "sqlite");
if (!_db_type.equals("pgsql") && !_db_type.equals("sqlite")) {
XLogger.err("当前数据库只支持 pgsql 或 sqlite已重置为 sqlite");
setDbType("sqlite");
}
_db_host = _file.getString("Database.Host", "localhost");
_db_port = _file.getString("Database.Port", "5432");
_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() {
return _debug;
}
public void setDebug(Boolean debug) {
_debug = debug;
_file.set("Debug", debug);
_plugin.saveConfig();
}
public Boolean getCheckUpdate() {
return _check_update;
}
public float getExpBottleRatio() {
return _exp_bottle_ratio;
}
public void setExpBottleRatio(float ratio) {
_exp_bottle_ratio = ratio;
_file.set("ExpBottleRatio", ratio);
_plugin.saveConfig();
}
public Boolean getCombineExpOrbs() {
return _combine_exp_orbs_enable;
}
public void setCombineExpOrbs(Boolean combine) {
_combine_exp_orbs_enable = combine;
_file.set("CombineExpOrbs.Enable", combine);
_plugin.saveConfig();
}
public Float getCombineExpOrbsRadius() {
return _combine_exp_orbs_radius;
}
public void setCombineExpOrbsRadius(Float radius) {
_combine_exp_orbs_radius = radius;
_file.set("CombineExpOrbs.Radius", radius);
_plugin.saveConfig();
}
public Boolean getNoExpCoolDown() {
return _no_exp_cool_down;
}
public void setNoExpCoolDown(Boolean no_cool_down) {
_no_exp_cool_down = no_cool_down;
_file.set("NoExpCoolDown", no_cool_down);
_plugin.saveConfig();
for (Player player : EssentialsD.instance.getServer().getOnlinePlayers()) {
if (EssentialsD.config.getNoExpCoolDown()) {
player.setExpCooldown(0);
} else {
player.setExpCooldown(1);
}
}
}
public Integer getChunkOperateDelay() {
return _chunk_operate_delay;
}
public void setChunkOperateDelay(Integer delay) {
_chunk_operate_delay = delay;
_file.set("ChunkOperateDelay", delay);
_plugin.saveConfig();
}
public Integer getTpDelay() {
return _tp_delay;
}
public Integer getTpCoolDown() {
return _tp_cool_down;
}
public Integer getTpTpaExpire() {
return _tp_tpa_expire;
}
public Integer getTpRtpRadius() {
return _tp_rtp_radius;
}
public List<String> getTpWorldBlackList() {
return _tp_world_blacklist;
}
public Boolean getChairEnable() {
return _chair_enable;
}
public Integer getChairMaxWidth() {
return _chair_max_width;
}
public Boolean getChairSignCheck() {
return _chair_sign_check;
}
public Float getChairSitHeight() {
return _chair_sit_height;
}
public Boolean getRecipesCrowbar() {
return _recipes_crowbar;
}
public Boolean getRecipesInvisibleItemFrame() {
return _recipes_invisible_item_frame;
}
public Boolean getRecipesLightBlock() {
return _recipes_light_block;
}
public Boolean getRecipesStackedEnchantBook() {
return _recipes_stacked_enchant_book;
}
public void ApplyForceLoadChunks() {
if (_chunk_operate_delay < 0) {
XLogger.info("加载区块操作已禁用");
return;
}
Scheduler.runTaskLater(() -> {
// remove all force loaded chunks
int count = 0;
for (World world : EssentialsD.instance.getServer().getWorlds()) {
XLogger.debug("清除所有强加载区块: " + world.getName());
Collection<Chunk> chunks = world.getForceLoadedChunks();
for (Chunk chunk : chunks) {
count++;
world.setChunkForceLoaded(chunk.getX(), chunk.getZ(), false);
}
}
XLogger.info("清除所有强加载区块: " + count);
// world:0:0
for (String s : _force_load_chunks) {
String[] split = s.split(":");
if (split.length != 3) {
XLogger.warn("ForceLoadChunks 配置错误: " + s);
continue;
}
String world_name = split[0];
int x = Integer.parseInt(split[1]);
int z = Integer.parseInt(split[2]);
World world = _plugin.getServer().getWorld(world_name);
if (world == null) {
XLogger.warn("ForceLoadChunks 配置错误: 世界 " + world_name + " 不存在");
continue;
}
world.setChunkForceLoaded(x, z, true);
XLogger.info("标记强加载区块: " + world_name + " " + x + " " + z);
}
}, _chunk_operate_delay * 20);
}
public Integer getHomeLimitAmount() {
return _home_limit_amount;
}
public List<String> getHomeWorldBlacklist() {
return _home_world_blacklist;
}
public String getDbType() {
return _db_type;
}
public void setDbType(String db_type) {
_db_type = db_type;
_file.set("Database.Type", db_type);
_plugin.saveConfig();
}
public String getDbHost() {
return _db_host;
}
public String getDbPort() {
return _db_port;
}
public String getDbName() {
return _db_name;
}
public void setDbUser(String db_user) {
_db_user = db_user;
_file.set("Database.User", db_user);
_plugin.saveConfig();
}
public String getDbUser() {
if (_db_user.contains("@")) {
setDbUser("'" + _db_user + "'");
}
return _db_user;
}
public void setDbPass(String db_pass) {
_db_pass = db_pass;
_file.set("Database.Pass", db_pass);
_plugin.saveConfig();
}
public String getDbPass() {
if (_db_pass.contains("@")) {
setDbPass("'" + _db_pass + "'");
}
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;
private boolean _debug;
private float _exp_bottle_ratio;
private Boolean _combine_exp_orbs_enable;
private Float _combine_exp_orbs_radius;
private Boolean _no_exp_cool_down;
private List<String> _force_load_chunks;
private Integer _chunk_operate_delay;
private Integer _tp_tpa_expire;
private Integer _tp_delay;
private Integer _tp_cool_down;
private Integer _tp_rtp_radius;
private List<String> _tp_world_blacklist;
private Boolean _chair_enable;
private Integer _chair_max_width;
private Boolean _chair_sign_check;
private Float _chair_sit_height;
private Boolean _check_update;
// recipes
private Boolean _recipes_crowbar;
private Boolean _recipes_invisible_item_frame;
private Boolean _recipes_light_block;
private Boolean _recipes_stacked_enchant_book;
// home limit
private Integer _home_limit_amount;
private List<String> _home_world_blacklist;
// database
private String _db_type;
private String _db_host;
private String _db_port;
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

@ -0,0 +1,96 @@
package cn.lunadeer.essentialsd.managers;
import cn.lunadeer.essentialsd.EssentialsD;
public class DatabaseTables {
public static void migrate() {
String sql = "";
// player name
sql = "CREATE TABLE IF NOT EXISTS player_name (" +
" uuid VARCHAR(36) NOT NULL UNIQUE PRIMARY KEY," +
" last_known_name TEXT NOT NULL" +
");";
EssentialsD.database.query(sql);
// login record
sql = "CREATE TABLE IF NOT EXISTS login_record (" +
" id SERIAL PRIMARY KEY," +
" uuid VARCHAR(36) NOT NULL," +
" ip VARCHAR(15) NOT NULL," +
" login_time TIMESTAMP NOT NULL," +
" logout_location TEXT," +
" logout_time TIMESTAMP," +
" FOREIGN KEY (uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
");";
EssentialsD.database.query(sql);
// name record
sql = "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" +
");";
EssentialsD.database.query(sql);
// tp record
sql = "CREATE TABLE IF NOT EXISTS tp_record (" +
" id SERIAL PRIMARY KEY," +
" initiator_uuid VARCHAR(36) NOT NULL," +
" from_location TEXT NOT NULL," +
" to_location TEXT NOT NULL," +
" type TEXT NOT NULL," +
" success BOOLEAN NOT NULL," +
" time TIMESTAMP NOT NULL," +
" FOREIGN KEY (initiator_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
");";
EssentialsD.database.query(sql);
// message record
sql = "CREATE TABLE IF NOT EXISTS message_record (" +
" id SERIAL PRIMARY KEY," +
" sender_uuid VARCHAR(36) NOT NULL," +
" message TEXT NOT NULL," +
" time TIMESTAMP NOT NULL," +
" FOREIGN KEY (sender_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
");";
EssentialsD.database.query(sql);
// command record
sql = "CREATE TABLE IF NOT EXISTS command_record (" +
" id SERIAL PRIMARY KEY," +
" executor_uuid VARCHAR(36) NOT NULL," +
" command TEXT NOT NULL," +
" time TIMESTAMP NOT NULL," +
" FOREIGN KEY (executor_uuid) REFERENCES player_name(uuid) ON DELETE CASCADE" +
");";
EssentialsD.database.query(sql);
// home info
sql = "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" +
");";
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

@ -0,0 +1,328 @@
package cn.lunadeer.essentialsd.managers;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.minecraftpluginutils.Notification;
import cn.lunadeer.minecraftpluginutils.Scheduler;
import cn.lunadeer.minecraftpluginutils.XLogger;
import cn.lunadeer.minecraftpluginutils.stui.components.Button;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class TeleportManager {
private static final TextColor main_color = TextColor.color(0, 233, 255);
private final ConcurrentHashMap<UUID, TpTask> _tasks = new ConcurrentHashMap<>();
private final ConcurrentHashMap<UUID, LocalDateTime> _next_time_allow_tp = new ConcurrentHashMap<>();
private final ConcurrentHashMap<UUID, Location> _last_tp_location = new ConcurrentHashMap<>();
private static class TpTask {
public Player initiator;
public Player target;
public UUID taskId;
public Boolean tpahere = false;
}
private boolean tpReqCheckFail(Player initiator, Player target) {
if (initiator == target) {
Notification.error(initiator, "不能传送到同一个位置");
return true;
}
if (!target.isOnline()) {
Notification.error(initiator, "玩家 " + target.getName() + " 不在线");
return true;
}
if (EssentialsD.config.getTpWorldBlackList().contains(target.getWorld().getName())) {
Notification.error(initiator, "目的地所在世界 " + initiator.getWorld().getName() + " 不允许传送");
return true;
}
return CoolingDown(initiator);
}
public void tpaRequest(Player initiator, Player target) {
if (tpReqCheckFail(initiator, target)) return;
TpTask task = new TpTask();
task.initiator = initiator;
task.target = target;
task.taskId = UUID.randomUUID();
_tasks.put(task.taskId, task);
Notification.info(initiator, "已向 " + target.getName() + " 发送传送请求");
TextComponent acceptBtn = Button.createGreen("接受").setExecuteCommand("/tpa accept " + task.taskId).build();
TextComponent denyBtn = Button.createRed("拒绝").setExecuteCommand("/tpa deny " + task.taskId).build();
Notification.info(target, Component.text(" ", Style.style(main_color, TextDecoration.STRIKETHROUGH)));
Notification.info(target, Component.text("| 玩家 " + initiator.getName() + " 请求传送到你的位置", main_color));
Notification.info(target, Component.text("| 此请求将在 " + EssentialsD.config.getTpTpaExpire() + " 秒后失效", main_color));
Notification.info(target, Component.text("| ", main_color).append(acceptBtn).append(Component.text(" ", main_color)).append(denyBtn));
Notification.info(target, Component.text(" ", Style.style(main_color, TextDecoration.STRIKETHROUGH)));
Scheduler.runTaskLater(() -> {
_tasks.remove(task.taskId);
}, 20L * EssentialsD.config.getTpTpaExpire());
}
public void tpahereRequest(Player initiator, Player target) {
if (tpReqCheckFail(initiator, target)) return;
TpTask task = new TpTask();
task.initiator = initiator;
task.target = target;
task.taskId = UUID.randomUUID();
task.tpahere = true;
_tasks.put(task.taskId, task);
Notification.info(initiator, "已向 " + target.getName() + " 发送传送请求");
TextComponent acceptBtn = Button.createGreen("接受").setExecuteCommand("/tpa accept " + task.taskId).build();
TextComponent denyBtn = Button.createRed("拒绝").setExecuteCommand("/tpa deny " + task.taskId).build();
Notification.info(target, Component.text(" ", Style.style(main_color, TextDecoration.STRIKETHROUGH)));
Notification.info(target, Component.text("| 玩家 " + initiator.getName() + " 请求传送你到他的位置", main_color));
Notification.info(target, Component.text("| 此请求将在 " + EssentialsD.config.getTpTpaExpire() + " 秒后失效", main_color));
Notification.info(target, Component.text("| ", main_color).append(acceptBtn).append(Component.text(" ", main_color)).append(denyBtn));
Notification.info(target, Component.text(" ", Style.style(main_color, TextDecoration.STRIKETHROUGH)));
Scheduler.runTaskLater(() -> {
_tasks.remove(task.taskId);
}, 20L * EssentialsD.config.getTpTpaExpire());
}
public void deny(Player player, UUID taskId) {
TpTask task = _tasks.get(taskId);
if (task == null) {
Notification.error(player, "传送请求不存在或已过期");
return;
}
if (task.target != player) {
Notification.error(player, "这不是你的传送请求");
return;
}
_tasks.remove(taskId);
if (task.initiator.isOnline()) {
Notification.error(task.initiator, "玩家 " + player.getName() + " 拒绝了你的传送请求");
}
if (task.target.isOnline()) {
Notification.error(player, "已拒绝 " + task.initiator.getName() + " 的传送请求");
}
}
public void accept(Player player, UUID taskId) {
TpTask task = _tasks.get(taskId);
if (task == null) {
Notification.error(player, "传送请求不存在或已过期");
return;
}
if (task.target != player) {
Notification.error(player, "这不是你的传送请求");
return;
}
_tasks.remove(taskId);
if (!task.initiator.isOnline() || !task.target.isOnline()) {
return;
}
Notification.info(task.target, "已接受 " + task.initiator.getName() + " 的传送请求");
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已接受你的传送请求");
if (!task.tpahere) {
try {
doTeleportDelayed(task.initiator, task.target.getLocation(), EssentialsD.config.getTpDelay(), () -> {
Notification.info(task.initiator, "正在传送到 " + task.initiator.getName() + " 的位置");
}, () -> {
Notification.info(task.initiator, "已传送到 " + task.initiator.getName() + " 的位置");
Notification.info(task.target, "玩家 " + task.initiator.getName() + " 已传送到你的位置");
});
} catch (RuntimeException e) {
Notification.error(player, e.getMessage());
}
} else {
try {
doTeleportDelayed(task.target, task.initiator.getLocation(), EssentialsD.config.getTpDelay(), () -> {
Notification.info(task.target, "正在传送到 " + task.initiator.getName() + " 的位置");
}, () -> {
Notification.info(task.target, "已传送到 " + task.initiator.getName() + " 的位置");
Notification.info(task.initiator, "玩家 " + task.target.getName() + " 已传送到你的位置");
});
} catch (RuntimeException e) {
Notification.error(player, e.getMessage());
}
}
}
public void back(Player player) {
if (!_last_tp_location.containsKey(player.getUniqueId())) {
Notification.error(player, "没有找到可返回的位置");
return;
}
Location target = _last_tp_location.get(player.getUniqueId());
if (EssentialsD.config.getTpWorldBlackList().contains(target.getWorld().getName())) {
Notification.error(player, "目的地所在世界 " + target.getWorld().getName() + " 不允许传送");
return;
}
if (CoolingDown(player)) return;
if (EssentialsD.config.getTpDelay() > 0) {
Notification.info(player, "将在 " + EssentialsD.config.getTpDelay() + " 秒后返回上次传送的位置");
}
try {
doTeleportDelayed(player, target, EssentialsD.config.getTpDelay(), () -> {
Notification.info(player, "正在返回上次传送的位置");
}, () -> {
Notification.info(player, "已返回上次传送的位置");
});
} catch (RuntimeException e) {
Notification.error(player, e.getMessage());
}
}
public void rtp(Player player) {
if (EssentialsD.config.getTpWorldBlackList().contains(player.getWorld().getName())) {
Notification.error(player, "此世界 " + player.getWorld().getName() + " 不允许传送");
return;
}
if (CoolingDown(player)) return;
int radius = EssentialsD.config.getTpRtpRadius();
// 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);
Location location = new Location(world, x + 0.5, player.getY(), z + 0.5);
try {
doTeleportDelayed(player, location, EssentialsD.config.getTpDelay(), () -> {
Notification.info(player, "正在传送到随机位置");
}, () -> {
Notification.info(player, "已传送到随机位置");
});
} catch (RuntimeException e) {
Notification.error(player, e.getMessage());
}
}
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 to, Long delay, Runnable before, Runnable after) {
if (EssentialsD.config.getTpWorldBlackList().contains(to.getWorld().getName())) {
Notification.error(player, "目的地所在世界 %s 不允许传送", to.getWorld().getName());
return;
}
if (CoolingDown(player)) return;
if (delay > 0) {
Notification.info(player, "将在 %d 秒后执行传送", delay);
Scheduler.runTaskAsync(() -> {
long i = delay;
while (i > 0) {
if (!player.isOnline()) {
return;
}
Notification.actionBar(player, "传送倒计时 %d 秒", i);
i--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
XLogger.warn(e.getMessage());
return;
}
}
});
Scheduler.runTaskLater(() -> {
before.run();
doTeleportSafely(player, to);
after.run();
}, 20L * delay);
} else {
before.run();
doTeleportSafely(player, to);
after.run();
}
}
private boolean CoolingDown(Player player) {
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);
Notification.warn(player, "请等待 %d 秒后再次执行传送请求", secs_until_next);
return true;
}
}
return false;
}
/**
* 把玩家传送到指定位置 并更新上次传送的位置
*
* @param player 玩家
* @param location 位置
*/
public void doTeleportSafely(Player player, Location location) {
if (CoolingDown(player)) return;
LocalDateTime now = LocalDateTime.now();
_next_time_allow_tp.put(player.getUniqueId(), now.plusSeconds(EssentialsD.config.getTpCoolDown()));
location.getWorld().getChunkAtAsyncUrgently(location).thenAccept((chunk) -> {
int max_attempts = 512;
while (location.getBlock().isPassable()) {
location.setY(location.getY() - 1);
max_attempts--;
if (max_attempts <= 0) {
Notification.error(player, "传送目的地不安全,已取消传送");
return;
}
}
Block up1 = location.getBlock().getRelative(BlockFace.UP);
Block up2 = up1.getRelative(BlockFace.UP);
max_attempts = 512;
while (!(up1.isPassable() && !up1.isLiquid()) || !(up2.isPassable() && !up2.isLiquid())) {
location.setY(location.getY() + 1);
up1 = location.getBlock().getRelative(BlockFace.UP);
up2 = up1.getRelative(BlockFace.UP);
max_attempts--;
if (max_attempts <= 0) {
Notification.error(player, "传送目的地不安全,已取消传送");
return;
}
}
location.setY(location.getY() + 1);
if (location.getBlock().getRelative(BlockFace.DOWN).getType() == Material.LAVA) {
Notification.error(player, "传送目的地不安全,已取消传送");
return;
}
updateLastTpLocation(player);
player.teleportAsync(location, PlayerTeleportEvent.TeleportCause.PLUGIN);
});
}
public void updateLastTpLocation(Player player) {
_last_tp_location.put(player.getUniqueId(), player.getLocation());
}
}

View File

@ -0,0 +1,72 @@
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;
import org.bukkit.block.data.Rail;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.List;
import static org.bukkit.block.data.Rail.Shape.NORTH_SOUTH;
public class Crowbar {
public static ShapelessRecipe getRecipe() {
NamespacedKey key = new NamespacedKey(EssentialsD.instance, "crowbar");
ItemStack item = getItemStack();
ShapelessRecipe recipe = new ShapelessRecipe(key, item);
recipe.addIngredient(Material.STICK);
recipe.addIngredient(Material.IRON_INGOT);
return recipe;
}
public static ItemStack getItemStack(){
return getItemStack(1);
}
public static ItemStack getItemStack(Integer size) {
ItemStack item = new ItemStack(Material.STICK, size);
ItemMeta meta = item.getItemMeta();
meta.displayName(Component.text("撬棍"));
meta.getPersistentDataContainer().set(new NamespacedKey(EssentialsD.instance, "this_is_crowbar"), PersistentDataType.BYTE, (byte) 1);
List<Component> lore = new ArrayList<>();
lore.add(Component.text("神奇的物理学圣剑"));
lore.add(Component.text("对着铁轨使用可以改变铁轨方向"));
meta.lore(lore);
item.setItemMeta(meta);
return item;
}
public static Rail.Shape changeToNext(Rail.Shape shape){
boolean found = false;
for (Rail.Shape s : changeableShapes()) {
if (found) {
return s;
}
if (s == shape) {
found = true;
}
}
return NORTH_SOUTH;
}
public static Boolean changeable(Rail.Shape shape) {
return changeableShapes().contains(shape);
}
public static List<Rail.Shape> changeableShapes(){
List<Rail.Shape> shapes = new ArrayList<>();
shapes.add(Rail.Shape.NORTH_SOUTH);
shapes.add(Rail.Shape.EAST_WEST);
shapes.add(Rail.Shape.NORTH_WEST);
shapes.add(Rail.Shape.NORTH_EAST);
shapes.add(Rail.Shape.SOUTH_EAST);
shapes.add(Rail.Shape.SOUTH_WEST);
return shapes;
}
}

View File

@ -5,19 +5,20 @@ import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.ShapelessRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
public class InvisibleGlowItemFrame {
import java.util.ArrayList;
import java.util.List;
public static ShapedRecipe getRecipe() {
public class InvisibleGlowItemFrame {
public static ShapelessRecipe getRecipe() {
NamespacedKey key = new NamespacedKey(EssentialsD.instance, "invisible_glow_item_frame");
ItemStack item = getItemStack();
ShapedRecipe recipe = new ShapedRecipe(key, item);
recipe.shape("sss","sgs","sss");
recipe.setIngredient('s',Material.BLAZE_ROD);
recipe.setIngredient('g',Material.GLASS_PANE);
ShapelessRecipe recipe = new ShapelessRecipe(key, item);
recipe.addIngredient(InvisibleItemFrame.getItemStack());
recipe.addIngredient(Material.GLOWSTONE_DUST);
return recipe;
}
@ -30,6 +31,9 @@ public class InvisibleGlowItemFrame {
ItemMeta meta = item.getItemMeta();
meta.displayName(Component.text("隐形发光物品展示框"));
meta.getPersistentDataContainer().set(new NamespacedKey(EssentialsD.instance, "invisible"), PersistentDataType.BYTE, (byte) 1);
List<Component> lore = new ArrayList<>();
lore.add(Component.text("放置物品后会自动隐形"));
meta.lore(lore);
item.setItemMeta(meta);
return item;
}

View File

@ -4,11 +4,14 @@ import cn.lunadeer.essentialsd.EssentialsD;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Item;
import org.bukkit.inventory.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapedRecipe;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
import java.util.ArrayList;
import java.util.List;
public class InvisibleItemFrame {
public static ShapedRecipe getRecipe() {
@ -29,6 +32,9 @@ public class InvisibleItemFrame {
ItemMeta meta = item.getItemMeta();
meta.displayName(Component.text("隐形物品展示框"));
meta.getPersistentDataContainer().set(new NamespacedKey(EssentialsD.instance, "invisible"), PersistentDataType.BYTE, (byte) 1);
List<Component> lore = new ArrayList<>();
lore.add(Component.text("放置物品后会自动隐形"));
meta.lore(lore);
item.setItemMeta(meta);
return item;
}

View File

@ -0,0 +1,19 @@
package cn.lunadeer.essentialsd.recipes;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
public class LightBlock {
public static ShapelessRecipe getRecipe() {
NamespacedKey key = new NamespacedKey(EssentialsD.instance, "torch_to_light_block");
// 获取亮度为15的光源方块
ItemStack item = new ItemStack(Material.LIGHT, 1);
ShapelessRecipe recipe = new ShapelessRecipe(key, item);
recipe.addIngredient(Material.TORCH);
return recipe;
}
}

View File

@ -0,0 +1,23 @@
package cn.lunadeer.essentialsd.recipes;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.ShapelessRecipe;
public class StackedEnchantBook {
public static ShapelessRecipe getRecipe() {
NamespacedKey key = new NamespacedKey(EssentialsD.instance, "two_curse_of_vanishing_books");
ItemStack item = stackedEnchantBook();
ShapelessRecipe recipe = new ShapelessRecipe(key, item);
recipe.addIngredient(Material.BOOK);
recipe.addIngredient(Material.BOOK);
return recipe;
}
public static ItemStack stackedEnchantBook() {
return new ItemStack(Material.ENCHANTED_BOOK, 2);
}
}

View File

@ -0,0 +1,44 @@
package cn.lunadeer.essentialsd.tuis;
import cn.lunadeer.essentialsd.EssentialsD;
import cn.lunadeer.essentialsd.dtos.HomeInfo;
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 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.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, "/homes");
view.title("Home 列表");
for (HomeInfo home : homes) {
Line line = Line.create()
.append(home.homeName)
.append(Button.create("传送").setExecuteCommand("/home " + home.homeName).build())
.append(Button.createRed("删除").setExecuteCommand("/delhome " + home.homeName + " " + page).build());
view.add(line);
}
view.showOn(player, page);
}
}

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

@ -1,35 +0,0 @@
package cn.lunadeer.essentialsd.utils;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.configuration.file.FileConfiguration;
public class ConfigManager {
public ConfigManager(EssentialsD plugin) {
_plugin = plugin;
_plugin.saveDefaultConfig();
reload();
_plugin.saveConfig();
}
public void reload() {
_plugin.reloadConfig();
_file = _plugin.getConfig();
_debug = _file.getBoolean("Debug", false);
}
public Boolean isDebug() {
return _debug;
}
public void setDebug(Boolean debug) {
_debug = debug;
_file.set("Debug", debug);
_plugin.saveConfig();
}
private final EssentialsD _plugin;
private FileConfiguration _file;
private boolean _debug;
}

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

@ -1,63 +0,0 @@
package cn.lunadeer.essentialsd.utils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class Notification {
private static final Style i_style = Style.style(TextColor.color(139, 255, 123));
private static final Style w_style = Style.style(TextColor.color(255, 185, 69));
private static final Style e_style = Style.style(TextColor.color(255, 96, 72));
private static final String prefix = "[EssentialsD] ";
public static void info(Player player, String msg) {
player.sendMessage(Component.text(prefix + msg, i_style));
}
public static void warn(Player player, String msg) {
player.sendMessage(Component.text(prefix + msg, w_style));
}
public static void error(Player player, String msg) {
player.sendMessage(Component.text(prefix + msg, e_style));
}
public static void info(CommandSender sender, String msg) {
sender.sendMessage(Component.text(prefix + msg, i_style));
}
public static void warn(CommandSender sender, String msg) {
sender.sendMessage(Component.text(prefix + msg, w_style));
}
public static void error(CommandSender sender, String msg) {
sender.sendMessage(Component.text(prefix + msg, e_style));
}
public static void info(Player player, Component msg) {
player.sendMessage(Component.text(prefix, i_style).append(msg));
}
public static void warn(Player player, Component msg) {
player.sendMessage(Component.text(prefix, w_style).append(msg));
}
public static void error(Player player, Component msg) {
player.sendMessage(Component.text(prefix, e_style).append(msg));
}
public static void info(CommandSender player, Component msg) {
player.sendMessage(Component.text(prefix, i_style).append(msg));
}
public static void warn(CommandSender player, Component msg) {
player.sendMessage(Component.text(prefix, w_style).append(msg));
}
public static void error(CommandSender player, Component msg) {
player.sendMessage(Component.text(prefix, e_style).append(msg));
}
}

View File

@ -1,12 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
public class Button {
public static TextComponent create(String text, String command) {
return Component.text("[" + text + "]", ViewStyles.action_color)
.clickEvent(net.kyori.adventure.text.event.ClickEvent.clickEvent(net.kyori.adventure.text.event.ClickEvent.Action.RUN_COMMAND, command));
}
}

View File

@ -1,48 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import java.util.ArrayList;
import java.util.List;
public class Line {
private final List<Component> elements = new ArrayList<>();
private final TextComponent divider = Component.text(" - ", ViewStyles.sub_color);
public Line() {
}
public TextComponent build() {
TextComponent.Builder builder = Component.text();
for (int i = 0; i < elements.size(); i++) {
builder.append(elements.get(i));
if (i != elements.size() - 1) {
builder.append(divider);
}
}
return builder.build();
}
public static Line create() {
return new Line();
}
public Line append(TextComponent component) {
elements.add(component);
return this;
}
public Line append(Component component) {
elements.add(component);
return this;
}
public Line append(String component) {
elements.add(Component.text(component));
return this;
}
}

View File

@ -1,71 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import cn.lunadeer.essentialsd.utils.Notification;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
public class ListView {
private final Integer page_size;
private final List<Line> lines = new ArrayList<>();
private String command = "";
private final View view = View.create();
public ListView(int page_size, String command) {
super();
this.page_size = page_size;
this.command = command;
}
public static ListView create(int page_size, String command) {
return new ListView(page_size, command);
}
public ListView title(String title) {
view.title(title);
return this;
}
public ListView title(String title, String subtitle) {
view.title(title);
view.subtitle(subtitle);
return this;
}
public ListView subtitle(String subtitle) {
view.subtitle(subtitle);
return this;
}
public ListView add(Line line) {
lines.add(line);
return this;
}
public ListView addLines(List<Line> lines) {
this.lines.addAll(lines);
return this;
}
public void showOn(Player player, Integer page) {
int offset = (page - 1) * page_size;
if (lines.isEmpty()) {
Notification.warn(player, "没有数据");
return;
}
if (offset >= lines.size() || offset < 0) {
Notification.error(player, "页数超出范围");
return;
}
for (int i = offset; i < offset + page_size; i++) {
if (i >= lines.size()) {
break;
}
view.addLine(lines.get(i));
}
view.actionBar(Pagination.create(page, lines.size(), this.command));
view.showOn(player);
}
}

View File

@ -1,39 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import java.util.ArrayList;
import java.util.List;
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.main_color;
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.sub_color;
public class Pagination {
public static TextComponent create(int page, int item_size, String command) {
// x/y [上一页] [下一页]
int page_size = 4;
int page_count = (int) Math.ceil((double) item_size / page_size);
if (page_count == 0) {
page_count = 1;
}
List<Component> componentList = new ArrayList<>();
componentList.add(Component.text("", main_color));
componentList.add(Component.text(page, sub_color));
componentList.add(Component.text("/", main_color));
componentList.add(Component.text(page_count, sub_color));
componentList.add(Component.text("", main_color));
if (page > 1) {
componentList.add(Button.create("上一页", command + " " + (page - 1)));
}
if (page < page_count) {
componentList.add(Button.create("下一页", command + " " + (page + 1)));
}
TextComponent.Builder builder = Component.text();
for (Component component : componentList) {
builder.append(component);
}
return builder.build();
}
}

View File

@ -1,106 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import static cn.lunadeer.essentialsd.utils.STUI.ViewStyles.main_color;
public class View {
protected TextComponent title_decorate = Component.text("", main_color);
protected TextComponent space = Component.text(" ");
protected TextComponent sub_title_decorate = Component.text("- ", main_color);
protected TextComponent line_decorate = Component.text("", main_color);
protected TextComponent action_decorate = Component.text("", main_color);
protected TextComponent title = Component.text(" ");
protected TextComponent subtitle = Component.text("");
protected List<TextComponent> content_lines = new ArrayList<>();
protected TextComponent actionbar = Component.text(" ");
protected TextComponent edge = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
protected TextComponent divide_line = Component.text("━━━━━━━━━━━━━━━━━━━━━━━━━━━━", main_color);
public void showOn(Player player) {
player.sendMessage(edge);
TextComponent.Builder builder = Component.text();
int title_length = title.content().length();
int title_width = title_length * 2 + 2;
int decorate_count = divide_line.content().length() - title_width;
for (int i = 0; i < decorate_count / 2; i++) {
builder.append(title_decorate);
}
builder.append(space).append(title).append(space);
for (int i = 0; i < decorate_count / 2; i++) {
builder.append(title_decorate);
}
player.sendMessage(builder.build());
if (subtitle.content().length() > 0) {
player.sendMessage(divide_line);
player.sendMessage(Component.text().append(sub_title_decorate).append(subtitle).build());
}
player.sendMessage(divide_line);
for (TextComponent content_line : content_lines) {
player.sendMessage(Component.text().append(line_decorate).append(content_line).build());
}
player.sendMessage(divide_line);
player.sendMessage(Component.text().append(action_decorate).append(actionbar).build());
player.sendMessage(edge);
player.sendMessage(Component.text(" "));
}
public static View create() {
return new View();
}
public View title(String title) {
this.title = Component.text(title);
return this;
}
public View title(TextComponent title) {
this.title = title;
return this;
}
public View subtitle(String subtitle) {
this.subtitle = Component.text(subtitle);
return this;
}
public View subtitle(TextComponent subtitle) {
this.subtitle = subtitle;
return this;
}
public View actionBar(TextComponent actionbar) {
this.actionbar = actionbar;
return this;
}
public View actionBar(String actionbar) {
this.actionbar = Component.text(actionbar);
return this;
}
public View actionBar(Line actionbar) {
this.actionbar = actionbar.build();
return this;
}
public View addLine(TextComponent component) {
this.content_lines.add(component);
return this;
}
public View addLine(String component) {
this.content_lines.add(Component.text(component));
return this;
}
public View addLine(Line component) {
this.content_lines.add(component.build());
return this;
}
}

View File

@ -1,11 +0,0 @@
package cn.lunadeer.essentialsd.utils.STUI;
import net.kyori.adventure.text.format.TextColor;
public class ViewStyles {
public static TextColor main_color = TextColor.color(0, 148, 213);
public static TextColor sub_color = TextColor.color(122, 122, 122);
public static TextColor action_color = TextColor.color(251, 255, 139);
public static TextColor error_color = TextColor.color(255, 96, 72);
public static TextColor success_color = TextColor.color(139, 255, 123);
}

View File

@ -1,56 +0,0 @@
package cn.lunadeer.essentialsd.utils;
import cn.lunadeer.essentialsd.EssentialsD;
import org.bukkit.entity.Player;
import java.util.logging.Logger;
public class XLogger {
private static final EssentialsD _plugin = EssentialsD.instance;
private static final Logger _logger = _plugin.getLogger();
private static final String prefix = "[EssentialsD] ";
public static void info(Player player, String message) {
Notification.info(player, prefix + "I | " + message);
if (EssentialsD.config.isDebug())
debug("来自玩家[ " + player.getName() + " ] 的信息 | " + message);
}
public static void info(String message) {
_logger.info(" I | " + message);
}
public static void warn(Player player, String message) {
Notification.warn(player, prefix + "W | " + message);
if (EssentialsD.config.isDebug())
debug("来自玩家[ " + player.getName() + " ] 的警告 | " + message);
}
public static void warn(String message) {
_logger.warning(" W | " + message);
}
public static void err(Player player, String message) {
Notification.error(player, prefix + "E | " + message);
if (EssentialsD.config.isDebug())
debug("来自玩家[ " + player.getName() + " ] 的报错 | " + message);
}
public static void err(String message) {
_logger.severe(" E | " + message);
}
public static void debug(Player player, String message) {
if (!EssentialsD.config.isDebug()) return;
if (player.isOp())
Notification.info(player, prefix + "D | " + message);
else
debug("来自玩家[ " + player.getName() + " ] 的调试 | " + message);
}
public static void debug(String message) {
if (!EssentialsD.config.isDebug()) return;
_logger.info(" D | " + message);
}
}

View File

@ -1 +1,66 @@
Debug: false
# 数据库配置
Database:
Type: sqlite # pgsql, sqlite
Host: localhost # 数据库地址
Port: 5432 # 数据库端口
Name: essentials_d # 数据库名称
User: essentials_d # 数据库用户名
Pass: essentials_d # 数据库密码
# 附魔瓶经验值倍率
ExpBottleRatio: 1.0
# 合并经验球
CombineExpOrbs:
Enable: false
Radius: 1.5
# 经验吸收无冷却
NoExpCoolDown: false
# 强加载区块列表
ForceLoadChunks: [ ]
# - world:0:0
# - world_the_end:-12:12
# 区块操作延迟(强加载清理、设置) 秒
# 过低可能导致世界未加载完成时触发操作引起报错
# -1 为禁用强加载区块操作
ChunkOperateDelay: 10
# 扩展合成表
Recipes:
CrowBar: true # 撬棍
InvisibleItemFrame: true # 隐形(发光)物品展示框
LightBlock: true # 光源方块
StackedEnchantBook: true # 附魔书堆叠
# 传送
Teleport:
Delay: 0 # 传送延迟 秒
CoolDown: 0 # 冷却时间 秒
TpaExpire: 30 # 传送请求有效期 秒
RtpRadius: 1000 # 随机传送最大半径
WorldBlackList: [ ] # 不允许传送的世界
# 把楼梯当作椅子使用
Chair:
Enable: true
MaxWidth: 4
SignCheck: false
SitHeight: -0.95
# home 相关限制
HomeLimit:
Amount: 5 # 数量限制
WorldBlackList: [ ] # 不允许设置 home 的世界
# prefix (需要 PlaceholderAPI 支持)
Prefix:
Enable: false
ChatFormat: '<%player_name%> '
TabFormat: '%player_name%'
Debug: false
CheckUpdate: true

View File

@ -1,20 +1,197 @@
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
description: 允许使用 EssentialsD 的所有功能
essd.suicide:
default: true
essd.hat:
default: true
essd.showitem:
default: true
essd.skull:
default: true
essd.god:
default: op
essd.fly:
default: op
essd.time:
default: op
essd.save:
default: op
essd.more:
default: op
essd.weather:
default: op
essd.enderchest:
default: true
essd.tp.*:
default: true
children:
essd.tp.tpa: true
essd.tp.tpahere: true
essd.tp.rtp: true
essd.tp.back: true
essd.inspect:
default: op
essd.home:
default: true
essd.setwarp:
default: op
essd.delwarp:
default: op
essd.warp:
default: true
commands:
suicide:
description: 自杀
usage: /suicide
permission: essd.suicide
permission-message: 你不被允许自杀,快说“谢谢管理员”。
hat:
description: 将主手持的物品放在头部
usage: /hat
permission: essd.hat
permission-message: 管理员不允许你随便在头上放东西(没权限)。
showItem:
description: 展示主手持的物品
usage: /showItem
usage: /showitem
permission: essd.showitem
permission-message: 不要什么都想拿出来啊喂!(没权限)
skull:
description: 使用任意头颅交换获得一个自己的头颅
usage: /skull
usage: /skull
permission: essd.skull
permission-message: 禁止献祭(没权限)。
god:
description: 无敌模式
usage: /god [player]
permission: essd.god
permission-message: 禁止成仙(没权限)。
fly:
description: 飞行模式
usage: /fly [player]
permission: essd.fly
permission-message: 禁止起飞(没权限)。
day:
description: 设置时间为白天
usage: /day
permission: essd.time
permission-message: 起床失败(没权限)。
noon:
description: 设置时间为中午
usage: /noon
permission: essd.time
permission-message: 午休失败(没权限)。
night:
description: 设置时间为晚上
usage: /night
permission: essd.time
permission-message: 禁止熬夜(没权限)。
save:
description: 保存
usage: /save
permission: essd.save
permission-message: 保存失败(没权限)。
more:
description: 获取更多手持物品
usage: /more [amount]
permission: essd.more
permission-message: more不出来了没权限
sun:
description: 设置天气为晴天
usage: /sun
permission: essd.weather
permission-message: 禁止晒太阳(没权限)。
rain:
description: 设置天气为雨天
usage: /rain
permission: essd.weather
permission-message: 求雨失败(没权限)。
storm:
description: 设置天气为雷雨
usage: /storm
permission: essd.weather
permission-message: (没权限)。
enderchest:
description: 通过指令打开末影箱
usage: /enderchest
permission: essd.enderchest
permission-message: 你没有权限快速打开末影箱。
tpa:
description: 发起传送请求
usage: /tpa <player>
permission: essd.tp.tpa
permission-message: 你没有权限发起传送请求。
tpahere:
description: 发起传送到自己的请求
usage: /tpahere <player>
permission: essd.tp.tpahere
permission-message: 你没有权限发起传送请求。
rtp:
description: 随机传送到附近
usage: /rtp
permission: essd.tp.rtp
permission-message: 你没有权限随机传送。
back:
description: 回到上一个传送点
usage: /back
permission: essd.tp.back
permission-message: 你没有权限回到上一个传送点。
inspect:
description: 检查玩家背包
usage: /inspect <player>
permission: essd.inspect
permission-message: 禁止偷窥(没权限)。
home:
description: 回家
usage: /home [名称]
permission: essd.home
permission-message: 你没有权限使用home。
homes:
description: 查看家列表
usage: /homes
permission: essd.home
permission-message: 你没有权限使用home。
sethome:
description: 设置家
usage: /sethome [名称]
permission: essd.home
permission-message: 你没有权限使用home。
delhome:
description: 删除家
usage: /delhome <名称>
permission: essd.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: 你没有权限查看传送点列表。