diff --git a/gradle.properties b/gradle.properties index 645052c..dd9a168 100644 --- a/gradle.properties +++ b/gradle.properties @@ -192,4 +192,4 @@ curseForgeRelations = # This is meant to be set in $HOME/.gradle/gradle.properties. # ideaCheckSpotlessOnBuild = true -version = 3.0 +version = 3.6 diff --git a/src/main/java/com/CatFish/BetterWater/BetterWater.java b/src/main/java/com/CatFish/BetterWater/BetterWater.java index 44f1439..6899497 100644 --- a/src/main/java/com/CatFish/BetterWater/BetterWater.java +++ b/src/main/java/com/CatFish/BetterWater/BetterWater.java @@ -19,7 +19,6 @@ import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; - import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; @@ -30,52 +29,26 @@ import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent; + @Mod(modid = "betterwater", name = "Better Water", version = "2.0", acceptedMinecraftVersions = "[1.7.10]") public class BetterWater { @Instance("betterwater") public static BetterWater instance; + // ========== 水区域检测所需变量 ========== + private static BiomeDictionary.Type[] validBiomeTypes = null; + private static BiomeDictionary.Type[] bannedBiomeTypes = null; + private static boolean regionCheckInitialized = false; + public static Logger logger = Logger.getLogger("betterwater"); - // 用于存储待处理的方块破坏事件(增加来源标记) private static final Queue pendingEvents = new LinkedList<>(); - // ========== 流体兼容性支持 ========== private static Set fluidBlocks = null; - // ========== 群系限制检测 ========== - private static BiomeDictionary.Type[] validBiomeTypes = null; - private static BiomeDictionary.Type[] bannedBiomeTypes = null; - private static boolean regionCheckInitialized = false; - - /** - * 初始化流体方块集合 - */ - private static void initFluidBlocks() { - if (fluidBlocks != null) return; - fluidBlocks = new HashSet<>(); - fluidBlocks.add(Blocks.water); - fluidBlocks.add(Blocks.flowing_water); - for (Fluid fluid : FluidRegistry.getRegisteredFluids().values()) { - Block block = fluid.getBlock(); - if (block != null) { - fluidBlocks.add(block); - } - } - if (BetterWaterConfig.debugMode) { - logger.info("Fluid blocks initialized: " + fluidBlocks.size() + " fluids registered."); - } - } - - public static boolean isFluidBlock(Block block) { - if (fluidBlocks == null) { - initFluidBlocks(); - } - return fluidBlocks.contains(block); - } + // 群系缓存(略,原样) - // ========== 群系检测方法 ========== private static synchronized void initRegionCheck() { if (regionCheckInitialized) return; validBiomeTypes = new BiomeDictionary.Type[BetterWaterConfig.validBiomeDictionary.length]; @@ -108,27 +81,42 @@ private static boolean containsBannedBiome(BiomeDictionary.Type[] currentTypes) } private static boolean isValidDim(int dim) { - for (int d : BetterWaterConfig.validDims) { - if (d == dim) return true; - } + for (int d : BetterWaterConfig.validDims) if (d == dim) return true; return false; } private static boolean isBannedDim(int dim) { - for (int d : BetterWaterConfig.bannedDims) { - if (d == dim) return true; - } + for (int d : BetterWaterConfig.bannedDims) if (d == dim) return true; return false; } private static boolean isOceanDim(int dim) { - for (int d : BetterWaterConfig.oceanDims) { - if (d == dim) return true; - } + for (int d : BetterWaterConfig.oceanDims) if (d == dim) return true; return false; } - public static boolean shouldGenerateSourceByRegion(World world, int x, int y, int z) { + private static void initFluidBlocks() { + if (fluidBlocks != null) return; + fluidBlocks = new HashSet<>(); + fluidBlocks.add(Blocks.water); + fluidBlocks.add(Blocks.flowing_water); + fluidBlocks.add(Blocks.lava); + fluidBlocks.add(Blocks.flowing_lava); + for (Fluid fluid : FluidRegistry.getRegisteredFluids().values()) { + Block block = fluid.getBlock(); + if (block != null) fluidBlocks.add(block); + } + if (BetterWaterConfig.debugMode) { + logger.info("Fluid blocks initialized: " + fluidBlocks.size() + " fluids registered."); + } + } + + public static boolean isFluidBlock(Block block) { + if (fluidBlocks == null) initFluidBlocks(); + return fluidBlocks.contains(block); + } + + private static boolean shouldGenerateWaterSourceByRegion(World world, int x, int y, int z) { if (!regionCheckInitialized) { initRegionCheck(); } @@ -156,29 +144,93 @@ public static boolean shouldGenerateSourceByRegion(World world, int x, int y, in return isValidDim(dim) && containsValidBiome(biomes); } + // ========== 区域判断(根据流体类型) ========== + private static boolean shouldGenerateSourceByRegion(World world, int x, int y, int z, boolean isLava) { + if (isLava) { + return shouldGenerateLavaSourceByRegion(world, x, y, z); + } else { + return shouldGenerateWaterSourceByRegion(world, x, y, z); + } + } + + public static boolean shouldGenerateSourceByRegion(World world, int x, int y, int z) { + return shouldGenerateSourceByRegion(world, x, y, z, false); + } + + private static boolean shouldGenerateLavaSourceByRegion(World world, int x, int y, int z) { + if (!BetterWaterConfig.lavaEnabled) return false; + if (!lavaRegionCheckInitialized) { + initLavaRegionCheck(); + } + int dim = world.provider.dimensionId; + + // 强制允许维度 + for (int d : BetterWaterConfig.lavaOceanDims) if (d == dim) return true; + + // 禁止维度 + for (int d : BetterWaterConfig.lavaBannedDims) if (d == dim) return false; + + // Y轴范围 + if (y < BetterWaterConfig.lavaLower || y > BetterWaterConfig.lavaUpper) return false; + + // 群系检测 + BiomeDictionary.Type[] biomes = BiomeDictionary.getTypesForBiome(world.getBiomeGenForCoords(x, z)); + // 禁止群系 + for (BiomeDictionary.Type banned : lavaBannedBiomeTypes) { + for (BiomeDictionary.Type current : biomes) if (current == banned) return false; + } + + if (BetterWaterConfig.lavaReverse) return true; + + // 有效群系 + for (BiomeDictionary.Type valid : lavaValidBiomeTypes) { + for (BiomeDictionary.Type current : biomes) if (current == valid) return true; + } + return false; + } + // 群系类型数组初始化(类似水的,需新增 lavaValidBiomeTypes 和 lavaBannedBiomeTypes) + private static BiomeDictionary.Type[] lavaValidBiomeTypes = null; + private static BiomeDictionary.Type[] lavaBannedBiomeTypes = null; + private static boolean lavaRegionCheckInitialized = false; + + private static synchronized void initLavaRegionCheck() { + if (lavaRegionCheckInitialized) return; + lavaValidBiomeTypes = new BiomeDictionary.Type[BetterWaterConfig.lavaValidBiomeDictionary.length]; + for (int i = 0; i < BetterWaterConfig.lavaValidBiomeDictionary.length; i++) { + lavaValidBiomeTypes[i] = BiomeDictionary.Type.getType(BetterWaterConfig.lavaValidBiomeDictionary[i]); + } + lavaBannedBiomeTypes = new BiomeDictionary.Type[BetterWaterConfig.lavaBannedBiomeDictionary.length]; + for (int i = 0; i < BetterWaterConfig.lavaBannedBiomeDictionary.length; i++) { + lavaBannedBiomeTypes[i] = BiomeDictionary.Type.getType(BetterWaterConfig.lavaBannedBiomeDictionary[i]); + } + lavaRegionCheckInitialized = true; + } + @EventHandler public void preInit(FMLPreInitializationEvent event) { BetterWaterConfig.init(event.getSuggestedConfigurationFile()); FMLCommonHandler.instance().bus().register(this); MinecraftForge.EVENT_BUS.register(this); - logger.info("Better Water mod v2.0 loaded!"); + logger.info("Better Water mod v2.0 loaded (with lava support)!"); } - @EventHandler - public void init(FMLInitializationEvent event) {} - - @EventHandler - public void postInit(FMLPostInitializationEvent event) {} + // init, postInit 省略 @SubscribeEvent public void onWorldTick(TickEvent.WorldTickEvent event) { if (event.phase != TickEvent.Phase.END) return; - synchronized (pendingEvents) { + Queue newQueue = new LinkedList<>(); while (!pendingEvents.isEmpty()) { PendingBreakEvent pending = pendingEvents.poll(); - processBlockBreak(pending); // 传入整个事件对象 + if (pending.delayTicks <= 0) { + processBlockBreak(pending); + } else { + pending.delayTicks--; + newQueue.add(pending); + } } + pendingEvents.addAll(newQueue); } } @@ -195,12 +247,18 @@ public void onFillBucket(FillBucketEvent event) { int z = target.blockZ; Block block = world.getBlock(x, y, z); + Block fluidType = null; if (block == Blocks.water && world.getBlockMetadata(x, y, z) == 0) { + fluidType = Blocks.water; + } else if (block == Blocks.lava && world.getBlockMetadata(x, y, z) == 0) { + fluidType = Blocks.lava; + } + if (fluidType != null) { synchronized (pendingEvents) { - pendingEvents.add(new PendingBreakEvent(world, x, y, z, true)); // 标记为桶取水 + pendingEvents.add(new PendingBreakEvent(world, x, y, z, true, fluidType)); } if (BetterWaterConfig.debugMode) { - logger.info(String.format("FillBucketEvent queued at [%d, %d, %d] (bucket)", x, y, z)); + logger.info(String.format("FillBucketEvent queued at [%d, %d, %d] for %s", x, y, z, fluidType.getLocalizedName())); } } } @@ -215,196 +273,233 @@ public void onBlockBreak(BlockEvent.BreakEvent event) { int y = event.y; int z = event.z; - int seaLevel = 63; - if (y < seaLevel - BetterWaterConfig.seaLevelRange || y > seaLevel + BetterWaterConfig.seaLevelRange) { - return; - } +// // 简单高度过滤(水海平面附近,岩浆默认不过滤高度,因为由区域检测控制) +// // 此处可保留水的过滤,岩浆的过滤在区域检测中进行 +// if (BetterWaterConfig.seaLevelRange >= 0) { +// int seaLevel = 63; +// if (y < seaLevel - BetterWaterConfig.seaLevelRange || y > seaLevel + BetterWaterConfig.seaLevelRange) { +// return; +// } +// } Block brokenBlock = event.block; if (!BetterWaterConfig.isBlockAffected(brokenBlock)) return; synchronized (pendingEvents) { - pendingEvents.add(new PendingBreakEvent(world, x, y, z, false)); // 标记为方块破坏 + pendingEvents.add(new PendingBreakEvent(world, x, y, z, false, null)); } } - /** - * 处理待办事件(区分来源) - */ private static void processBlockBreak(PendingBreakEvent event) { World world = event.world; int x = event.x; int y = event.y; int z = event.z; boolean fromBucket = event.fromBucket; + Block specifiedFluid = event.fluidType; // 桶事件指定流体,破坏事件为 null Block currentBlock = world.getBlock(x, y, z); - if (currentBlock != Blocks.air && currentBlock != Blocks.water && currentBlock != Blocks.flowing_water) { + if (currentBlock != Blocks.air && currentBlock != Blocks.water && currentBlock != Blocks.flowing_water + && currentBlock != Blocks.lava && currentBlock != Blocks.flowing_lava) { return; } - // ===== 桶取水事件:优先使用群系检测 ===== - if (fromBucket) { - if (shouldGenerateSourceByRegion(world, x, y, z)) { - world.setBlock(x, y, z, Blocks.water, 0, 3); + // 桶事件:优先尝试区域检测直接放置 + if (fromBucket && specifiedFluid != null) { + boolean isLava = (specifiedFluid == Blocks.lava || specifiedFluid == Blocks.flowing_lava); + if (shouldGenerateSourceByRegion(world, x, y, z, isLava)) { + world.setBlock(x, y, z, specifiedFluid == Blocks.lava ? Blocks.lava : Blocks.water, 0, 3); if (BetterWaterConfig.debugMode) { - logger.info(String.format("Placed water source at [%d, %d, %d] (bucket, region check)", x, y, z)); + logger.info(String.format("Placed %s source at [%d, %d, %d] (bucket, region check)", + isLava ? "lava" : "water", x, y, z)); } - placeFlowingWater(world, x, y, z); + placeFlowingFluid(world, x, y, z, specifiedFluid); return; } - // 未通过群系检测,则继续执行下面的水域检测 + // 未通过区域检测,继续水体检测 } - // ===== 水域检测(适用于破坏事件,以及未通过群系检测的桶事件) ===== - // 只检查水平相邻的流体(确保破坏点与水体同一水平面) - int[][] horizontalDirs = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 } }; - + // 水平方向检查相邻流体 + int[][] horizontalDirs = { {1,0,0}, {-1,0,0}, {0,0,1}, {0,0,-1} }; for (int[] dir : horizontalDirs) { int adjX = x + dir[0]; int adjY = y + dir[1]; int adjZ = z + dir[2]; - Block adjacentBlock = world.getBlock(adjX, adjY, adjZ); - if (isFluidBlock(adjacentBlock)) { - WaterDetectionResult result = detectConnectedWaterBody(world, adjX, adjY, adjZ); - - if (result.sourceCount >= BetterWaterConfig.waterBodyThreshold) { - world.setBlock(x, y, z, Blocks.water, 0, 3); - if (BetterWaterConfig.debugMode) { - logger.info(String.format("Placed water source at [%d, %d, %d]. Water body size: %d", - x, y, z, result.sourceCount)); - } - placeFlowingWater(world, x, y, z); - return; + if (!isFluidBlock(adjacentBlock)) continue; + + // 确定流体类型(水或岩浆) + boolean isLavaAdj = (adjacentBlock == Blocks.lava || adjacentBlock == Blocks.flowing_lava); + Block fluidType = isLavaAdj ? Blocks.lava : Blocks.water; + + // 如果来自桶事件且指定了流体,则只处理与该流体一致的相邻流体 + if (fromBucket && specifiedFluid != null && fluidType != specifiedFluid) continue; + + // 检测该流体连通体 + FluidDetectionResult result = detectConnectedFluidBody(world, adjX, adjY, adjZ, fluidType); + + int threshold = isLavaAdj ? BetterWaterConfig.lavaBodyThreshold : BetterWaterConfig.waterBodyThreshold; + if (result.sourceCount >= threshold) { + // 检查区域限制 + if (!shouldGenerateSourceByRegion(world, x, y, z, isLavaAdj)) continue; + + world.setBlock(x, y, z, fluidType, 0, 3); + if (BetterWaterConfig.debugMode) { + logger.info(String.format("Placed %s source at [%d, %d, %d]. Body size: %d", + isLavaAdj ? "lava" : "water", x, y, z, result.sourceCount)); } + placeFlowingFluid(world, x, y, z, fluidType); + return; } } } - private static void placeFlowingWater(World world, int x, int y, int z) { - int[][] directions = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, -1, 0 } }; + private static void placeFlowingFluid(World world, int x, int y, int z, Block fluidType) { + boolean shouldPlace = (fluidType == Blocks.lava) ? BetterWaterConfig.lavaAlwaysCheckAirBlocks : BetterWaterConfig.alwaysCheckAirBlocks; + if (!shouldPlace) return; + int[][] directions = { {1,0,0}, {-1,0,0}, {0,0,1}, {0,0,-1}, {0,-1,0} }; + Block flowingBlock = (fluidType == Blocks.lava) ? Blocks.flowing_lava : Blocks.flowing_water; for (int[] dir : directions) { int adjX = x + dir[0]; int adjY = y + dir[1]; int adjZ = z + dir[2]; - - Block adjacentBlock = world.getBlock(adjX, adjY, adjZ); - if (adjacentBlock == Blocks.air) { - world.setBlock(adjX, adjY, adjZ, Blocks.water, 1, 3); + if (world.getBlock(adjX, adjY, adjZ) == Blocks.air) { + world.setBlock(adjX, adjY, adjZ, flowingBlock, 1, 3); if (BetterWaterConfig.debugMode) { - logger.info(String.format("Placed flowing water (ID=1) at [%d, %d, %d] to trigger update", - adjX, adjY, adjZ)); + logger.info(String.format("Placed flowing %s at [%d, %d, %d]", + fluidType == Blocks.lava ? "lava" : "water", adjX, adjY, adjZ)); } } } } - public static WaterDetectionResult detectConnectedWaterBody(World world, int startX, int startY, int startZ) { - if (fluidBlocks == null) { - initFluidBlocks(); - } + // 通用流体检测(按类型) + public static FluidDetectionResult detectConnectedFluidBody(World world, int startX, int startY, int startZ, Block targetFluid) { + if (fluidBlocks == null) initFluidBlocks(); Queue queue = new LinkedList<>(); HashSet visited = new HashSet<>(); int sourceCount = 0; - int totalWaterCount = 0; + int totalCount = 0; - queue.add(new int[] { startX, startY, startZ }); + queue.add(new int[]{startX, startY, startZ}); visited.add(key(startX, startY, startZ)); - while (!queue.isEmpty() && totalWaterCount < BetterWaterConfig.maxBlocksToCheck) { + int maxBlocks = (targetFluid == Blocks.lava) ? BetterWaterConfig.lavaMaxBlocksToCheck : BetterWaterConfig.maxBlocksToCheck; + int searchRad = (targetFluid == Blocks.lava) ? BetterWaterConfig.lavaSearchRadius : BetterWaterConfig.searchRadius; + int vertRange = (targetFluid == Blocks.lava) ? BetterWaterConfig.lavaMaxVerticalRange : BetterWaterConfig.maxVerticalRange; + + while (!queue.isEmpty() && totalCount < maxBlocks) { int[] pos = queue.poll(); int x = pos[0]; int y = pos[1]; int z = pos[2]; Block block = world.getBlock(x, y, z); - if (!isFluidBlock(block)) { - continue; - } - - totalWaterCount++; + if (!isFluidBlock(block)) continue; + // 检查是否为目标流体类型(包括流动) + boolean matches = (targetFluid == Blocks.lava) ? + (block == Blocks.lava || block == Blocks.flowing_lava) : + (block == Blocks.water || block == Blocks.flowing_water); + if (!matches) continue; + + totalCount++; int metadata = world.getBlockMetadata(x, y, z); - - if (metadata == 0) { + if (metadata == 0) { // 源块 sourceCount++; - if (sourceCount >= BetterWaterConfig.waterBodyThreshold) { - return new WaterDetectionResult(sourceCount, totalWaterCount); + int threshold = (targetFluid == Blocks.lava) ? BetterWaterConfig.lavaBodyThreshold : BetterWaterConfig.waterBodyThreshold; + if (sourceCount >= threshold) { + return new FluidDetectionResult(sourceCount, totalCount); } } - int[][] directions = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, 1, 0 }, { 0, -1, 0 } }; - + int[][] directions = { {1,0,0}, {-1,0,0}, {0,0,1}, {0,0,-1}, {0,1,0}, {0,-1,0} }; for (int[] dir : directions) { int nx = x + dir[0]; int ny = y + dir[1]; int nz = z + dir[2]; - - if (Math.abs(nx - startX) > BetterWaterConfig.searchRadius - || Math.abs(nz - startZ) > BetterWaterConfig.searchRadius - || Math.abs(ny - startY) > BetterWaterConfig.maxVerticalRange) { - continue; - } - + if (Math.abs(nx - startX) > searchRad || Math.abs(nz - startZ) > searchRad || Math.abs(ny - startY) > vertRange) continue; String key = key(nx, ny, nz); if (!visited.contains(key)) { visited.add(key); - queue.add(new int[] { nx, ny, nz }); + queue.add(new int[]{nx, ny, nz}); } } } - - return new WaterDetectionResult(sourceCount, totalWaterCount); + return new FluidDetectionResult(sourceCount, totalCount); } - private static String key(int x, int y, int z) { - return x + ":" + y + ":" + z; + // 保留原有 detectConnectedWaterBody 作为兼容(可删除或重定向) + public static WaterDetectionResult detectConnectedWaterBody(World world, int startX, int startY, int startZ) { + FluidDetectionResult res = detectConnectedFluidBody(world, startX, startY, startZ, Blocks.water); + return new WaterDetectionResult(res.sourceCount, res.totalCount); } - public static WaterDetectionResult detectConnectedWaterBodyFromPos(World world, int x, int y, int z) { - Block block = world.getBlock(x, y, z); - if (isFluidBlock(block)) { - return detectConnectedWaterBody(world, x, y, z); - } - int[][] dirs = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, 1, 0 }, { 0, -1, 0 } }; - for (int[] dir : dirs) { - int nx = x + dir[0]; - int ny = y + dir[1]; - int nz = z + dir[2]; - Block nb = world.getBlock(nx, ny, nz); - if (isFluidBlock(nb)) { - return detectConnectedWaterBody(world, nx, ny, nz); - } - } - return new WaterDetectionResult(0, 0); - } + private static String key(int x, int y, int z) { return x + ":" + y + ":" + z; } - /** - * 待处理事件类(增加来源标记) - */ private static class PendingBreakEvent { final World world; final int x, y, z; - final boolean fromBucket; // true=桶取水, false=方块破坏 + final boolean fromBucket; + final Block fluidType; + int delayTicks; // 剩余等待 tick 数 - PendingBreakEvent(World world, int x, int y, int z, boolean fromBucket) { + PendingBreakEvent(World world, int x, int y, int z, boolean fromBucket, Block fluidType) { this.world = world; this.x = x; this.y = y; this.z = z; this.fromBucket = fromBucket; + this.fluidType = fluidType; + // 桶事件根据流体类型设置延迟,破坏事件延迟为 0(立即处理) + if (fromBucket && fluidType != null) { + this.delayTicks = (fluidType == Blocks.lava) ? + BetterWaterConfig.lavaProcessingDelayTicks : + BetterWaterConfig.processingDelayTicks; + } else { + this.delayTicks = 0; + } } } + public static class FluidDetectionResult { + public final int sourceCount; + public final int totalCount; + public FluidDetectionResult(int sourceCount, int totalCount) { + this.sourceCount = sourceCount; + this.totalCount = totalCount; + } + } + + // 保留 WaterDetectionResult 供外部调用 public static class WaterDetectionResult { public final int sourceCount; public final int totalWaterCount; - public WaterDetectionResult(int sourceCount, int totalWaterCount) { this.sourceCount = sourceCount; this.totalWaterCount = totalWaterCount; } } + /** + * 从指定位置检测相连水体(如果该位置不是流体,则检查相邻方块) + * 用于原版水的流动性钩子(BetterWaterHooks) + */ + public static WaterDetectionResult detectConnectedWaterBodyFromPos(World world, int x, int y, int z) { + Block block = world.getBlock(x, y, z); + if (isFluidBlock(block)) { + return detectConnectedWaterBody(world, x, y, z); + } + int[][] dirs = { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, { 0, 1, 0 }, { 0, -1, 0 } }; + for (int[] dir : dirs) { + int nx = x + dir[0]; + int ny = y + dir[1]; + int nz = z + dir[2]; + Block nb = world.getBlock(nx, ny, nz); + if (isFluidBlock(nb)) { + return detectConnectedWaterBody(world, nx, ny, nz); + } + } + return new WaterDetectionResult(0, 0); + } } diff --git a/src/main/java/com/CatFish/BetterWater/BetterWaterConfig.java b/src/main/java/com/CatFish/BetterWater/BetterWaterConfig.java index 476e922..f64ae60 100644 --- a/src/main/java/com/CatFish/BetterWater/BetterWaterConfig.java +++ b/src/main/java/com/CatFish/BetterWater/BetterWaterConfig.java @@ -1,42 +1,28 @@ package com.CatFish.BetterWater; import java.io.File; - import net.minecraftforge.common.config.Configuration; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; public class BetterWaterConfig { // ========== 主要开关 ========== - /** 是否启用模组(true=启用,false=禁用,恢复原版行为) */ public static boolean enabled = true; // ========== 水域检测参数 ========== - /** 连通完整水源的最小数量,达到此值才允许生成新水源(默认50) */ - public static int waterBodyThreshold = 50; - - /** 水平搜索半径(单位:方块),用于限制水域检测范围 */ + public static int waterBodyThreshold = 30; public static int searchRadius = 10; - - /** 垂直搜索范围(单位:方块),仅检测起始点上下各1格 */ - public static int maxVerticalRange = 1; - - /** 最大检测方块数,防止性能问题(默认1000) */ + public static int maxVerticalRange = 0; // 默认0,只检测同一水平面 public static int maxBlocksToCheck = 1000; // ========== 原版功能扩展参数 ========== - /** 海平面垂直范围,仅在该范围内生效(海平面63 ± seaLevelRange) */ - public static int seaLevelRange = 1; - - /** 方块破坏事件处理延迟(tick数),0为立即处理 */ + public static int seaLevelRange = 5; public static int processingDelayTicks = 1; - - /** 是否在生成水源时检查周围空气并放置流动水以触发更新 */ public static boolean alwaysCheckAirBlocks = true; - - /** 调试模式(输出详细日志) */ public static boolean debugMode = false; - // ========== 群系限制配置(来自 RegionalWater) ========== + // ========== 群系限制配置(水) ========== public static int[] validDims = {0}; public static int[] bannedDims = {-1, 1}; public static int[] oceanDims = {}; @@ -46,6 +32,25 @@ public class BetterWaterConfig { public static int waterLower = 0; public static int waterUpper = 255; + // ========== 岩浆专用配置 ========== + public static boolean lavaEnabled = true; + public static int lavaBodyThreshold = 10; + public static int lavaSearchRadius = 8; + public static int lavaMaxVerticalRange = 0; // 默认0,只检测同一水平面 + public static int lavaMaxBlocksToCheck = 500; + public static int lavaProcessingDelayTicks = 20; // 默认20 tick + public static boolean lavaAlwaysCheckAirBlocks = true; + + // 岩浆维度/群系限制 + public static int[] lavaValidDims = {-1}; + public static int[] lavaBannedDims = {0, 1}; + public static int[] lavaOceanDims = {}; + public static boolean lavaReverse = false; + public static String[] lavaValidBiomeDictionary = {"NETHER"}; + public static String[] lavaBannedBiomeDictionary = {}; + public static int lavaLower = 0; + public static int lavaUpper = 50; // 默认最高 Y=50 + private static Configuration config; public static void init(File configFile) { @@ -58,110 +63,70 @@ public static void load() { config.load(); // 主要开关 - enabled = config - .getBoolean("enabled", Configuration.CATEGORY_GENERAL, true, "Enable/disable the Better Water mod"); + enabled = config.getBoolean("enabled", Configuration.CATEGORY_GENERAL, true, "Enable/disable the Better Water mod"); // 水域检测参数 - waterBodyThreshold = config.getInt( - "waterBodyThreshold", - Configuration.CATEGORY_GENERAL, - 30, - 1, - 1000, - "Minimum number of connected water source blocks required to create a new source"); - - searchRadius = config.getInt( - "searchRadius", - Configuration.CATEGORY_GENERAL, - 10, - 1, - 50, - "Horizontal search radius for connected water body detection"); - - maxBlocksToCheck = config.getInt( - "maxBlocksToCheck", - Configuration.CATEGORY_GENERAL, - 1000, - 10, - 10000, - "Maximum number of blocks to check when detecting water bodies"); + waterBodyThreshold = config.getInt("waterBodyThreshold", Configuration.CATEGORY_GENERAL, 30, 1, 1000, "Minimum number of connected water source blocks required to create a new source"); + searchRadius = config.getInt("searchRadius", Configuration.CATEGORY_GENERAL, 10, 1, 50, "Horizontal search radius for connected water body detection"); + maxBlocksToCheck = config.getInt("maxBlocksToCheck", Configuration.CATEGORY_GENERAL, 1000, 10, 10000, "Maximum number of blocks to check when detecting water bodies"); + maxVerticalRange = config.getInt("maxVerticalRange", Configuration.CATEGORY_GENERAL, 0, 0, 10, "Vertical search range for water bodies (0 = same Y level only)"); // 原版功能扩展参数 - seaLevelRange = config.getInt( - "seaLevelRange", - Configuration.CATEGORY_GENERAL, - 5, - 0, - 30, - "Vertical range around sea level (63) where water can be generated"); - - processingDelayTicks = config.getInt( - "processingDelayTicks", - Configuration.CATEGORY_GENERAL, - 1, - 0, - 20, - "Number of ticks to wait before processing block break (0 for immediate)"); - - alwaysCheckAirBlocks = config.getBoolean( - "alwaysCheckAirBlocks", - Configuration.CATEGORY_GENERAL, - true, - "Always check for air blocks near broken blocks and place flowing water to trigger updates"); - + seaLevelRange = config.getInt("seaLevelRange", Configuration.CATEGORY_GENERAL, 5, 0, 30, "Vertical range around sea level (63) where water can be generated"); + processingDelayTicks = config.getInt("processingDelayTicks", Configuration.CATEGORY_GENERAL, 1, 0, 20, "Number of ticks to wait before processing block break (0 for immediate)"); + alwaysCheckAirBlocks = config.getBoolean("alwaysCheckAirBlocks", Configuration.CATEGORY_GENERAL, true, "Always check for air blocks near broken blocks and place flowing water to trigger updates"); debugMode = config.getBoolean("debugMode", Configuration.CATEGORY_GENERAL, false, "Enable debug logging"); - // 群系限制参数 - validDims = config.get("general", "validDims", validDims, - "Dimension array to allow infinite source water to be created. Unused if 'reversed' is set to true").getIntList(); - - bannedDims = config.get("general", "bannedDims", bannedDims, - "Dimension array to ban infinite source water to be created (overrides 'validDims' and 'validBiomes')").getIntList(); - - oceanDims = config.get("general", "oceanDims", oceanDims, - "Dimension array that allows water regeneration regardless of biome (overrides all other config settings)").getIntList(); - - reverse = config.getBoolean("reverse", "general", reverse, - "If true, water can create infinite sources everywhere except in banned dimensions and biomes"); - - validBiomeDictionary = config.getStringList("validBiomes", "general", validBiomeDictionary, - "Biome dictionary entries where infinite sources are allowed (e.g., OCEAN, BEACH, RIVER)"); - - bannedBiomeDictionary = config.getStringList("bannedBiomes", "general", bannedBiomeDictionary, - "Biome dictionary entries where infinite sources are NOT allowed (overrides valid biomes)"); - - waterLower = config.getInt("waterLowerBounds", "general", waterLower, 0, 255, - "The lowest Y-level where source water can form"); - - waterUpper = config.getInt("waterUpperBounds", "general", waterUpper, 0, 255, - "The highest Y-level where source water can form"); + // 群系限制参数(水) + validDims = config.get("general", "validDims", validDims, "Dimension array to allow infinite source water to be created. Unused if 'reversed' is set to true").getIntList(); + bannedDims = config.get("general", "bannedDims", bannedDims, "Dimension array to ban infinite source water to be created (overrides 'validDims' and 'validBiomes')").getIntList(); + oceanDims = config.get("general", "oceanDims", oceanDims, "Dimension array that allows water regeneration regardless of biome (overrides all other config settings)").getIntList(); + reverse = config.getBoolean("reverse", "general", reverse, "If true, water can create infinite sources everywhere except in banned dimensions and biomes"); + validBiomeDictionary = config.getStringList("validBiomes", "general", validBiomeDictionary, "Biome dictionary entries where infinite sources are allowed (e.g., OCEAN, BEACH, RIVER)"); + bannedBiomeDictionary = config.getStringList("bannedBiomes", "general", bannedBiomeDictionary, "Biome dictionary entries where infinite sources are NOT allowed (overrides valid biomes)"); + waterLower = config.getInt("waterLowerBounds", "general", waterLower, 0, 255, "The lowest Y-level where source water can form"); + waterUpper = config.getInt("waterUpperBounds", "general", waterUpper, 0, 255, "The highest Y-level where source water can form"); + + // === 岩浆配置 === + lavaEnabled = config.getBoolean("lavaEnabled", "lava", true, "Enable infinite lava source generation"); + lavaBodyThreshold = config.getInt("lavaBodyThreshold", "lava", 10, 1, 1000, "Minimum connected lava sources to create new source"); + lavaSearchRadius = config.getInt("lavaSearchRadius", "lava", 8, 1, 50, "Horizontal search radius for lava body"); + lavaMaxVerticalRange = config.getInt("lavaMaxVerticalRange", "lava", 0, 0, 10, "Vertical search range for lava (0 = same Y level only)"); + lavaMaxBlocksToCheck = config.getInt("lavaMaxBlocksToCheck", "lava", 500, 10, 10000, "Max blocks to check for lava"); + lavaProcessingDelayTicks = config.getInt("lavaProcessingDelayTicks", "lava", 20, 0, 20, "Delay before processing lava block break"); + lavaAlwaysCheckAirBlocks = config.getBoolean("lavaAlwaysCheckAirBlocks", "lava", true, "Place flowing lava around new source"); + + lavaValidDims = config.get("lava", "lavaValidDims", lavaValidDims, "Dimensions where lava sources can form").getIntList(); + lavaBannedDims = config.get("lava", "lavaBannedDims", lavaBannedDims, "Dimensions where lava sources are banned").getIntList(); + lavaOceanDims = config.get("lava", "lavaOceanDims", lavaOceanDims, "Dimensions where lava always allowed").getIntList(); + lavaReverse = config.getBoolean("lavaReverse", "lava", lavaReverse, "If true, lava allowed everywhere except banned dims/biomes"); + + lavaValidBiomeDictionary = config.getStringList("lavaValidBiomes", "lava", lavaValidBiomeDictionary, "Biome dictionary tags where lava sources allowed"); + lavaBannedBiomeDictionary = config.getStringList("lavaBannedBiomes", "lava", lavaBannedBiomeDictionary, "Biome dictionary tags where lava sources banned"); + + lavaLower = config.getInt("lavaLowerBounds", "lava", lavaLower, 0, 255, "Lowest Y-level for lava source formation"); + lavaUpper = config.getInt("lavaUpperBounds", "lava", lavaUpper, 0, 255, "Highest Y-level for lava source formation"); } catch (Exception e) { BetterWater.logger.warning("Failed to load config: " + e.getMessage()); } finally { - if (config.hasChanged()) { - config.save(); - } + if (config.hasChanged()) config.save(); } } /** * 判断指定方块是否受模组影响(即破坏后可能触发水源生成) */ - public static boolean isBlockAffected(net.minecraft.block.Block block) { + public static boolean isBlockAffected(Block block) { if (block == null) return false; - - // 排除水、流动水、空气、基岩、岩浆、流动岩浆、黑曜石等 - if (block == net.minecraft.init.Blocks.water || block == net.minecraft.init.Blocks.flowing_water - || block == net.minecraft.init.Blocks.air - || block == net.minecraft.init.Blocks.bedrock - || block == net.minecraft.init.Blocks.lava - || block == net.minecraft.init.Blocks.flowing_lava - || block == net.minecraft.init.Blocks.obsidian) { + if (block == Blocks.water || block == Blocks.flowing_water + || block == Blocks.air + || block == Blocks.bedrock + || block == Blocks.lava + || block == Blocks.flowing_lava + || block == Blocks.obsidian) { return false; } - - // 默认只影响不透明方块(固体) return block.isOpaqueCube(); } } diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index a1ab117..d1c5b14 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -2,8 +2,8 @@ { "modid": "betterwater", "name": "Better Water", - "description": "Automatically creates water source blocks when breaking blocks near large bodies of water", - "version": "3.0", + "description": "Automatically creates water source blocks when breaking blocks near large bodies of water (and lava)", + "version": "3.6", "mcversion": "1.7.10", "url": "", "updateUrl": "",