1 Commits
2.2.1 ... 2.2.2

Author SHA1 Message Date
xiaobai
032ef02ec8 2.2.2-1.20.4
可以通过配置文件修改方块生成的范围
2026-02-16 19:00:54 +08:00
33 changed files with 141 additions and 26 deletions

View File

@@ -0,0 +1,8 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavadocReference" enabled="true" level="ERROR" enabled_by_default="true">
<option name="REPORT_INACCESSIBLE" value="false" />
</inspection_tool>
</profile>
</component>

View File

@@ -4,7 +4,7 @@ plugins {
}
group = 'com.playerblocklife'
version = '2.2.0-1.20.4'
version = '2.2.2-1.20.4'
sourceCompatibility = 17
targetCompatibility = 17

Binary file not shown.

Binary file not shown.

View File

@@ -9,6 +9,12 @@ game:
become_spectator: true
# 是否启用生命值系统
health_system: true
# 方块生成设置
# 生成方块范围(以玩家为中心的半径)
spread_range: 5
# 生成方块距离玩家的最小距离
min_distance: 2
# 广播设置
broadcast:

View File

@@ -1,5 +1,5 @@
name: PlayerBlockLife
version: 2.2.0-1.20.4
version: 2.2.2-1.20.4
main: com.playerblocklife.PlayerBlockLife
api-version: 1.20
author: xiaobai

View File

@@ -1,4 +1,4 @@
Manifest-Version: 1.0
Implementation-Version: 2.2.0-alpha-1.20.4
Implementation-Version: 2.2.1-1.20.4
Main-Class: com.playerblocklife.PlayerBlockLife

View File

@@ -1,4 +1,4 @@
Manifest-Version: 1.0
Implementation-Version: 2.2.0-1.20.4
Implementation-Version: 2.2.2-1.20.4
Main-Class: com.playerblocklife.PlayerBlockLife

View File

@@ -5,5 +5,5 @@ org.gradle.caching=true
org.gradle.daemon=true
# ????
pluginVersion=2.2.0-1.20.4
pluginVersion=2.2.2-1.20.4
mcVersion=1.20.4

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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);
}
// 命令启用配置获取方法

View File

@@ -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");
}
/**
* 获取玩家剩余方块数量
*/

View File

@@ -33,7 +33,7 @@ import java.util.UUID;
* </pre>
*
* @author xiaobai
* @version 2.2.0
* @version
* @since 1.0.0
*/
public class LifeSystem {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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();
}
/**
* 获取所有生命方块的统计信息
*/

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -9,6 +9,12 @@ game:
become_spectator: true
# 是否启用生命值系统
health_system: true
# 方块生成设置
# 生成方块范围(以玩家为中心的半径)
spread_range: 5
# 生成方块距离玩家的最小距离
min_distance: 2
# 广播设置
broadcast:

View File

@@ -1,5 +1,5 @@
name: PlayerBlockLife
version: 2.2.0-1.20.4
version: 2.2.2-1.20.4
main: com.playerblocklife.PlayerBlockLife
api-version: 1.20
author: xiaobai