- 版权类型
- 原创
- 插件中文名称
- 限制物品栏
- 插件英文名称
- RestrictedInv
- 原帖地址
- #
- 支持的核心(服务端)
- Spigot
- Paper
- Purpur
- 语言支持
- 多语言
- 适配版本(Java)
- 1.20
[MD]
# RestrictedInv
[](https://www.spigotmc.org/)
[](https://adoptium.net/)
[]()
一款基于 Spigot 的物品栏限制插件,支持多世界配置、等级系统、升级物品机制和物品堆叠限制。
## ✨ 功能特性
- 🌍 **多世界支持** - 可配置启用限制的世界列表
- 🎒 **三重限制模式**
- 快捷栏限制 - 保留指定槽位,其他禁用
- 副手限制 - 禁止使用副手
- 背包限制 - 支持等级递进解锁
- 📈 **等级系统** - 通过权限控制玩家限制等级
- 🎁 **升级物品** - 带附魔光效的可使用升级道具
- 🚫 **物品堆叠限制** - 可在指定世界禁用物品堆叠
- 🔗 **物品绑定系统** - 可绑定特定物品绕过堆叠限制
- 🔓 **Bypass权限** - 管理员可绕过所有限制
- 🔧 **高度可配置** - 所有文本和参数均可自定义
- 🔄 **热重载** - 无需重启服务器即可更新配置
- 🛡️ **防物品丢失** - 自动处理限制槽位中的物品
- 🛡️ **防插件冲突** - 最高优先级事件处理,防止其他插件强制堆叠
## 💻 环境要求
| 环境 | 版本要求 |
|------|----------|
| 服务端 | Spigot/Paper 1.16.5+ (推荐 1.20.1) |
| Java | 17 或更高版本 |
## 📥 安装方法
1. 下载最新版本的 JAR 文件
2. 将 JAR 文件放入服务器的 `plugins` 目录
3. 启动服务器,插件会自动生成配置文件
4. 根据需要修改配置文件
5. 使用 `/ri reload` 重载配置或重启服务器
## ⚙️ 配置说明
### 主配置 (config.yml)
```yaml
# RestrictedInv 配置文件
# 启用物品栏限制的世界列表
enabled-worlds:
- world
# 禁用物品堆叠的世界列表
# 在这些世界中,物品无法堆叠(每个槽位最多1个物品)
stacking-disabled-worlds:
- world_nether
```
#### 配置项说明
| 配置项 | 类型 | 说明 |
|--------|------|------|
| `enabled-worlds` | 列表 | 启用物品栏限制的世界名称列表 |
| `stacking-disabled-worlds` | 列表 | 禁用物品堆叠的世界名称列表 |
### 限制配置 (restriction_data.yml)[/MD]
[MD]
#### 占用方块配置
| 配置项 | 类型 | 说明 |
|--------|------|------|
| `material` | 物品ID | 占用方块的物品类型 |
| `name` | 字符串 | 占用方块的显示名称(支持颜色代码) |
#### 快捷栏限制配置
| 配置项 | 类型 | 说明 |
|--------|------|------|
| `enabled` | 布尔 | 是否启用快捷栏限制 |
| `slots` | 字符串 | 允许使用的槽位(其他槽位将被限制) |
#### 槽位格式说明
| 格式 | 示例 | 说明 |
|------|------|------|
| 单个槽位 | `9` | 仅禁用槽位 9 |
| 范围槽位 | `9-17` | 禁用槽位 9 到 17 |
| 多个范围 | `9-17, 27-35` | 禁用多个范围 |
| 全部解锁 | `all` | 解锁所有槽位 |
#### 槽位索引参考
```
快捷栏: [0] [1] [2] [3] [4] [5] [6] [7] [8]
背包: [9] [10] [11] [12] [13] [14] [15] [16] [17] <- 第一行
[18] [19] [20] [21] [22] [23] [24] [25] [26] <- 第二行
[27] [28] [29] [30] [31] [32] [33] [34] [35] <- 第三行
副手: [40]
```
### 语言配置 (lang.yml)[/MD]
[MD]
## 📝 指令说明
| 指令 | 描述 | 权限 |
|------|------|------|
| `/ri` | 显示帮助信息 | - |
| `/ri help` | 显示帮助信息 | - |
| `/ri reload` | 重载配置文件 | `restrictedinv.reload` |
| `/ri bind <等级>` | 获得指定等级的升级物品 | `restrictedinv.bind` |
| `/ri give <玩家> <等级>` | 给予玩家升级物品 | `restrictedinv.give` |
| `/ri stackbind` | 绑定手持物品不受堆叠限制 | `restrictedinv.stackbind` |
## 🔐 权限节点
| 权限 | 描述 | 默认 |
|------|------|------|
| `restrictedinv.admin` | 管理员权限(包含所有子权限) | OP |
| `restrictedinv.bypass` | 绕过所有限制 | OP |
| `restrictedinv.reload` | 重载配置权限 | OP |
| `restrictedinv.bind` | 获得升级物品权限 | OP |
| `restrictedinv.give` | 给予升级物品权限 | OP |
| `restrictedinv.stackbind` | 绑定物品绕过堆叠限制权限 | OP |
| `restrictedinv.level.0` | 等级0权限(默认) | 所有人 |
| `restrictedinv.level.1` | 等级1权限 | OP |
| `restrictedinv.level.2` | 等级2权限(完全解锁) | OP |
| `restrictedinv.level.X` | 等级X权限(可自定义更多等级) | - |
### Bypass权限详情
拥有 `restrictedinv.bypass` 权限的玩家将:
- 不受物品栏槽位限制
- 不受快捷栏限制
- 不受副手限制
- 不受物品堆叠限制
- 可以自由移动占位方块
- 进入世界时不会填充占位方块
## 📊 等级系统
### 工作原理
1. 插件检查玩家拥有的最高等级权限
2. 根据等级配置确定禁用的槽位
3. 在禁用槽位填充占用方块
4. 玩家使用升级物品后获得更高等级权限
### 默认等级配置
| 等级 | 禁用槽位 | 可用槽位 | 升级物品 | 权限节点 |
|------|----------|----------|----------|----------|
| 0 | 9-26 | 0-8, 27-35 | 无 | `restrictedinv.level.0` |
| 1 | 9-17 | 0-8, 18-35 | 白色潜影盒 | `restrictedinv.level.1` |
| 2 | 无 | 0-35 | 淡灰色潜影盒 | `restrictedinv.level.2` |
### 自定义等级
在 `restriction_data.yml` 中添加更多等级:
```yaml
inventory-restriction:
levels:
0:
slots: ["9-26"]
item: NONE
1:
slots: ["9-17"]
item:
material: WHITE_SHULKER_BOX
name: "&e背包扩展 I"
2:
slots: ["9-9"] # 仅禁用槽位9
item:
material: LIGHT_GRAY_SHULKER_BOX
name: "&e背包扩展 II"
3:
slots: ["all"] # 完全解锁
item:
material: GREEN_SHULKER_BOX
name: "&e背包扩展 III"
```
然后在权限插件中添加对应的 `restrictedinv.level.3` 权限。
### 升级物品
升级物品具有以下特性:
- 自定义名称和Lore
- 右键点击使用
- 使用后自动授予对应等级权限
- 可以自由丢弃和移动
- 可以在任何世界使用(不限制在启用限制的世界)
## 🚫 物品堆叠限制
### 功能说明
在配置的世界中,物品无法堆叠,每个槽位最多只能放置1个物品。
### 配置方法
在 `config.yml` 中添加需要禁用堆叠的世界:
```yaml
stacking-disabled-worlds:
- world_nether
- world_the_end
```
### 限制范围
物品堆叠限制会在以下情况下生效:
- 玩家点击物品时
- Shift点击移动物品时
- 拖拽物品时
- 捡起物品时
- 创造模式操作时
### 防止其他插件绕过
插件使用 `EventPriority.HIGHEST` 优先级处理事件,确保在其他插件处理之后再次检查堆叠限制,防止被绕过。
### 与其他功能的关系
- 物品堆叠限制独立于物品栏限制
- 可以在启用物品栏限制的世界中单独使用
- 也可以在未启用物品栏限制的世界中使用
- Bypass权限可以绕过此限制
- 绑定物品可以绕过此限制
## 🔗 物品绑定系统
### 功能说明
物品绑定系统允许管理员将特定物品标记为"可堆叠",使其在禁用堆叠的世界中也能正常堆叠。
### 使用场景
- 特殊道具需要在禁用堆叠的世界中堆叠
- 活动物品需要绕过堆叠限制
- VIP特权物品
### 使用方法
1. 手持需要绑定的物品
2. 执行 `/ri stackbind` 指令
3. 系统会提示绑定成功
### 技术实现
- 使用 `PersistentDataContainer` 存储绑定标记
- 标记数据存储在物品的 NBT 中
- 物品死亡后标记不会消失
- 物品交易后标记会保留
### 绑定物品特性
绑定后的物品具有以下特性:
- 可以在禁用堆叠的世界中正常堆叠
- 可以放入已有相同物品的槽位
- 捡起时可以与背包中相同物品合并
- Shift点击时可以正常移动
## 📄 版权声明
**All rights resevred**
---
[/MD]
[MD]
```yaml
# RestrictedInv 限制配置文件
# 占用方块配置
# 用于填充被限制的物品栏槽位
placeholder-block:
material: WHITE_STAINED_GLASS_PANE
name: " "
# 副手限制
# 禁止玩家在副手放置物品
offhand-restriction:
enabled: true
# 背包限制
# 支持等级系统,等级越高解锁的槽位越多
# 槽位索引参考:
# 快捷栏: [0] [1] [2] [3] [4] [5] [6] [7] [8]
# 背包: [9] [10] [11] [12] [13] [14] [15] [16] [17] <- 第一行
# [18] [19] [20] [21] [22] [23] [24] [25] [26] <- 第二行
# [27] [28] [29] [30] [31] [32] [33] [34] [35] <- 第三行
# 副手: [40]
inventory-restriction:
enabled: true
levels:
# 等级0:默认等级
# 仅可用快捷栏前5格 (0-4)
0:
slots:
- "5-26"
item: NONE
# 等级1:解锁部分背包
# 可用快捷栏前5格 + 背包第二、三行
1:
slots:
- "5-17"
item:
material: WHITE_SHULKER_BOX
name: "&e背包扩展 I"
# 等级2:完全解锁
# 解锁全部槽位
2:
slots:
- "all"
item:
material: LIGHT_GRAY_SHULKER_BOX
name: "&e背包扩展 II"
[/MD]
[MD]
```yaml
# RestrictedInv 语言配置文件
# 消息前缀
prefix: "&e[RestrictedInv] "
# 无权限提示
no-permission: "&c你没有权限执行此操作!"
# 重载成功
reload-success: "&a配置文件已重新加载!"
# 仅玩家可用
player-only: "&c该指令只能由玩家执行!"
# 无效等级
invalid-level: "&c无效的等级!"
# 绑定成功
bind-success: "&a成功获得等级 {level} 的升级物品!"
# 世界未启用
world-not-enabled: "&c当前世界未启用物品栏限制!"
# 已是最高等级
already-max-level: "&c你已经拥有更高或相同等级!"
# 升级成功
upgrade-success: "&a成功升级物品栏至等级 {level}!"
# 无法使用物品
cannot-use-item: "&c你无法使用此物品!"
# 升级物品Lore
# {level} 会被替换为目标等级
upgrade-item-lore:
- "&e右键以使用该物品"
- "&e提升物品栏格数至 {level}"
```
[/MD]
[MD]
## 📚 完整API文档
### API概述
RestrictedInv 提供了完整的开发者API,允许其他插件集成和扩展功能。
### 获取插件实例
```java
import com.Harry_H2O.restrictedInv.RestrictedInv;
public class YourPlugin extends JavaPlugin {
@Override
public void onEnable() {
RestrictedInv restrictedInv = RestrictedInv.getInstance();
}
}
```
### API架构图
```
RestrictedInv (主类)
├── ConfigManager (配置管理器)
│ ├── MainConfig (主配置)
│ ├── RestrictionConfig (限制配置)
│ └── LanguageConfig (语言配置)
├── RestrictionManager (限制管理器)
└── UpgradeManager (升级物品管理器)
```
---
### RestrictedInv 主类API
主类是插件的入口点,提供获取各管理器的静态方法。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `getInstance()` | `RestrictedInv` | 获取插件单例实例 |
| `getConfigManager()` | `ConfigManager` | 获取配置管理器 |
| `getRestrictionManager()` | `RestrictionManager` | 获取限制管理器 |
| `getUpgradeManager()` | `UpgradeManager` | 获取升级物品管理器 |
**使用示例:**
```java
RestrictedInv plugin = RestrictedInv.getInstance();
ConfigManager configManager = plugin.getConfigManager();
RestrictionManager restrictionManager = plugin.getRestrictionManager();
UpgradeManager upgradeManager = plugin.getUpgradeManager();
```
---
### ConfigManager API
配置管理器负责加载和管理所有配置文件。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `loadAll()` | `void` | 加载所有配置文件 |
| `reloadAll()` | `void` | 重新加载所有配置文件 |
| `getMainConfig()` | `MainConfig` | 获取主配置实例 |
| `getRestrictionConfig()` | `RestrictionConfig` | 获取限制配置实例 |
| `getLanguageConfig()` | `LanguageConfig` | 获取语言配置实例 |
**使用示例:**
```java
ConfigManager configManager = RestrictedInv.getInstance().getConfigManager();
MainConfig mainConfig = configManager.getMainConfig();
RestrictionConfig restrictionConfig = configManager.getRestrictionConfig();
LanguageConfig languageConfig = configManager.getLanguageConfig();
configManager.reloadAll();
```
---
### MainConfig API
主配置类,管理全局配置选项。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `isWorldEnabled(String worldName)` | `boolean` | 检查指定世界是否启用物品栏限制 |
| `isStackingDisabled(String worldName)` | `boolean` | 检查指定世界是否禁用物品堆叠 |
**使用示例:**
```java
MainConfig mainConfig = configManager.getMainConfig();
if (mainConfig.isWorldEnabled("world")) {
}
if (mainConfig.isStackingDisabled("world_nether")) {
}
```
---
### RestrictionConfig API
限制配置类,管理物品栏限制相关配置。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `getPlaceholderBlock()` | `ItemStack` | 获取占位方块(返回克隆副本) |
| `isHotbarRestrictionEnabled()` | `boolean` | 检查快捷栏限制是否启用 |
| `getHotbarAllowedSlots()` | `Set<Integer>` | 获取快捷栏允许的槽位集合 |
| `isOffhandRestrictionEnabled()` | `boolean` | 检查副手限制是否启用 |
| `getLevels()` | `Map<Integer, LevelData>` | 获取所有等级配置 |
| `getHighestLevel()` | `int` | 获取最高等级数值 |
| `getLevelData(int level)` | `LevelData` | 获取指定等级的配置数据 |
**LevelData 记录类:**
| 字段/方法 | 类型 | 描述 |
|-----------|------|------|
| `restrictedSlots()` | `Set<Integer>` | 被限制的槽位集合 |
| `upgradeItem()` | `ItemStack` | 升级物品 |
| `isAllUnlocked()` | `boolean` | 检查是否全部解锁 |
**使用示例:**
```java
RestrictionConfig restrictionConfig = configManager.getRestrictionConfig();
ItemStack placeholder = restrictionConfig.getPlaceholderBlock();
if (restrictionConfig.isHotbarRestrictionEnabled()) {
Set<Integer> allowedSlots = restrictionConfig.getHotbarAllowedSlots();
}
int highestLevel = restrictionConfig.getHighestLevel();
for (int level = 0; level <= highestLevel; level++) {
RestrictionConfig.LevelData levelData = restrictionConfig.getLevelData(level);
if (levelData != null) {
Set<Integer> restrictedSlots = levelData.restrictedSlots();
ItemStack upgradeItem = levelData.upgradeItem();
boolean allUnlocked = levelData.isAllUnlocked();
}
}
```
---
### LanguageConfig API
语言配置类,管理所有可配置的消息文本。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `getPrefix()` | `String` | 获取消息前缀 |
| `getNoPermission()` | `String` | 获取无权限提示 |
| `getReloadSuccess()` | `String` | 获取重载成功提示 |
| `getPlayerOnly()` | `String` | 获取仅玩家可用提示 |
| `getInvalidLevel()` | `String` | 获取无效等级提示 |
| `getBindSuccess()` | `String` | 获取绑定成功提示 |
| `getWorldNotEnabled()` | `String` | 获取世界未启用提示 |
| `getAlreadyMaxLevel()` | `String` | 获取已是最高等级提示 |
| `getUpgradeSuccess()` | `String` | 获取升级成功提示 |
| `getUpgradeItemLore(int level)` | `List<String>` | 获取升级物品Lore(替换等级变量) |
**使用示例:**
```java
LanguageConfig langConfig = configManager.getLanguageConfig();
String prefix = langConfig.getPrefix();
String message = prefix + langConfig.getNoPermission();
player.sendMessage(message);
List<String> lore = langConfig.getUpgradeItemLore(1);
```
---
### RestrictionManager API
限制管理器是核心API,负责管理玩家的物品栏限制状态。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `loadPlayer(Player player)` | `void` | 加载玩家限制数据 |
| `unloadPlayer(Player player)` | `void` | 卸载玩家限制数据 |
| `getPlayerLevel(Player player)` | `int` | 获取玩家的限制等级 |
| `calculateRestrictedSlots(int level)` | `Set<Integer>` | 计算指定等级的限制槽位 |
| `calculateHotbarRestrictedSlots()` | `Set<Integer>` | 计算快捷栏被限制的槽位 |
| `fillRestrictedSlots(Player player)` | `void` | 填充玩家的限制槽位 |
| `clearRestrictedSlots(Player player)` | `void` | 清除玩家的占位方块 |
| `isPlaceholderBlock(ItemStack item)` | `boolean` | 检查物品是否为占位方块 |
| `isSlotRestricted(Player player, int slot)` | `boolean` | 检查槽位是否被限制 |
| `isOffhandRestricted(Player player)` | `boolean` | 检查副手是否被限制 |
| `isWorldEnabled(Player player)` | `boolean` | 检查玩家所在世界是否启用限制 |
| `hasBypass(Player player)` | `boolean` | 检查玩家是否有bypass权限 |
| `updatePlayerLevel(Player player)` | `void` | 更新玩家的限制等级 |
| `getRestrictedSlots(Player player)` | `Set<Integer>` | 获取玩家的所有限制槽位 |
**使用示例:**
```java
RestrictionManager restrictionManager = plugin.getRestrictionManager();
restrictionManager.loadPlayer(player);
int level = restrictionManager.getPlayerLevel(player);
player.sendMessage("你的限制等级: " + level);
if (restrictionManager.isWorldEnabled(player)) {
if (restrictionManager.hasBypass(player)) {
player.sendMessage("你拥有绕过权限!");
} else {
Set<Integer> restrictedSlots = restrictionManager.getRestrictedSlots(player);
player.sendMessage("被限制的槽位数量: " + restrictedSlots.size());
int slot = 15;
if (restrictionManager.isSlotRestricted(player, slot)) {
player.sendMessage("槽位 " + slot + " 被限制!");
}
if (restrictionManager.isOffhandRestricted(player)) {
player.sendMessage("副手被限制!");
}
}
}
ItemStack item = player.getInventory().getItem(10);
if (restrictionManager.isPlaceholderBlock(item)) {
player.sendMessage("这是占位方块!");
}
restrictionManager.unloadPlayer(player);
```
**等级提升示例:**
```java
public void upgradePlayer(Player player, int newLevel) {
String permission = "restrictedinv.level." + newLevel;
player.addAttachment(plugin, permission, true);
restrictionManager.updatePlayerLevel(player);
player.sendMessage("§a成功升级至等级 " + newLevel + "!");
}
```
---
### UpgradeManager API
升级物品管理器,负责创建和管理升级物品。
**常量:**
| 常量 | 值 | 描述 |
|------|-----|------|
| `UPGRADE_KEY` | `"RestrictedInv_Upgrade"` | 升级物品NBT键名 |
| `STACKABLE_KEY` | `"RestrictedInv_Stackable"` | 可堆叠物品NBT键名 |
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `createUpgradeItem(int level)` | `ItemStack` | 创建指定等级的升级物品 |
| `isUpgradeItem(ItemStack item)` | `boolean` | 检查物品是否为升级物品 |
| `getUpgradeLevel(ItemStack item)` | `int` | 获取升级物品的目标等级(无效返回-1) |
| `applyUpgrade(Player player, int targetLevel)` | `void` | 应用升级效果 |
| `giveUpgradeItem(Player player, int level)` | `void` | 给予玩家升级物品 |
| `markAsStackable(ItemStack item)` | `boolean` | 标记物品为可堆叠 |
| `isStackableItem(ItemStack item)` | `boolean` | 检查物品是否被标记为可堆叠 |
**使用示例:**
```java
UpgradeManager upgradeManager = plugin.getUpgradeManager();
ItemStack upgradeItem = upgradeManager.createUpgradeItem(1);
if (upgradeItem != null) {
player.getInventory().addItem(upgradeItem);
}
ItemStack handItem = player.getInventory().getItemInMainHand();
if (upgradeManager.isUpgradeItem(handItem)) {
int targetLevel = upgradeManager.getUpgradeLevel(handItem);
player.sendMessage("这是升级物品,目标等级: " + targetLevel);
upgradeManager.applyUpgrade(player, targetLevel);
}
upgradeManager.giveUpgradeItem(player, 2);
ItemStack specialItem = new ItemStack(Material.DIAMOND);
if (upgradeManager.markAsStackable(specialItem)) {
player.getInventory().addItem(specialItem);
player.sendMessage("已标记物品为可堆叠!");
}
if (upgradeManager.isStackableItem(specialItem)) {
player.sendMessage("此物品可以绕过堆叠限制!");
}
```
**自定义升级物品示例:**
```java
public void giveCustomUpgradeItem(Player player, int level) {
UpgradeManager upgradeManager = plugin.getUpgradeManager();
ItemStack upgradeItem = upgradeManager.createUpgradeItem(level);
if (upgradeItem == null) {
player.sendMessage("§c无效的等级!");
return;
}
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(upgradeItem);
if (!leftover.isEmpty()) {
player.getWorld().dropItemNaturally(player.getLocation(), upgradeItem);
player.sendMessage("§e背包已满,升级物品已掉落在地上!");
} else {
player.sendMessage("§a已获得等级 " + level + " 的升级物品!");
}
}
```
---
### ItemBuilder 工具类API
物品构建工具类,提供链式API用于快速构建ItemStack。
| 方法 | 返回类型 | 描述 |
|------|----------|------|
| `ItemBuilder(Material material)` | 构造函数 | 使用指定材料创建构建器 |
| `ItemBuilder(ItemStack item)` | 构造函数 | 使用现有物品创建构建器 |
| `lore(List<String> lore)` | `ItemBuilder` | 设置物品Lore(自动处理颜色代码) |
| `glow(boolean glow)` | `ItemBuilder` | 设置物品附魔光效 |
| `build()` | `ItemStack` | 构建最终的ItemStack |
| `static of(ItemStack item)` | `ItemBuilder` | 从现有ItemStack创建构建器 |
**使用示例:**
```java
import com.Harry_H2O.restrictedInv.util.ItemBuilder;
ItemStack item = ItemBuilder.of(new ItemStack(Material.DIAMOND_SWORD))
.lore(Arrays.asList(
"&6传说之剑",
"&7攻击力: &c+100",
"&e右键使用特殊技能"
))
.glow(true)
.build();
player.getInventory().addItem(item);
```
---
### NBT数据键说明
插件使用 `PersistentDataContainer` 存储物品的特殊标记。
| 键名 | 类型 | 存储位置 | 描述 |
|------|------|----------|------|
| `RestrictedInv_Upgrade` | `INTEGER` | 升级物品 | 存储目标等级 |
| `RestrictedInv_Stackable` | `BYTE` | 可堆叠物品 | 标记物品可绕过堆叠限制 |
**检查NBT数据示例:**
```java
import org.bukkit.NamespacedKey;
import org.bukkit.persistence.PersistentDataType;
NamespacedKey upgradeKey = new NamespacedKey(plugin, "RestrictedInv_Upgrade");
NamespacedKey stackableKey = new NamespacedKey(plugin, "RestrictedInv_Stackable");
ItemStack item = player.getInventory().getItemInMainHand();
if (item != null && item.hasItemMeta()) {
var meta = item.getItemMeta();
var container = meta.getPersistentDataContainer();
if (container.has(upgradeKey, PersistentDataType.INTEGER)) {
int level = container.get(upgradeKey, PersistentDataType.INTEGER);
player.sendMessage("升级物品等级: " + level);
}
if (container.has(stackableKey, PersistentDataType.BYTE)) {
player.sendMessage("此物品可绕过堆叠限制!");
}
}
```
---
### 事件监听列表
插件监听以下Bukkit事件:
| 事件类 | 优先级 | 忽略取消 | 描述 |
|--------|--------|----------|------|
| `PlayerJoinEvent` | NORMAL | 否 | 加载玩家限制数据 |
| `PlayerQuitEvent` | NORMAL | 否 | 卸载玩家限制数据 |
| `PlayerChangedWorldEvent` | NORMAL | 否 | 处理世界切换 |
| `PlayerRespawnEvent` | MONITOR | 否 | 处理玩家重生 |
| `PlayerDeathEvent` | HIGH | 否 | 移除占位方块掉落 |
| `PlayerDropItemEvent` | HIGH | 否 | 阻止占位方块丢弃 |
| `PlayerSwapHandItemsEvent` | HIGH | 否 | 阻止副手交换 |
| `PlayerItemHeldEvent` | MONITOR | 否 | 处理快捷栏切换 |
| `PlayerPickupItemEvent` | HIGH | 否 | 处理物品捡起堆叠限制 |
| `InventoryClickEvent` | HIGH | 否 | 处理物品栏点击 |
| `InventoryClickEvent` | HIGHEST | 是 | 防止其他插件绕过堆叠限制 |
| `InventoryDragEvent` | HIGH | 否 | 处理物品栏拖拽 |
| `InventoryCreativeEvent` | HIGH | 否 | 处理创造模式操作 |
| `PlayerInteractEvent` | HIGH | 否 | 处理升级物品使用 |
| `BlockPlaceEvent` | HIGH | 否 | 阻止升级物品和占位方块放置 |
---
### 完整集成示例
以下是一个完整的示例插件,展示如何集成RestrictedInv API:
```java
import com.Harry_H2O.restrictedInv.RestrictedInv;
import com.Harry_H2O.restrictedInv.manager.RestrictionManager;
import com.Harry_H2O.restrictedInv.manager.UpgradeManager;
import com.Harry_H2O.restrictedInv.config.ConfigManager;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.java.JavaPlugin;
public class MyPlugin extends JavaPlugin implements Listener {
private RestrictedInv restrictedInv;
@Override
public void onEnable() {
restrictedInv = RestrictedInv.getInstance();
if (restrictedInv == null) {
getLogger().warning("RestrictedInv not found! Some features may not work.");
return;
}
getServer().getPluginManager().registerEvents(this, this);
getLogger().info("MyPlugin has been enabled with RestrictedInv integration!");
}
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
ConfigManager configManager = restrictedInv.getConfigManager();
RestrictionManager restrictionManager = restrictedInv.getRestrictionManager();
UpgradeManager upgradeManager = restrictedInv.getUpgradeManager();
if (restrictionManager.isWorldEnabled(player)) {
int level = restrictionManager.getPlayerLevel(player);
player.sendMessage("§e欢迎!你的背包限制等级: §a" + level);
if (level < 2) {
upgradeManager.giveUpgradeItem(player, level + 1);
player.sendMessage("§a你获得了一个升级物品!");
}
}
}
public void checkPlayerInventory(Player player) {
RestrictionManager rm = restrictedInv.getRestrictionManager();
if (rm.hasBypass(player)) {
player.sendMessage("§6你拥有绕过权限,不受限制!");
return;
}
Set<Integer> restricted = rm.getRestrictedSlots(player);
player.sendMessage("§e被限制的槽位: §c" + restricted.size() + " §e个");
if (rm.isOffhandRestricted(player)) {
player.sendMessage("§c副手被限制!");
}
}
public void forceUpgrade(Player player, int targetLevel) {
RestrictionManager rm = restrictedInv.getRestrictionManager();
int currentLevel = rm.getPlayerLevel(player);
if (targetLevel <= currentLevel) {
player.sendMessage("§c目标等级必须高于当前等级!");
return;
}
String permission = "restrictedinv.level." + targetLevel;
player.addAttachment(this, permission, true);
rm.updatePlayerLevel(player);
player.sendMessage("§a成功强制升级至等级 " + targetLevel + "!");
}
}
```
### 开发者注意事项
1. **线程安全**: 所有API方法应在主线程调用
2. **空检查**: 调用API前检查 `getInstance()` 是否返回 `null`
3. **权限管理**: 使用 `updatePlayerLevel()` 而非直接修改权限
4. **物品克隆**: `getPlaceholderBlock()` 返回克隆副本,可直接使用
5. **NBT键名**: 使用常量 `UPGRADE_KEY` 和 `STACKABLE_KEY` 而非硬编码字符串
[/MD]