/* * Decompiled with CFR 0.152. */ package com.vinlanx.explosionoverhaul; import java.io.BufferedReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.loading.FMLPaths; import org.apache.commons.lang3.tuple.Pair; public class Config { public static final ForgeConfigSpec CLIENT_SPEC; public static final Client CLIENT; public static final ForgeConfigSpec COMMON_SPEC; public static final Common COMMON; public static boolean isFirstLaunch() { if (((Boolean)Config.CLIENT.firstLaunchComplete.get()).booleanValue()) { return false; } try { Boolean fileVal = Config.readFirstLaunchFromFile(); if (fileVal != null && fileVal.booleanValue()) { Config.CLIENT.firstLaunchComplete.set((Object)true); return false; } } catch (Exception exception) { // empty catch block } return true; } public static void markFirstLaunchComplete() { Config.CLIENT.firstLaunchComplete.set((Object)true); CLIENT_SPEC.save(); } /* * Enabled aggressive block sorting * Enabled unnecessary exception pruning * Enabled aggressive exception aggregation */ private static Boolean readFirstLaunchFromFile() { Path configPath = FMLPaths.CONFIGDIR.get().resolve("explosionoverhaul").resolve("explosionoverhaul-client.toml"); if (!Files.exists(configPath, new LinkOption[0])) { return null; } try (BufferedReader reader = Files.newBufferedReader(configPath);){ int eq; String line; String trimmed; do { if ((line = reader.readLine()) == null) return null; } while (!(trimmed = line.trim()).startsWith("firstLaunchComplete") || (eq = trimmed.indexOf(61)) <= 0); String val = trimmed.substring(eq + 1).trim(); if (val.startsWith("\"") && val.endsWith("\"")) { val = val.substring(1, val.length() - 1); } Boolean bl = Boolean.parseBoolean(val); return bl; } catch (IOException iOException) { // empty catch block } return null; } static { Pair clientSpecPair = new ForgeConfigSpec.Builder().configure(Client::new); CLIENT_SPEC = (ForgeConfigSpec)clientSpecPair.getRight(); CLIENT = (Client)clientSpecPair.getLeft(); Pair commonSpecPair = new ForgeConfigSpec.Builder().configure(Common::new); COMMON_SPEC = (ForgeConfigSpec)commonSpecPair.getRight(); COMMON = (Common)commonSpecPair.getLeft(); } public static class Client { public final ForgeConfigSpec.EnumValue glowTextureQuality; public final ForgeConfigSpec.EnumValue particleRenderMode; public final ForgeConfigSpec.DoubleValue particleSizeScale; public final ForgeConfigSpec.BooleanValue firstLaunchComplete; public final ForgeConfigSpec.BooleanValue enableGroundDustEffect; public final ForgeConfigSpec.DoubleValue groundDustQuality; public final ForgeConfigSpec.IntValue groundDustRaycastFrequency; public final ForgeConfigSpec.BooleanValue enableGroundMistEffect; public final ForgeConfigSpec.DoubleValue groundMistQuality; public final ForgeConfigSpec.IntValue groundMistRaycastFrequency; public final ForgeConfigSpec.BooleanValue enableExplosionParticles; public final ForgeConfigSpec.BooleanValue enablePlasmaParticles; public final ForgeConfigSpec.BooleanValue enablePlasmaSmokeTrail; public final ForgeConfigSpec.DoubleValue plasmaSmokeFrequency; public final ForgeConfigSpec.IntValue plasmaSmokeCount; public final ForgeConfigSpec.BooleanValue enableFlashEffect; public final ForgeConfigSpec.DoubleValue flashMaxOpacity; public final ForgeConfigSpec.BooleanValue enableLineSparks; public final ForgeConfigSpec.DoubleValue lineSparkAmountMultiplier; public final ForgeConfigSpec.BooleanValue enableCameraShake; public final ForgeConfigSpec.DoubleValue cameraShakeAmplifier; public final ForgeConfigSpec.BooleanValue enableShockwaveEffect; public final ForgeConfigSpec.BooleanValue showWindControls; public final ForgeConfigSpec.DoubleValue windVisualizationOpacity; public final ForgeConfigSpec.BooleanValue enableWindEffect; public final ForgeConfigSpec.DoubleValue windSpeedMultiplier; public final ForgeConfigSpec.BooleanValue enableConcussion; public final ForgeConfigSpec.DoubleValue concussionDurationMultiplier; public final ForgeConfigSpec.DoubleValue concussionChanceMultiplier; public final ForgeConfigSpec.BooleanValue enableHeartbeatPulse; public final ForgeConfigSpec.BooleanValue enableCameraSway; public final ForgeConfigSpec.DoubleValue cameraSwayIntensity; public final ForgeConfigSpec.BooleanValue enableDeafness; public final ForgeConfigSpec.BooleanValue enableLowPass; public final ForgeConfigSpec.DoubleValue deafnessChanceMultiplier; public final ForgeConfigSpec.DoubleValue lowPassChanceMultiplier; public final ForgeConfigSpec.BooleanValue showHeartbeatHUD; Client(ForgeConfigSpec.Builder builder) { builder.comment("Visual effect settings (client-side only)").push("Render Settings"); this.glowTextureQuality = builder.comment(new String[]{"Quality of the main explosion fireball textures (glow, glow_2, sglow).", "Lower quality (64p) can significantly improve performance on systems with less VRAM.", "Requires a resource pack reload (F3+T) to apply the change."}).defineEnum("glowTextureQuality", (Enum)GlowTextureQuality.QUALITY_256); this.particleRenderMode = builder.comment(new String[]{"Particle rendering system mode:", "REALISTIC - Uses animated sprite sheets with complex textures (current system)", "VANILA - Vanilla-like simple textures with color phases (better performance)"}).defineEnum("particleRenderMode", (Enum)ParticleRenderMode.VANILA); this.particleSizeScale = builder.comment(new String[]{"Scales the size of all explosion particles across all render modes.", "1.0 = default size, 0.1 = 10% of default, 5.0 = 500% of default."}).defineInRange("particleSizeScale", 1.0, 0.1, 5.0); this.firstLaunchComplete = builder.comment("Internal flag: marks whether the first-time setup screen has been shown.").define("firstLaunchComplete", false); builder.comment("\nCore explosion visual effects"); this.enableExplosionParticles = builder.comment("Enables the main fiery glow particles (glow, glow_2, sglow). Disabling this can significantly improve performance.").define("enableExplosionParticles", true); builder.comment("\nPlasma particle effects"); this.enablePlasmaParticles = builder.comment("Enables or disables plasma sparks entirely.").define("enablePlasmaParticles", true); this.enablePlasmaSmokeTrail = builder.comment("Enables the smoke trail that follows plasma sparks.").define("enablePlasmaSmokeTrail", true); this.plasmaSmokeFrequency = builder.comment("Frequency of plasma smoke spawning. 0.0 = no smoke, 0.7 = default chance (70%), 1.0 = always spawn smoke.").defineInRange("plasmaSmokeFrequency", 0.25, 0.0, 1.0); this.plasmaSmokeCount = builder.comment("Number of smoke particles spawned per plasma particle tick. Default was 2.").defineInRange("plasmaSmokeCount", 1, 0, 5); this.enableFlashEffect = builder.comment("Enables the flash overlay effect on explosions.").define("enableFlashEffect", true); this.flashMaxOpacity = builder.comment("Maximum opacity of the flash effect overlay. 0.0 = no flash, 1.0 = full opacity.").defineInRange("flashMaxOpacity", 0.5, 0.0, 1.0); builder.comment("\nConfiguration for the electrical spark effects"); this.enableLineSparks = builder.comment("Enables or disables the electrical line sparks that shoot out from explosions.").define("enableLineSparks", true); this.lineSparkAmountMultiplier = builder.comment(new String[]{"Multiplier for the number of sparks generated by an explosion.", "0.0 = no sparks, 1.0 = default amount, 2.0 = double amount.", "Higher values can impact performance."}).defineInRange("lineSparkAmountMultiplier", 1.0, 0.0, 5.0); builder.comment("\nConfiguration for the ground dust cloud effect"); this.enableGroundDustEffect = builder.comment("Enables or disables the dust cloud effect from explosions.").define("enableGroundDustEffect", true); this.groundDustQuality = builder.comment(new String[]{"Quality of the dust cloud effect. Affects particle count and duration.", "Lower values can improve performance on weaker PCs.", "0.0 = minimum particles, 1.0 = default quality."}).defineInRange("groundDustQuality", 1.0, 0.0, 1.0); this.groundDustRaycastFrequency = builder.comment(new String[]{"Dust Propagation Quality. Controls how often dust particles check for the ground beneath them.", "A value of 1 means every particle checks (highest quality, high performance cost).", "A value of 10 means every 10th particle checks (default performance)."}).defineInRange("groundDustRaycastFrequency", 10, 1, 20); builder.comment("\nConfiguration for the ground mist effect"); this.enableGroundMistEffect = builder.comment("Enables or disables the mist cloud effect from explosions.").define("enableGroundMistEffect", true); this.groundMistQuality = builder.comment(new String[]{"Quality of the mist cloud effect. Affects particle count and duration.", "Lower values can improve performance on weaker PCs.", "0.0 = minimum particles, 1.0 = default quality."}).defineInRange("groundMistQuality", 1.0, 0.0, 1.0); this.groundMistRaycastFrequency = builder.comment(new String[]{"Mist Propagation Quality. Controls how often mist particles check for the ground beneath them.", "A value of 1 means every particle checks (highest quality, high performance cost).", "A value of 10 means every 10th particle checks (default performance)."}).defineInRange("groundMistRaycastFrequency", 10, 1, 20); builder.comment("\nConfiguration for the shockwave effect"); this.enableShockwaveEffect = builder.comment("Enables or disables the shockwave particle effect from explosions.").define("enableShockwaveEffect", true); builder.pop(); builder.comment("\nCamera shake settings").push("Camera Shake"); this.enableCameraShake = builder.comment("Enables or disables the camera shake effect from explosions.").define("enableCameraShake", true); this.cameraShakeAmplifier = builder.comment("Amplifier for the camera shake intensity. 0.0 = no shake, 1.0 = default, 10.0 = maximum shake.").defineInRange("cameraShakeAmplifier", 1.0, 0.0, 10.0); builder.pop(); builder.comment("\nWind Effect Settings").push("Wind System"); this.enableWindEffect = builder.comment(new String[]{"Enables or disables the wind effect that moves explosion particles (dust and glow).", "When disabled, particles will not be affected by wind and will behave as they originally did."}).define("enableWindEffect", true); this.windSpeedMultiplier = builder.comment(new String[]{"Speed multiplier for the wind effect on particles.", "1.0 = default wind speed, 1.5 = 50% faster, 2.0 = double speed.", "Supports precise values like 1.01, 1.25, 1.75, etc.", "Higher values make particles move faster in the wind direction."}).defineInRange("windSpeedMultiplier", 1.0, 1.0, 2.0); builder.comment("\nWind Visualization").push("Wind Visualization"); this.showWindControls = builder.comment(new String[]{"Shows additional wind control information in debug screens or overlays.", "This is a client-only visual setting that doesn't affect gameplay."}).define("showWindControls", false); this.windVisualizationOpacity = builder.comment(new String[]{"Opacity of wind direction visualization effects (if any are implemented).", "0.0 = invisible, 1.0 = fully opaque."}).defineInRange("windVisualizationOpacity", 0.3, 0.0, 1.0); builder.pop(); builder.comment("\nConcussion Effect Settings").push("Concussion"); this.enableConcussion = builder.comment("Enables or disables the concussion system (blur, deafness, heartbeat, etc.)").define("enableConcussion", true); this.concussionDurationMultiplier = builder.comment("Multiplier for the duration of concussion effects.").defineInRange("concussionDurationMultiplier", 1.0, 0.0, 5.0); this.concussionChanceMultiplier = builder.comment("General chance multiplier for all concussion effects.").defineInRange("concussionChanceMultiplier", 1.0, 0.0, 5.0); this.enableHeartbeatPulse = builder.comment("Enables or disables the visual screen pulse and audio heartbeat (lub-dub).").define("enableHeartbeatPulse", true); this.enableCameraSway = builder.comment("Enables or disables the camera sway (disorientation) effect.").define("enableCameraSway", true); this.cameraSwayIntensity = builder.comment("Intensity (radius) multiplier for camera sway.").defineInRange("cameraSwayIntensity", 1.0, 0.0, 5.0); this.enableDeafness = builder.comment("Enables or disables the high-pitched ringing (deafness) effect.").define("enableDeafness", true); this.enableLowPass = builder.comment("Enables or disables the low-pass (muffled sound) effect.").define("enableLowPass", true); this.deafnessChanceMultiplier = builder.comment("Multiplier for the chance of deafness occurring.").defineInRange("deafnessChanceMultiplier", 1.0, 0.0, 5.0); this.lowPassChanceMultiplier = builder.comment("Multiplier for the chance of low-pass effect occurring.").defineInRange("lowPassChanceMultiplier", 1.0, 0.0, 5.0); this.showHeartbeatHUD = builder.comment("Whether to show the Heartbeat BPM/BPS HUD in the top-right corner.").define("showHeartbeatHUD", false); builder.pop(); builder.pop(); } public static enum GlowTextureQuality { QUALITY_256, QUALITY_64; } public static enum ParticleRenderMode { REALISTIC, REALISTIC_2, VANILA; } } public static class Common { public final ForgeConfigSpec.BooleanValue enablePlayerShake; public final ForgeConfigSpec.DoubleValue playerShakeAmplifier; public final ForgeConfigSpec.BooleanValue enableCraterDestruction; public final ForgeConfigSpec.BooleanValue enableFallingBlocks; public final ForgeConfigSpec.BooleanValue enableExplosionClustering; public final ForgeConfigSpec.IntValue maxClusterPower; public final ForgeConfigSpec.BooleanValue enableGlassBreaking; public final ForgeConfigSpec.BooleanValue enableAsyncCrater; public final ForgeConfigSpec.IntValue craterMaxThreads; public final ForgeConfigSpec.IntValue craterApplyBlocksPerTick; public final ForgeConfigSpec.IntValue craterMaxFallingBlocksPerTick; public final ForgeConfigSpec.BooleanValue enableDirectChunkWrites; public final ForgeConfigSpec.IntValue craterChunksPerTick; public final ForgeConfigSpec.IntValue glassBreakingIntervalTicks; public final ForgeConfigSpec.IntValue glassBlocksPerCycle; public final ForgeConfigSpec.DoubleValue craterSizeMultiplier; public final ForgeConfigSpec.DoubleValue craterCoreRatio; public final ForgeConfigSpec.BooleanValue enableLampFlicker; public final ForgeConfigSpec.IntValue lampFlickerSearchRadius; public final ForgeConfigSpec.BooleanValue enableDripstoneFalling; public final ForgeConfigSpec.IntValue dripstoneFallingSearchRadius; public final ForgeConfigSpec.BooleanValue enableAdvancedSoundSpeed; public final Ambient ambient; public final Scan scan; Common(ForgeConfigSpec.Builder builder) { builder.comment("Sound system settings").push("Sounds"); this.enableAdvancedSoundSpeed = builder.comment("Enable advanced sound speed system for explosions. If disabled, sound always travels at 343 m/s.").define("enableAdvancedSoundSpeed", false); builder.pop(); builder.comment("\nPlayer shake settings").push("Player Shake"); this.enablePlayerShake = builder.comment("Enables or disables the player shake effect from explosions.").define("enablePlayerShake", true); this.playerShakeAmplifier = builder.comment("Amplifier for the player shake intensity. 0.0 = no shake, 1.0 = default, 10.0 = maximum shake.").defineInRange("playerShakeAmplifier", 1.0, 0.0, 10.0); builder.pop(); builder.comment("Common settings that will be synced from server to client.").push("General"); this.enableFallingBlocks = builder.comment(new String[]{"Enables or disables blocks being launched from explosions.", "If false, explosions will still destroy blocks but won't create falling block entities."}).define("enableFallingBlocks", true); this.enableExplosionClustering = builder.comment(new String[]{"Enables or disables the clustering of nearby explosives into a single, more powerful explosion.", "If true, multiple TNT blocks/entities close together will merge into one explosion with increased power."}).define("enableExplosionClustering", true); this.maxClusterPower = builder.comment(new String[]{"Maximum total power for clustered TNT explosions.", "4 = minimum (single TNT), 100 = default, 1000 = extreme (high crash risk).", "WARNING: Values above 150 may cause rendering lag. Values above 500 risk game crashes."}).defineInRange("maxClusterPower", 100, 4, 1000); this.enableDripstoneFalling = builder.comment("Enables or disables the falling effect for pointed dripstone near explosions.").define("enableDripstoneFalling", true); this.enableCraterDestruction = builder.comment(new String[]{"Enables or disables the destruction of blocks, creating craters.", "If false, explosions will still cause visual and sound effects, but won't break blocks."}).define("enableCraterDestruction", true); this.enableGlassBreaking = builder.comment("Enables or disables glass being shattered by the explosion's shockwave.").define("enableGlassBreaking", true); this.enableLampFlicker = builder.comment("Enables or disables the flickering effect on Redstone Lamps near explosions.").define("enableLampFlicker", true); builder.pop(); builder.comment("\nDripstone Falling").push("Dripstone Falling"); this.dripstoneFallingSearchRadius = builder.comment(new String[]{"The radius around the explosion in which to search for pointed dripstone to fall.", "Warning: High values on servers with many players and dripstones can cause lag."}).defineInRange("dripstoneFallingSearchRadius", 50, 1, 100); builder.pop(); builder.comment("\nFine-tuning for the glass breaking effect. High values can impact performance.").push("Glass Breaking"); this.glassBreakingIntervalTicks = builder.comment(new String[]{"The interval in game ticks between each glass breaking cycle.", "1 tick = 0.05 seconds. Lower values make the effect smoother but use more server resources.", "Default: 1"}).defineInRange("glassBreakingIntervalTicks", 1, 1, 20); this.glassBlocksPerCycle = builder.comment(new String[]{"The maximum number of glass blocks that can be broken in a single processing cycle.", "This prevents server lag from massive explosions. Higher values can handle large glass structures better but may cause spikes.", "Default: 70"}).defineInRange("glassBlocksPerCycle", 70, 10, 500); builder.pop(); builder.comment("\nCrater Customization").push("Crater Settings"); this.craterSizeMultiplier = builder.comment(new String[]{"Multiplier for the radius of the explosion crater.", "Affects both crater size and the number of generated particles.", "1.0 = default size."}).defineInRange("craterSizeMultiplier", 1.0, 0.1, 50.0); this.craterCoreRatio = builder.comment(new String[]{"For explosions with power 40+, this controls the shape of the crater.", "Determines the size of the solid 'core' relative to the total radius.", "0.1 = very ray-like, 0.95 = almost a perfect sphere.", "Default: 0.7 (70%)"}).defineInRange("craterCoreRatio", 0.7, 0.1, 0.95); builder.pop(); int availableThreadsForCrater = Runtime.getRuntime().availableProcessors(); int maxThreadsForSystemCrater = Math.min(32, availableThreadsForCrater); builder.comment("\nAsync crater pipeline (off-thread ray geometry + main-thread batched application)").push("Async Crater"); this.enableAsyncCrater = builder.comment(new String[]{"Enable the asynchronous crater pipeline.", "Compute crater geometry off-thread and apply block changes in small batches per tick to keep TPS smooth on large explosions.", "", "WARNING: When asynchronous and multi-threaded mode is enabled - destruction of VS objects - does not work."}).define("enableAsyncCrater", true); this.craterMaxThreads = builder.comment(new String[]{"Maximum number of threads for off-thread crater geometry precomputation.", "0 = Auto (use all available: " + availableThreadsForCrater + ")", "1 = Single-threaded", "2-" + maxThreadsForSystemCrater + " = Custom thread count for this system"}).defineInRange("craterMaxThreads", 0, 0, maxThreadsForSystemCrater); this.craterApplyBlocksPerTick = builder.comment(new String[]{"Maximum number of blocks to evaluate/apply per server tick when building a crater.", "Higher values complete faster but can cause small TPS dips.", "Lower values keep TPS flatter but take longer."}).defineInRange("craterApplyBlocksPerTick", 50000, 0, 150000); this.craterMaxFallingBlocksPerTick = builder.comment(new String[]{"Limit of falling block entities to spawn per tick during crater application (visual debris).", "Set to 0 to disable spawning via the async pipeline."}).defineInRange("craterMaxFallingBlocksPerTick", 500, 0, 2000); this.enableDirectChunkWrites = builder.comment(new String[]{"Directly write block states into chunk sections during crater application (much faster).", "When enabled, bypasses Level#setBlock and updates heightmaps/light manually.", "Note: This skips Forge block events and neighbor updates."}).define("enableDirectChunkWrites", true); this.craterChunksPerTick = builder.comment(new String[]{"Maximum number of chunks to process per tick when direct writes are enabled.", "Used along with block budget to smooth TPS."}).defineInRange("craterChunksPerTick", 120, 0, 500); builder.pop(); builder.comment("\nRedstone Lamp Flickering").push("Lamp Flickering"); this.lampFlickerSearchRadius = builder.comment(new String[]{"The radius around the player in which to search for lamps to flicker.", "Warning: High values on servers with many players and lamps can cause lag."}).defineInRange("lampFlickerSearchRadius", 50, 1, 100); builder.pop(); this.ambient = new Ambient(builder); this.scan = new Scan(builder); } public static class Ambient { public final ForgeConfigSpec.BooleanValue enableAmbientExplosions; public final ForgeConfigSpec.IntValue minTimeBetweenExplosions; public final ForgeConfigSpec.IntValue maxTimeBetweenExplosions; public final ForgeConfigSpec.IntValue minExplosionDistance; public final ForgeConfigSpec.IntValue maxExplosionDistance; public final ForgeConfigSpec.DoubleValue maxAmbientExplosionPower; public final Scenarios scenarios; public final PowerTiers powerTiers; public final SoundTypes soundTypes; Ambient(ForgeConfigSpec.Builder builder) { builder.comment("Settings for the ambient explosion system, creating a 'battlefield' atmosphere.").push("Ambient"); this.enableAmbientExplosions = builder.comment("Globally enables or disables the ambient explosion sound system.").define("enableAmbientExplosions", false); this.minTimeBetweenExplosions = builder.comment("Minimum time in ticks between ambient explosion events (20 ticks = 1 second).").defineInRange("minTimeBetweenExplosions", 1200, 100, 72000); this.maxTimeBetweenExplosions = builder.comment("Maximum time in ticks between ambient explosion events.").defineInRange("maxTimeBetweenExplosions", 6000, 200, 72000); this.minExplosionDistance = builder.comment("Minimum distance in blocks from the player where an ambient sound can originate.").defineInRange("minExplosionDistance", 501, 100, 10000); this.maxExplosionDistance = builder.comment("Maximum distance in blocks from the player where an ambient sound can originate.").defineInRange("maxExplosionDistance", 5001, 200, 10000); this.maxAmbientExplosionPower = builder.comment("The maximum power a random 'Cataclysm' tier explosion can have.").defineInRange("maxAmbientExplosionPower", 80.0, 40.0, 200.0); this.scenarios = new Scenarios(builder); this.powerTiers = new PowerTiers(builder); this.soundTypes = new SoundTypes(builder); builder.pop(); } public static class Scenarios { public final ForgeConfigSpec.IntValue singleExplosionWeight; public final ForgeConfigSpec.IntValue chainReactionWeight; public final ForgeConfigSpec.IntValue shellingWeight; public final ForgeConfigSpec.IntValue minChainReactionShots; public final ForgeConfigSpec.IntValue maxChainReactionShots; public final ForgeConfigSpec.IntValue minTimeBetweenChainShots; public final ForgeConfigSpec.IntValue maxTimeBetweenChainShots; public final ForgeConfigSpec.IntValue minShellingDelay; public final ForgeConfigSpec.IntValue maxShellingDelay; Scenarios(ForgeConfigSpec.Builder builder) { builder.comment(new String[]{"\nConfiguration for different ambient event scenarios.", "The chance for a scenario is (its_weight / sum_of_all_scenario_weights)."}).push("Scenarios"); this.singleExplosionWeight = builder.comment("Weight for a standard, single explosion event.").defineInRange("singleExplosionWeight", 70, 0, 1000); this.chainReactionWeight = builder.comment("Weight for a 'Chain Reaction' event (a series of increasingly powerful explosions).").defineInRange("chainReactionWeight", 15, 0, 1000); this.shellingWeight = builder.comment("Weight for an 'Artillery Shelling' event (a quiet shot followed by a delayed, loud impact).").defineInRange("shellingWeight", 15, 0, 1000); builder.comment("\nSettings for the 'Chain Reaction' scenario.").push("ChainReaction"); this.minChainReactionShots = builder.defineInRange("minChainReactionShots", 3, 2, 20); this.maxChainReactionShots = builder.defineInRange("maxChainReactionShots", 7, 2, 20); this.minTimeBetweenChainShots = builder.defineInRange("minTimeBetweenChainShots", 10, 5, 200); this.maxTimeBetweenChainShots = builder.defineInRange("maxTimeBetweenChainShots", 40, 10, 400); builder.pop(); builder.comment("\nSettings for the 'Artillery Shelling' scenario.").push("Shelling"); this.minShellingDelay = builder.comment("Minimum delay in ticks between the 'shot' sound and the 'impact' sound (20 ticks = 1s).").defineInRange("minShellingDelay", 40, 20, 400); this.maxShellingDelay = builder.comment("Maximum delay in ticks between the 'shot' and 'impact' sounds.").defineInRange("maxShellingDelay", 140, 20, 400); builder.pop(); builder.pop(); } } public static class PowerTiers { public final ForgeConfigSpec.IntValue tier1_weight; public final ForgeConfigSpec.IntValue tier2_weight; public final ForgeConfigSpec.IntValue tier3_weight; public final ForgeConfigSpec.IntValue tier4_weight; public final ForgeConfigSpec.IntValue tier5_weight; PowerTiers(ForgeConfigSpec.Builder builder) { builder.comment(new String[]{"\nWeighted chances for explosion power tiers (for single and shelling events).", "The chance for a tier is (its_weight / sum_of_all_weights). Set a weight to 0 to disable that tier."}).push("Power_Tiers_Weight"); this.tier1_weight = builder.comment("Weight for 'Background Noise' (Power 1-4)").defineInRange("tier1_weight", 50, 0, 1000); this.tier2_weight = builder.comment("Weight for 'Local Skirmish' (Power 5-15)").defineInRange("tier2_weight", 25, 0, 1000); this.tier3_weight = builder.comment("Weight for 'Serious Battle' (Power 16-40)").defineInRange("tier3_weight", 15, 0, 1000); this.tier4_weight = builder.comment("Weight for 'Epicenter' (Power 41-80)").defineInRange("tier4_weight", 8, 0, 1000); this.tier5_weight = builder.comment("Weight for 'Cataclysm' (Power 81+)").defineInRange("tier5_weight", 2, 0, 1000); builder.pop(); } } public static class SoundTypes { public final ForgeConfigSpec.BooleanValue enableSurfaceSounds; public final ForgeConfigSpec.BooleanValue enableCaveSounds; public final ForgeConfigSpec.BooleanValue enableAmbientCaveDust; SoundTypes(ForgeConfigSpec.Builder builder) { builder.comment("\nEnable or disable specific types of ambient sound environments.").push("Sound_Types"); this.enableSurfaceSounds = builder.comment("Surface: A clear explosion sound in an open area.").define("enableSurfaceSounds", true); this.enableCaveSounds = builder.comment("Cave: A loud, reverberating sound when both player and explosion are in a cave.").define("enableCaveSounds", true); this.enableAmbientCaveDust = builder.comment("If enabled, an ambient cave explosion will cause a visual dust effect to fall from the ceiling.").define("enableAmbientCaveDust", true); builder.pop(); } } } public static class Scan { public final ForgeConfigSpec.IntValue maxScanThreads; public final ForgeConfigSpec.IntValue cpuUsagePercent; public final ForgeConfigSpec.BooleanValue enableBlockIndexing; public final ForgeConfigSpec.BooleanValue showScanProgressHUD; Scan(ForgeConfigSpec.Builder builder) { int availableThreads = Runtime.getRuntime().availableProcessors(); builder.comment(new String[]{"Settings for chunk scanning and block indexing system.", "System detected: " + availableThreads + " CPU threads available", "Configuration ranges are automatically adjusted for your system"}).push("Scan"); int maxThreadsForSystem = Math.min(32, availableThreads); this.maxScanThreads = builder.comment(new String[]{"Maximum number of threads to use for chunk scanning.", "Available range for your system: 0-" + maxThreadsForSystem + " threads", "0 = Auto-detect (recommended): uses all " + availableThreads + " available threads", "1 = Single-threaded (slowest but safest)", "2-" + maxThreadsForSystem + " = Custom thread count for this system", "Your system supports up to " + availableThreads + " concurrent threads"}).defineInRange("maxScanThreads", 0, 0, maxThreadsForSystem); this.cpuUsagePercent = builder.comment(new String[]{"How much CPU power to use for chunk scanning (1-100%).", "100% = Maximum speed, uses all available threads intensively", "50% = Balanced, leaves room for other server processes", "25% = Conservative, minimal impact on server performance", "Lower values add delays between chunk processing to reduce CPU load."}).defineInRange("cpuUsagePercent", 75, 1, 100); this.enableBlockIndexing = builder.comment(new String[]{"Enables or disables the block indexing system.", "When enabled, chunks are automatically scanned for Redstone Lamps and Pointed Dripstone.", "When disabled, only manual registration/unregistration of blocks will occur.", "This affects Redstone Lamp flickering and Pointed Dripstone falling effects near explosions."}).define("enableBlockIndexing", true); this.showScanProgressHUD = builder.comment(new String[]{"Controls visibility of the scanning progress HUD.", "When disabled, no progress bar will be shown even if scanning is enabled.", "Shows percentage of chunks scanned during world initialization and automatically hides when complete."}).define("showScanProgressHUD", true); builder.pop(); } } } }