2.2.2-1.20.4
可以通过配置文件修改方块生成的范围
This commit is contained in:
@@ -23,7 +23,7 @@ import java.util.UUID;
|
||||
* <p>这些命令在新模式下会与GameStateManager交互,以正确管理游戏状态。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class AdminCommands implements CommandExecutor {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.UUID;
|
||||
* <p>此监听器与GameStateManager协作,确保游戏规则正确执行。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class BlockBreakListener implements Listener {
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.bukkit.entity.Player;
|
||||
* 与旧模式不同,此命令不再显示生命方块的具体位置,而是提供当前游戏状态信息。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class CheckLifeBlocksCommand implements CommandExecutor {
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.nio.charset.StandardCharsets;
|
||||
* </ul>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version -1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class ConfigManager {
|
||||
@@ -323,6 +323,24 @@ public class ConfigManager {
|
||||
return getConfig().getBoolean("protection.protect_from_pistons", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取方块生成范围(以玩家为中心的半径)
|
||||
*
|
||||
* @return 生成范围(方块),默认为5
|
||||
*/
|
||||
public int getSpreadRange() {
|
||||
return getConfig().getInt("game.spread_range", 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取方块生成距离玩家的最小距离
|
||||
*
|
||||
* @return 最小距离(方块),默认为2
|
||||
*/
|
||||
public int getMinDistance() {
|
||||
return getConfig().getInt("game.min_distance", 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 命令启用配置获取方法
|
||||
|
||||
@@ -45,7 +45,7 @@ import java.util.UUID;
|
||||
* </ul>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version -1.20.4
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class GameStateManager {
|
||||
@@ -253,7 +253,8 @@ public class GameStateManager {
|
||||
Material color = playerColors.get(player.getUniqueId());
|
||||
ConfigManager config = plugin.getConfigManager();
|
||||
int blockAmount = 5; // 使用固定值,因为配置已移除
|
||||
int spreadRange = 5; // 使用固定值,因为配置已移除
|
||||
int spreadRange = config.getSpreadRange(); // 从配置获取范围
|
||||
int minDistance = config.getMinDistance(); // 从配置获取最小距离
|
||||
|
||||
List<Location> blocks = new ArrayList<>();
|
||||
int blocksPlaced = 0;
|
||||
@@ -266,6 +267,13 @@ public class GameStateManager {
|
||||
int x = random.nextInt(spreadRange * 2 + 1) - spreadRange;
|
||||
int z = random.nextInt(spreadRange * 2 + 1) - spreadRange;
|
||||
|
||||
// 检查与玩家的距离是否满足最小距离要求
|
||||
double distance = Math.sqrt(x * x + z * z);
|
||||
if (distance < minDistance) {
|
||||
attempts++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Location testLoc = center.clone().add(x, 0, z);
|
||||
World world = testLoc.getWorld();
|
||||
if (world == null) continue;
|
||||
@@ -608,6 +616,14 @@ public class GameStateManager {
|
||||
* 重置游戏
|
||||
*/
|
||||
public void resetGame() {
|
||||
// 删除世界中所有未被破坏的生命方块(新模式)
|
||||
removeGameBlocksFromWorld();
|
||||
|
||||
// 删除旧模式的生命方块
|
||||
if (plugin.getBlockManager() != null) {
|
||||
plugin.getBlockManager().resetGameBlocks();
|
||||
}
|
||||
|
||||
// 清空所有数据
|
||||
playerColors.clear();
|
||||
playerBlocks.clear();
|
||||
@@ -631,6 +647,33 @@ public class GameStateManager {
|
||||
setCurrentState(GameState.WAITING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从世界中删除所有游戏生命方块
|
||||
*/
|
||||
private void removeGameBlocksFromWorld() {
|
||||
// 遍历所有玩家的生命方块位置并将其设置为空气
|
||||
for (List<Location> blocks : playerBlocks.values()) {
|
||||
for (Location location : blocks) {
|
||||
if (location.getWorld() != null) {
|
||||
Block block = location.getBlock();
|
||||
// 只删除生命方块(彩色羊毛、玻璃或混凝土)
|
||||
if (isLifeBlockMaterial(block.getType())) {
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查材料是否为生命方块材料
|
||||
*/
|
||||
private boolean isLifeBlockMaterial(Material material) {
|
||||
return material.name().endsWith("_WOOL") ||
|
||||
material.name().endsWith("_STAINED_GLASS") ||
|
||||
material.name().endsWith("_CONCRETE");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取玩家剩余方块数量
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.UUID;
|
||||
* </pre>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0
|
||||
* @version
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class LifeSystem {
|
||||
|
||||
@@ -18,7 +18,7 @@ import org.bukkit.entity.Player;
|
||||
* <p>这些命令仅允许服务器管理员(OP)执行,用于控制PlayerBlockLife游戏的生命周期。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class PBLCommands implements CommandExecutor {
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.logging.Level;
|
||||
* </ul>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PlayerBlockLife extends JavaPlugin {
|
||||
|
||||
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <p>使用并发安全的数据结构确保多线程环境下的数据一致性。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0
|
||||
* @version 2.2.2
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PlayerBlockManager {
|
||||
@@ -67,8 +67,10 @@ public class PlayerBlockManager {
|
||||
ConfigManager config = plugin.getConfigManager();
|
||||
boolean requireOpenSky = true; // 使用默认值,因为配置已移除
|
||||
int maxAttempts = 50; // 使用默认值,因为配置已移除
|
||||
int spreadRange = config.getSpreadRange(); // 从配置获取范围
|
||||
int minDistance = config.getMinDistance(); // 从配置获取最小距离
|
||||
|
||||
return generateLifeBlocksForPlayer(player, 5, 5, requireOpenSky, maxAttempts);
|
||||
return generateLifeBlocksForPlayer(player, 5, spreadRange, minDistance, requireOpenSky, maxAttempts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,14 +98,15 @@ public class PlayerBlockManager {
|
||||
*
|
||||
* @param player 目标玩家
|
||||
* @param blockAmount 要生成的方块数量
|
||||
* @param spreadRange 生成范围(以玩家为中心的正方形边长的一半)
|
||||
* @param spreadRange 生成范围(以玩家为中心的半径)
|
||||
* @param minDistance 生成方块距离玩家的最小距离
|
||||
* @param requireOpenSky 是否需要开阔天空(上方无方块覆盖)
|
||||
* @param maxAttempts 寻找合适位置的最大尝试次数
|
||||
* @return 生成成功返回true,失败返回false
|
||||
* @see SkinManager#isSkinLoaded(UUID)
|
||||
* @see SkinManager#getSkinFromSkinsRestorer(Player)
|
||||
*/
|
||||
public boolean generateLifeBlocksForPlayer(Player player, int blockAmount, int spreadRange, boolean requireOpenSky, int maxAttempts) {
|
||||
public boolean generateLifeBlocksForPlayer(Player player, int blockAmount, int spreadRange, int minDistance, boolean requireOpenSky, int maxAttempts) {
|
||||
UUID playerId = player.getUniqueId();
|
||||
String playerName = player.getName();
|
||||
|
||||
@@ -123,7 +126,7 @@ public class PlayerBlockManager {
|
||||
|
||||
// 尝试生成指定数量的方块
|
||||
while (blocksPlaced < blockAmount && attempts < maxAttempts) {
|
||||
Location blockLoc = findSurfaceLocation(player.getLocation(), spreadRange, requireOpenSky);
|
||||
Location blockLoc = findSurfaceLocation(player.getLocation(), spreadRange, minDistance, requireOpenSky);
|
||||
attempts++;
|
||||
|
||||
if (blockLoc != null && placePlayerHead(blockLoc, playerId, playerName)) {
|
||||
@@ -148,11 +151,18 @@ public class PlayerBlockManager {
|
||||
/**
|
||||
* 寻找地表位置(放宽条件,只要是露天地面就可以)
|
||||
*/
|
||||
private Location findSurfaceLocation(Location center, int spreadRange, boolean requireOpenSky) {
|
||||
private Location findSurfaceLocation(Location center, int spreadRange, int minDistance, boolean requireOpenSky) {
|
||||
for (int i = 0; i < 20; i++) { // 增加尝试次数
|
||||
int x = random.nextInt(spreadRange * 2 + 1) - spreadRange;
|
||||
int z = random.nextInt(spreadRange * 2 + 1) - spreadRange;
|
||||
|
||||
// 检查与玩家的距离是否满足最小距离要求
|
||||
double distance = Math.sqrt(x * x + z * z);
|
||||
if (distance < minDistance) {
|
||||
// 如果距离太近,重新生成坐标
|
||||
continue;
|
||||
}
|
||||
|
||||
// 以玩家坐标为中心,但高度从世界最高点开始寻找
|
||||
Location testLoc = center.clone().add(x, 0, z);
|
||||
World world = testLoc.getWorld();
|
||||
@@ -755,6 +765,30 @@ public class PlayerBlockManager {
|
||||
return nearest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置游戏时删除所有未被破坏的生命方块
|
||||
*/
|
||||
public void resetGameBlocks() {
|
||||
// 遍历所有生命方块位置并将其设置为空气
|
||||
for (Location location : blockOwners.keySet()) {
|
||||
if (location.getWorld() != null) {
|
||||
Block block = location.getBlock();
|
||||
// 只删除玩家头颅方块
|
||||
if (block.getType() == Material.PLAYER_HEAD || block.getType() == Material.PLAYER_WALL_HEAD) {
|
||||
block.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清空内部数据结构
|
||||
playerBlocks.clear();
|
||||
blockOwners.clear();
|
||||
playerBlockTypes.clear();
|
||||
|
||||
// 保存数据更新
|
||||
saveData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有生命方块的统计信息
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.util.UUID;
|
||||
* <p>此监听器与GameStateManager协作,确保玩家正确加入PlayerBlockLife游戏模式。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PlayerJoinListener implements Listener {
|
||||
@@ -90,7 +90,7 @@ public class PlayerJoinListener implements Listener {
|
||||
|
||||
// 调用方块管理器生成方块
|
||||
boolean success = plugin.getBlockManager().generateLifeBlocksForPlayer(
|
||||
player, 5, 5, requireOpenSky, maxAttempts
|
||||
player, 5, config.getSpreadRange(), config.getMinDistance(), requireOpenSky, maxAttempts
|
||||
);
|
||||
|
||||
if (success) {
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
* 其生命方块状态,因为方块位置信息仅在服务器运行期间维护。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class PlayerQuitListener implements Listener {
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.bukkit.entity.Player;
|
||||
* 玩家应等待管理员使用 /PlayerBlockLife start 命令开始游戏。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0-1.20.4
|
||||
* @version 2.2.2-1.20.4
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class SetLifeBlocksCommand implements CommandExecutor {
|
||||
|
||||
@@ -52,7 +52,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <p>皮肤缓存默认保留7天,过期后自动重新获取。</p>
|
||||
*
|
||||
* @author xiaobai
|
||||
* @version 2.2.0
|
||||
* @version 2.2.2
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class SkinManager {
|
||||
|
||||
Reference in New Issue
Block a user