实现3个新功能:耕地破坏权限(denyFarmlandTrample)+末影人传送控制(denyEnderTeleport)+容器记录按天分页
Auto Release / build (push) Successful in 27s

This commit is contained in:
2026-07-21 22:49:35 +08:00
parent e860b6ff4f
commit c64bc718a6
5 changed files with 183 additions and 20 deletions
@@ -565,6 +565,8 @@ public class AreaCLIManager {
case "audio": oldState = land.denyNoteblockJukebox; land.denyNoteblockJukebox = !land.denyNoteblockJukebox; break;
case "lead": oldState = land.denyLead; land.denyLead = !land.denyLead; break;
case "crop_harvest": oldState = land.denyCropHarvest; land.denyCropHarvest = !land.denyCropHarvest; break;
case "farmland_trample": oldState = land.denyFarmlandTrample; land.denyFarmlandTrample = !land.denyFarmlandTrample; break;
case "ender_teleport": oldState = land.denyEnderTeleport; land.denyEnderTeleport = !land.denyEnderTeleport; break;
case "wool_shear": oldState = land.denyWoolShear; land.denyWoolShear = !land.denyWoolShear; break;
case "animal_feed": oldState = land.denyAnimalFeeding; land.denyAnimalFeeding = !land.denyAnimalFeeding; break;
case "mob_attack": oldState = land.denyMobAttack; land.denyMobAttack = !land.denyMobAttack; break;
@@ -622,6 +624,8 @@ public class AreaCLIManager {
case "audio": return "denyNoteblockJukebox";
case "lead": return "denyLead";
case "crop_harvest": return "denyCropHarvest";
case "farmland_trample": return "denyFarmlandTrample";
case "ender_teleport": return "denyEnderTeleport";
case "wool_shear": return "denyWoolShear";
case "animal_feed": return "denyAnimalFeeding";
case "mob_attack": return "denyMobAttack";
@@ -682,6 +686,8 @@ public class AreaCLIManager {
perms.add(new PermItem("audio", "音频(音符盒/唱片机)", !land.denyNoteblockJukebox));
perms.add(new PermItem("lead", "拴绳使用", !land.denyLead));
perms.add(new PermItem("crop_harvest", land.denyCropHarvest ? "禁用农作物收获" : "启用农作物收获", !land.denyCropHarvest));
perms.add(new PermItem("farmland_trample", land.denyFarmlandTrample ? "禁用耕地破坏" : "启用耕地破坏", !land.denyFarmlandTrample));
perms.add(new PermItem("ender_teleport", land.denyEnderTeleport ? "禁止末影人传送" : "允许末影人传送", !land.denyEnderTeleport));
perms.add(new PermItem("wool_shear", "剪切羊毛/生物", !land.denyWoolShear));
perms.add(new PermItem("animal_feed", land.denyAnimalFeeding ? "禁止投喂" : "允许投喂动物", !land.denyAnimalFeeding));
perms.add(new PermItem("mob_attack", land.denyMobAttack ? "禁止攻击生物" : "允许攻击生物", !land.denyMobAttack));
@@ -721,6 +727,8 @@ public class AreaCLIManager {
case "audio": return "音频";
case "lead": return "拴绳使用";
case "crop_harvest": return "农作物收获";
case "farmland_trample": return "耕地破坏";
case "ender_teleport": return "末影人传送";
case "wool_shear": return "剪切羊毛";
case "animal_feed": return "投喂动物";
case "mob_attack": return "攻击生物";
@@ -1135,6 +1143,8 @@ public class AreaCLIManager {
{"audio", "音频(音符盒/唱片机)", "denyNoteblockJukebox"},
{"lead", "拴绳使用", "denyLead"},
{"crop_harvest", "农作物收获", "denyCropHarvest"},
{"farmland_trample", "耕地破坏", "denyFarmlandTrample"},
{"ender_teleport", "末影人传送", "denyEnderTeleport"},
{"wool_shear", "剪切羊毛/生物", "denyWoolShear"},
{"animal_feed", "投喂动物", "denyAnimalFeeding"},
{"mob_attack", "攻击生物", "denyMobAttack"},
@@ -1173,6 +1183,14 @@ public class AreaCLIManager {
if (field.equals("denySignEdit")) {
name = landDefault ? "禁止编辑告示牌" : "允许编辑告示牌";
}
// ★ denyFarmlandTrample显示名称
if (field.equals("denyFarmlandTrample")) {
name = landDefault ? "禁用耕地破坏" : "启用耕地破坏";
}
// ★ denyEnderTeleport显示名称
if (field.equals("denyEnderTeleport")) {
name = landDefault ? "禁止末影人传送" : "允许末影人传送";
}
// 如果有per-player覆盖,使用覆盖值;否则使用领地默认
if (playerPerms.containsKey(field)) {
@@ -1220,6 +1238,8 @@ public class AreaCLIManager {
case "denyNoteblockJukebox": return land.denyNoteblockJukebox;
case "denyLead": return land.denyLead;
case "denyCropHarvest": return land.denyCropHarvest;
case "denyFarmlandTrample": return land.denyFarmlandTrample;
case "denyEnderTeleport": return land.denyEnderTeleport;
case "denyWoolShear": return land.denyWoolShear;
case "denyAnimalFeeding": return land.denyAnimalFeeding;
case "denyGlowing": return land.denyGlowing;
+12 -1
View File
@@ -498,7 +498,8 @@ public class AreaGUIManager implements Listener {
{"农作物收获", "denyCropHarvest"}, {"剪切羊毛", "denyWoolShear"}, {"投喂动物", "denyAnimalFeeding"},
{"攻击生物", "denyMobAttack"},
{"禁止编辑告示牌", "denySignEdit"},
{"玩家发光", "denyGlowing"}, {"传送", "allowTeleport"}, {"和平模式", "peaceMode"}
{"玩家发光", "denyGlowing"}, {"传送", "allowTeleport"}, {"和平模式", "peaceMode"},
{"耕地破坏", "denyFarmlandTrample"}, {"末影人传送", "denyEnderTeleport"}
};
for (String[] def : permDefs) {
@@ -529,6 +530,12 @@ public class AreaGUIManager implements Listener {
if (field.equals("denySignEdit")) {
name = landDefault ? "禁止编辑告示牌" : "允许编辑告示牌";
}
if (field.equals("denyFarmlandTrample")) {
name = landDefault ? "禁用耕地破坏" : "启用耕地破坏";
}
if (field.equals("denyEnderTeleport")) {
name = landDefault ? "禁止末影人传送" : "允许末影人传送";
}
// ★ 对于 allowPickup/allowDrop,enabled=true 表示"允许操作"(即 allow=true)
// 其他权限,enabled = true 表示"允许操作"(即 deny=false)
@@ -691,6 +698,8 @@ public class AreaGUIManager implements Listener {
perms.add(new PermEntry(land.denyMobAttack ? "禁止攻击生物" : "允许攻击生物", !land.denyMobAttack));
perms.add(new PermEntry(land.denySignEdit ? "禁止编辑告示牌" : "允许编辑告示牌", !land.denySignEdit));
perms.add(new PermEntry("玩家发光", !land.denyGlowing));
perms.add(new PermEntry(land.denyFarmlandTrample ? "禁用耕地破坏" : "启用耕地破坏", !land.denyFarmlandTrample));
perms.add(new PermEntry(land.denyEnderTeleport ? "禁止末影人传送" : "允许末影人传送", !land.denyEnderTeleport));
perms.add(new PermEntry("传送", land.allowVisitorTeleport));
perms.add(new PermEntry("和平模式", land.peaceMode));
perms.add(new PermEntry("公共建筑设施", land.isPublicBuilding));
@@ -752,6 +761,8 @@ public class AreaGUIManager implements Listener {
case "禁止攻击生物": case "允许攻击生物": land.denyMobAttack = !land.denyMobAttack; break;
case "禁止编辑告示牌": case "允许编辑告示牌": land.denySignEdit = !land.denySignEdit; break;
case "玩家发光": land.denyGlowing = !land.denyGlowing; break;
case "禁用耕地破坏": case "启用耕地破坏": land.denyFarmlandTrample = !land.denyFarmlandTrample; break;
case "禁止末影人传送": case "允许末影人传送": land.denyEnderTeleport = !land.denyEnderTeleport; break;
case "传送": land.allowVisitorTeleport = !land.allowVisitorTeleport; break;
case "和平模式": land.peaceMode = !land.peaceMode; break;
case "公共建筑设施": land.isPublicBuilding = !land.isPublicBuilding; break;
+56 -3
View File
@@ -1220,6 +1220,8 @@ public class AreaProtection implements Listener {
try { ac.denyNoteblockJukebox = rs.getInt("deny_noteblock_jukebox") == 1; } catch (Exception ignored) {}
try { ac.denyLead = rs.getInt("deny_lead") == 1; } catch (Exception ignored) {}
try { ac.denyCropHarvest = rs.getInt("deny_crop_harvest") == 1; } catch (Exception ignored) {}
try { ac.denyFarmlandTrample = rs.getInt("deny_farmland_trample") == 1; } catch (Exception ignored) {}
try { ac.denyEnderTeleport = rs.getInt("deny_ender_teleport") == 1; } catch (Exception ignored) {}
try { ac.denyWoolShear = rs.getInt("deny_wool_shear") == 1; } catch (Exception ignored) {}
try { ac.denyAnimalFeeding = rs.getInt("deny_animal_feeding") == 1; } catch (Exception ignored) {}
try { ac.denyContainer = rs.getInt("deny_container") == 1; } catch (Exception ignored) {}
@@ -1496,6 +1498,8 @@ public class AreaProtection implements Listener {
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_noteblock_jukebox INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_lead INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_crop_harvest INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_farmland_trample INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_ender_teleport INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_wool_shear INTEGER DEFAULT 0"); } catch (Exception ignored) {}
try { stmt.executeUpdate("ALTER TABLE area_lands ADD COLUMN deny_animal_feeding INTEGER DEFAULT 0"); } catch (Exception ignored) {}
// ★ 传送点列
@@ -2882,6 +2886,8 @@ public class AreaProtection implements Listener {
case "denyNoteblockJukebox": return ac.denyNoteblockJukebox;
case "denyLead": return ac.denyLead;
case "denyCropHarvest": return ac.denyCropHarvest;
case "denyFarmlandTrample": return ac.denyFarmlandTrample;
case "denyEnderTeleport": return ac.denyEnderTeleport;
case "denyWoolShear": return ac.denyWoolShear;
case "denyAnimalFeeding": return ac.denyAnimalFeeding;
case "denyMobAttack": return ac.denyMobAttack;
@@ -5684,6 +5690,47 @@ public class AreaProtection implements Listener {
}
}
// ★ 耕地破坏(玩家在耕地上跳跃/掉落时触发)
@EventHandler
public void onFarmlandTrample(PlayerInteractEvent e) {
if (e.getAction() != Action.PHYSICAL) return;
Block block = e.getClickedBlock();
if (block == null || block.getType() != Material.FARMLAND) return;
Player p = e.getPlayer();
AreaConfig ac = getArea(
p.getWorld().getName(),
block.getX(), block.getY(), block.getZ());
if (ac != null && getEffectiveDeny(p, ac, "denyFarmlandTrample")) {
e.setCancelled(true);
}
}
// ★ 末影人传送控制(禁止末影人传送到领地内或从领地内传送走)
@EventHandler
public void onEnderTeleport(EntityTeleportEvent e) {
if (!e.getEntityType().name().equals("ENDERMAN")) return;
Location from = e.getFrom();
Location to = e.getTo();
// 检查起点是否在禁止末影人传送的领地内
if (from != null) {
AreaConfig fromAc = getArea(from.getWorld().getName(),
from.getBlockX(), from.getBlockY(), from.getBlockZ());
if (fromAc != null && fromAc.denyEnderTeleport) {
e.setCancelled(true);
return;
}
}
// 检查终点是否在禁止末影人传送的领地内
if (to != null) {
AreaConfig toAc = getArea(to.getWorld().getName(),
to.getBlockX(), to.getBlockY(), to.getBlockZ());
if (toAc != null && toAc.denyEnderTeleport) {
e.setCancelled(true);
return;
}
}
}
// ★ 判断方块是否为农作物
private boolean isCropBlock(Material mat) {
String name = mat.name();
@@ -8752,8 +8799,8 @@ public class AreaProtection implements Listener {
+ "confiscate_msg, enable_announce, announce_template, txt_content, created_at, "
+ "deny_thrown_projectiles, deny_glowing, deny_redstone_interaction, deny_door_interaction, "
+ "deny_noteblock_jukebox, deny_lead, deny_crop_harvest, deny_wool_shear, deny_animal_feeding, "
+ "warp_x, warp_y, warp_z, warp_yaw, warp_pitch, warp_world, deny_container, deny_mob_attack, deny_sign_edit, is_public_building, allow_visitor_teleport) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+ "warp_x, warp_y, warp_z, warp_yaw, warp_pitch, warp_world, deny_container, deny_mob_attack, deny_sign_edit, is_public_building, allow_visitor_teleport, deny_farmland_trample, deny_ender_teleport) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
+ "ON CONFLICT(name) DO UPDATE SET "
+ "owner=excluded.owner, world=excluded.world, x1=excluded.x1, z1=excluded.z1, x2=excluded.x2, z2=excluded.z2, y_min=excluded.y_min, y_max=excluded.y_max, "
+ "confiscate_items=excluded.confiscate_items, deny_use_items=excluded.deny_use_items, give_effects=excluded.give_effects, clear_effects=excluded.clear_effects, clear_all_bad=excluded.clear_all_bad, "
@@ -8766,7 +8813,7 @@ public class AreaProtection implements Listener {
+ "confiscate_msg=excluded.confiscate_msg, enable_announce=excluded.enable_announce, announce_template=excluded.announce_template, txt_content=excluded.txt_content, created_at=excluded.created_at, "
+ "deny_thrown_projectiles=excluded.deny_thrown_projectiles, deny_glowing=excluded.deny_glowing, deny_redstone_interaction=excluded.deny_redstone_interaction, deny_door_interaction=excluded.deny_door_interaction, "
+ "deny_noteblock_jukebox=excluded.deny_noteblock_jukebox, deny_lead=excluded.deny_lead, deny_crop_harvest=excluded.deny_crop_harvest, deny_wool_shear=excluded.deny_wool_shear, deny_animal_feeding=excluded.deny_animal_feeding, "
+ "warp_x=excluded.warp_x, warp_y=excluded.warp_y, warp_z=excluded.warp_z, warp_yaw=excluded.warp_yaw, warp_pitch=excluded.warp_pitch, warp_world=excluded.warp_world, deny_container=excluded.deny_container, deny_mob_attack=excluded.deny_mob_attack, deny_sign_edit=excluded.deny_sign_edit, is_public_building=excluded.is_public_building, allow_visitor_teleport=excluded.allow_visitor_teleport");
+ "warp_x=excluded.warp_x, warp_y=excluded.warp_y, warp_z=excluded.warp_z, warp_yaw=excluded.warp_yaw, warp_pitch=excluded.warp_pitch, warp_world=excluded.warp_world, deny_container=excluded.deny_container, deny_mob_attack=excluded.deny_mob_attack, deny_sign_edit=excluded.deny_sign_edit, is_public_building=excluded.is_public_building, allow_visitor_teleport=excluded.allow_visitor_teleport, deny_farmland_trample=excluded.deny_farmland_trample, deny_ender_teleport=excluded.deny_ender_teleport");
stmt.setString(1, ac.name);
stmt.setString(2, ac.owner != null ? ac.owner : "");
@@ -8835,6 +8882,8 @@ public class AreaProtection implements Listener {
stmt.setInt(65, ac.denySignEdit ? 1 : 0);
stmt.setInt(66, ac.isPublicBuilding ? 1 : 0);
stmt.setInt(67, ac.allowVisitorTeleport ? 1 : 0);
stmt.setInt(68, ac.denyFarmlandTrample ? 1 : 0);
stmt.setInt(69, ac.denyEnderTeleport ? 1 : 0);
stmt.executeUpdate();
stmt.close();
// ★ 领地设置变更:立即触发PHP同步(防抖10秒)
@@ -11434,6 +11483,10 @@ public class AreaProtection implements Listener {
public boolean denyLead = false;
// ★ 农作物状态检测(播种&收获)
public boolean denyCropHarvest = false;
// ★ 耕地破坏(玩家跳跃踩踏耕地 → 变为泥土)
public boolean denyFarmlandTrample = false;
// ★ 末影人传送控制
public boolean denyEnderTeleport = false;
// ★ 采集羊毛和乐魂挽具
public boolean denyWoolShear = false;
// ★ 投喂动物
+38 -4
View File
@@ -2355,19 +2355,53 @@ public class DatabaseManager {
/** 查询某坐标最近的容器记录(按时间倒序) */
public List<Map<String, Object>> getLandContainerLogAt(
String world, int x, int y, int z, int limit) {
return getLandContainerLogAt(world, x, y, z, limit, -1);
}
/** 查询某坐标指定天数前的容器记录(daysAgo=0今天,1昨天,-1所有) */
public List<Map<String, Object>> getLandContainerLogAt(
String world, int x, int y, int z, int limit, int daysAgo) {
List<Map<String, Object>> list = new ArrayList<>();
try {
PreparedStatement ps = db.prepareStatement(
StringBuilder sql = new StringBuilder(
"SELECT time, player_name, action, container_type,"
+ " detail, amount"
+ " FROM land_container_log"
+ " WHERE world=? AND x=? AND y=? AND z=?"
+ " ORDER BY time DESC LIMIT ?");
+ " WHERE world=? AND x=? AND y=? AND z=?");
if (daysAgo >= 0) {
// 计算当天起始和结束毫秒时间戳
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
cal.add(java.util.Calendar.DAY_OF_YEAR, -daysAgo);
long dayStart = cal.getTimeInMillis();
cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
long dayEnd = cal.getTimeInMillis();
sql.append(" AND time >= ? AND time < ?");
}
sql.append(" ORDER BY time DESC LIMIT ?");
PreparedStatement ps = db.prepareStatement(sql.toString());
ps.setString(1, world);
ps.setInt(2, x);
ps.setInt(3, y);
ps.setInt(4, z);
ps.setInt(5, limit > 0 ? limit : 20);
int idx = 5;
if (daysAgo >= 0) {
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
cal.set(java.util.Calendar.MINUTE, 0);
cal.set(java.util.Calendar.SECOND, 0);
cal.set(java.util.Calendar.MILLISECOND, 0);
cal.add(java.util.Calendar.DAY_OF_YEAR, -daysAgo);
long dayStart = cal.getTimeInMillis();
cal.add(java.util.Calendar.DAY_OF_YEAR, 1);
long dayEnd = cal.getTimeInMillis();
ps.setLong(idx++, dayStart);
ps.setLong(idx++, dayEnd);
}
ps.setInt(idx, limit > 0 ? limit : 20);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
Map<String, Object> row =
@@ -293,6 +293,10 @@ public class LandRecordManager implements Listener {
}
private void queryAndPrint(Player p, Location loc) {
queryAndPrint(p, loc, 0);
}
private void queryAndPrint(Player p, Location loc, int page) {
String world = loc.getWorld().getName();
int x = loc.getBlockX(), y = loc.getBlockY(),
z = loc.getBlockZ();
@@ -300,13 +304,19 @@ public class LandRecordManager implements Listener {
List<Map<String, Object>> blocks =
plugin.getDb().getLandBlockLogAt(
world, x, y, z, QUERY_LIMIT);
// 按天分页:page=0今日,1昨日,2前日...
List<Map<String, Object>> containers =
plugin.getDb().getLandContainerLogAt(
world, x, y, z, QUERY_LIMIT);
world, x, y, z, QUERY_LIMIT, page);
if (blocks.isEmpty() && containers.isEmpty()) {
if (page > 0) {
p.sendMessage("§6§l[回声碎片] §e坐标 ("
+ x + "," + y + "," + z + ") 第" + (page + 1) + "页无记录");
} else {
p.sendMessage("§6§l[回声碎片] §f坐标 ("
+ x + "," + y + "," + z + ") 暂无领地记录");
}
return;
}
@@ -319,19 +329,18 @@ public class LandRecordManager implements Listener {
if ("take".equals(r.get("action")) || "put".equals(r.get("action"))) {
materials.add((String) r.get("detail"));
}
// 容器类型(如 CHEST)也要翻译
String ct = (String) r.get("container_type");
if (ct != null && !ct.isEmpty()) {
materials.add(ct);
}
}
final int currentPage = page;
// 异步批量翻译
MaterialTranslator.translateBatch(materials)
.thenAccept(translations -> {
// 回到主线程发送消息
plugin.getServer().getScheduler().runTask(plugin, () -> {
printResults(p, x, y, z, blocks, containers, translations);
printResults(p, x, y, z, blocks, containers, translations, currentPage);
});
});
}
@@ -340,6 +349,15 @@ public class LandRecordManager implements Listener {
List<Map<String, Object>> blocks,
List<Map<String, Object>> containers,
Map<String, String> translations) {
printResults(p, x, y, z, blocks, containers, translations, 0);
}
private void printResults(Player p, int x, int y, int z,
List<Map<String, Object>> blocks,
List<Map<String, Object>> containers,
Map<String, String> translations,
int page) {
String pageLabel = page == 0 ? "今日" : (page == 1 ? "昨日" : (page + 1) + "日前");
p.sendMessage("§6§l[回声碎片] §e坐标 ("
+ x + "," + y + "," + z + ") 的记录:");
@@ -368,7 +386,6 @@ public class LandRecordManager implements Listener {
.append(" §f").append(r.get("player_name"))
.append(" ").append(act)
.append(" §e").append(mat).append(" §a").append(zh);
// ★ 告示牌内容显示
String detail = (String) r.get("detail");
if (detail != null && !detail.isEmpty()
&& ("sign_place".equals(action) || "sign_edit".equals(action))) {
@@ -379,7 +396,7 @@ public class LandRecordManager implements Listener {
}
if (!containers.isEmpty()) {
p.sendMessage("§b— 容器记录 —");
p.sendMessage("§b— 容器记录 §7(" + pageLabel + ")—");
for (Map<String, Object> r : containers) {
String act = (String) r.get("action");
if ("open".equals(act)) {
@@ -404,6 +421,8 @@ public class LandRecordManager implements Listener {
+ " §7x" + r.get("amount"));
}
}
// 分页提示
p.sendMessage(" §7使用 §e/landrec log " + (page + 2) + " §7查看前一日记录");
}
}
@@ -421,7 +440,7 @@ public class LandRecordManager implements Listener {
}
String sub = args[0];
if (sub.equalsIgnoreCase("give")) {
// 发放权限:给自己(self)任意玩家可发;发给他人需 OP 或领地管理员
// 发放权限...
boolean isOp = sender.isOp();
boolean isAreaAdmin = (sender instanceof Player)
&& plugin.areaProtection.isAreaAdmin((Player) sender);
@@ -448,6 +467,30 @@ public class LandRecordManager implements Listener {
sender.sendMessage("§a§l[回声碎片] §f已发放回声碎片给 " + target.getName());
return true;
}
if (sub.equalsIgnoreCase("log")) {
if (!(sender instanceof Player)) {
sender.sendMessage("§c§l[回声碎片] §f此命令仅限玩家使用");
return true;
}
Player p = (Player) sender;
int page = 0; // 默认今日
if (args.length >= 2) {
try {
page = Math.max(0, Integer.parseInt(args[1]) - 1);
} catch (NumberFormatException ignored) {
sender.sendMessage("§c§l[回声碎片] §f页码格式错误");
return true;
}
}
// 取玩家准心对准的方块
Block target = p.getTargetBlockExact(6);
if (target == null || target.getType() == Material.AIR) {
sender.sendMessage("§c§l[回声碎片] §f你面前没有可查询的方块或容器");
return true;
}
queryAndPrint(p, target.getLocation(), page);
return true;
}
sendHelp(sender);
return true;
}
@@ -456,6 +499,8 @@ public class LandRecordManager implements Listener {
sender.sendMessage("§6§l[回声碎片] §e指令:");
sender.sendMessage(" §7/landrec give §f- 给自己发放一枚回声碎片");
sender.sendMessage(" §7/landrec give <玩家> §f- 向他人发放(需 OP/领地管理员)");
sender.sendMessage(" §7手持回声碎片右键/左键方块或容器 §f- 查看该处记录");
sender.sendMessage(" §7/landrec log §f- 查看当前方块今日容器记录");
sender.sendMessage(" §7/landrec log <页码> §f- 查看指定日期的容器记录(1=今日 2=昨日 ...)");
sender.sendMessage(" §7手持回声碎片右键/左键方块或容器 §f- 查看该处今日记录");
}
}