diff --git a/build.gradle b/build.gradle index 9f1795fb..abe86a39 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { id 'net.minecraftforge.gradle' version '[6.0.16,6.2)' } -version = '2.2.0' +version = '4.5' group = 'com.aulyrius.custom_ore_gen' archivesBaseName = 'custom_ore_gen' diff --git a/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java b/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java index cf0a357a..4e7aea9e 100644 --- a/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java +++ b/src/main/java/net/mcreator/customoregen/CustomOreGenMod.java @@ -8,6 +8,8 @@ import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.fml.util.thread.SidedThreadGroups; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fml.config.ModConfig; +import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.IEventBus; @@ -20,6 +22,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.mcreator.customoregen.init.CustomOreGenModTabs; import net.mcreator.customoregen.init.CustomOreGenModItems; import net.mcreator.customoregen.init.CustomOreGenModBlocks; +import net.mcreator.customoregen.config.ModConfigs; import net.mcreator.customoregen.worldgen.WorldGenRegistration; import java.util.function.Supplier; @@ -42,6 +45,9 @@ public class CustomOreGenMod { MinecraftForge.EVENT_BUS.register(this); IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); + // Enregistre la configuration COMMON (crée/charge custom_ore_gen.toml) + ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfigs.SPEC, "custom_ore_gen.toml"); + CustomOreGenModBlocks.REGISTRY.register(bus); CustomOreGenModItems.REGISTRY.register(bus); diff --git a/src/main/java/net/mcreator/customoregen/config/ConfigHelper.java b/src/main/java/net/mcreator/customoregen/config/ConfigHelper.java index b996c4cd..c60546b5 100644 --- a/src/main/java/net/mcreator/customoregen/config/ConfigHelper.java +++ b/src/main/java/net/mcreator/customoregen/config/ConfigHelper.java @@ -1,35 +1,22 @@ package net.mcreator.customoregen.config; -import net.minecraftforge.fml.ModList; - +/** + * Accès sûr aux valeurs de configuration du mod. + *

+ * Chaque méthode retourne une valeur par défaut si la configuration n'est pas + * encore chargée (par ex. pendant la construction des objets enregistrés), + * évitant ainsi tout plantage lié à un accès prématuré au {@code ForgeConfigSpec}. + */ public class ConfigHelper { - // Helper method to safely access config values - public static boolean isFeatureEnabled(String featureName) { - switch (featureName) { - case "shardDiamondTools": - return ModConfigs.FEATURES.enableShardDiamondTools.get(); - case "shardDiamondOre": - return ModConfigs.FEATURES.enableShardDiamondOre.get(); - case "concentratedOres": - return ModConfigs.FEATURES.enableConcentratedOres.get(); - case "impureOres": - return ModConfigs.FEATURES.enableImpureOres.get(); - case "ashCoalOre": - return ModConfigs.FEATURES.enableAshCoalOre.get(); - case "pureGoldenOre": - return ModConfigs.FEATURES.enablePureGoldenOre.get(); - case "customEmeraldOres": - return ModConfigs.FEATURES.enableCustomEmeraldOres.get(); - case "customCopperOres": - return ModConfigs.FEATURES.enableCustomCopperOres.get(); - case "vanillaOreVariants": - return ModConfigs.FEATURES.enableVanillaOreVariants.get(); - default: - return true; - } + + private static boolean loaded() { + return ModConfigs.SPEC.isLoaded(); } + /** Durabilité de l'outil Shard Diamond concerné (par défaut 200). */ public static int getShardDiamondToolDurability(String toolType) { + if (!loaded()) + return 200; switch (toolType) { case "pickaxe": return ModConfigs.TOOL_STATS.shardDiamondPickaxeDurability.get(); @@ -42,7 +29,10 @@ public class ConfigHelper { } } + /** Vitesse de minage de l'outil Shard Diamond concerné. */ public static float getShardDiamondToolSpeed(String toolType) { + if (!loaded()) + return defaultSpeed(toolType); switch (toolType) { case "pickaxe": return ModConfigs.TOOL_STATS.shardDiamondPickaxeSpeed.get().floatValue(); @@ -55,16 +45,7 @@ public class ConfigHelper { } } - public static int getShardDiamondToolDamage(String toolType) { - switch (toolType) { - case "pickaxe": - return ModConfigs.TOOL_STATS.shardDiamondPickaxeAttackDamage.get(); - case "axe": - return ModConfigs.TOOL_STATS.shardDiamondAxeAttackDamage.get(); - case "shovel": - return ModConfigs.TOOL_STATS.shardDiamondShovelAttackDamage.get(); - default: - return 1; - } + private static float defaultSpeed(String toolType) { + return "shovel".equals(toolType) ? 4.0f : 7.0f; } } diff --git a/src/main/java/net/mcreator/customoregen/config/ModConfigs.java b/src/main/java/net/mcreator/customoregen/config/ModConfigs.java index 6aaef9ff..72c8c015 100644 --- a/src/main/java/net/mcreator/customoregen/config/ModConfigs.java +++ b/src/main/java/net/mcreator/customoregen/config/ModConfigs.java @@ -13,7 +13,7 @@ public class ModConfigs { public static final WorldGenConfig WORLD_GEN; static { - BUILDER.push("Custom Ore Gem Configuration"); + BUILDER.push("Custom Ore Gen Configuration"); ORE_GEN = new OreGenConfig(BUILDER); TOOL_STATS = new ToolStatsConfig(BUILDER); @@ -130,15 +130,12 @@ public class ModConfigs { public static class ToolStatsConfig { public final ForgeConfigSpec.ConfigValue shardDiamondPickaxeDurability; public final ForgeConfigSpec.DoubleValue shardDiamondPickaxeSpeed; - public final ForgeConfigSpec.ConfigValue shardDiamondPickaxeAttackDamage; public final ForgeConfigSpec.ConfigValue shardDiamondAxeDurability; public final ForgeConfigSpec.DoubleValue shardDiamondAxeSpeed; - public final ForgeConfigSpec.ConfigValue shardDiamondAxeAttackDamage; public final ForgeConfigSpec.ConfigValue shardDiamondShovelDurability; public final ForgeConfigSpec.DoubleValue shardDiamondShovelSpeed; - public final ForgeConfigSpec.ConfigValue shardDiamondShovelAttackDamage; public ToolStatsConfig(ForgeConfigSpec.Builder builder) { builder.push("tool_stats"); @@ -150,9 +147,6 @@ public class ModConfigs { shardDiamondPickaxeSpeed = builder .comment("Mining speed of Shard Diamond Pickaxe (default: 7.0)") .defineInRange("pickaxeSpeed", 7.0, 0.1, 20.0); - shardDiamondPickaxeAttackDamage = builder - .comment("Attack damage of Shard Diamond Pickaxe (default: 1)") - .defineInRange("pickaxeAttackDamage", 1, 0, 20); shardDiamondAxeDurability = builder .comment("Durability of Shard Diamond Axe (default: 200)") @@ -160,9 +154,6 @@ public class ModConfigs { shardDiamondAxeSpeed = builder .comment("Mining speed of Shard Diamond Axe (default: 7.0)") .defineInRange("axeSpeed", 7.0, 0.1, 20.0); - shardDiamondAxeAttackDamage = builder - .comment("Attack damage of Shard Diamond Axe (default: 6)") - .defineInRange("axeAttackDamage", 6, 0, 20); shardDiamondShovelDurability = builder .comment("Durability of Shard Diamond Shovel (default: 200)") @@ -170,9 +161,6 @@ public class ModConfigs { shardDiamondShovelSpeed = builder .comment("Mining speed of Shard Diamond Shovel (default: 4.0)") .defineInRange("shovelSpeed", 4.0, 0.1, 20.0); - shardDiamondShovelAttackDamage = builder - .comment("Attack damage of Shard Diamond Shovel (default: 2)") - .defineInRange("shovelAttackDamage", 2, 0, 20); builder.pop(); builder.pop(); @@ -333,7 +321,6 @@ public class ModConfigs { public static class WorldGenConfig { public final ForgeConfigSpec.ConfigValue biomeSize; public final ForgeConfigSpec.ConfigValue temperatureBandWidth; - public final ForgeConfigSpec.DoubleValue mountainHeightMultiplier; public final ForgeConfigSpec.ConfigValue enableBOPBiomes; public final ForgeConfigSpec.ConfigValue enableOceans; public final ForgeConfigSpec.ConfigValue enableWelcomeMessage; @@ -348,9 +335,6 @@ public class ModConfigs { temperatureBandWidth = builder .comment("Width of each temperature band in blocks (default: 4000)") .defineInRange("temperatureBandWidth", 4000, 1000, 50000); - mountainHeightMultiplier = builder - .comment("Multiplier for mountain terrain height (1.0 = vanilla, default: 1.5)") - .defineInRange("mountainHeightMultiplier", 1.5, 1.0, 3.0); enableBOPBiomes = builder .comment("Include Biomes O' Plenty biomes in temperature bands (default: true)") .define("enableBOPBiomes", true); diff --git a/src/main/java/net/mcreator/customoregen/item/SharddiamondaxeItem.java b/src/main/java/net/mcreator/customoregen/item/SharddiamondaxeItem.java index f61a47b6..a74a5157 100644 --- a/src/main/java/net/mcreator/customoregen/item/SharddiamondaxeItem.java +++ b/src/main/java/net/mcreator/customoregen/item/SharddiamondaxeItem.java @@ -7,16 +7,17 @@ import net.minecraft.world.item.AxeItem; import net.minecraft.world.item.ItemStack; import net.mcreator.customoregen.init.CustomOreGenModItems; +import net.mcreator.customoregen.config.ConfigHelper; public class SharddiamondaxeItem extends AxeItem { public SharddiamondaxeItem() { super(new Tier() { public int getUses() { - return 200; + return ConfigHelper.getShardDiamondToolDurability("axe"); } public float getSpeed() { - return 7f; + return ConfigHelper.getShardDiamondToolSpeed("axe"); } public float getAttackDamageBonus() { diff --git a/src/main/java/net/mcreator/customoregen/item/SharddiamondpickaxeItem.java b/src/main/java/net/mcreator/customoregen/item/SharddiamondpickaxeItem.java index 24b75976..d1a77d65 100644 --- a/src/main/java/net/mcreator/customoregen/item/SharddiamondpickaxeItem.java +++ b/src/main/java/net/mcreator/customoregen/item/SharddiamondpickaxeItem.java @@ -8,16 +8,17 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Item; import net.mcreator.customoregen.init.CustomOreGenModItems; +import net.mcreator.customoregen.config.ConfigHelper; public class SharddiamondpickaxeItem extends PickaxeItem { public SharddiamondpickaxeItem() { super(new Tier() { public int getUses() { - return 200; // Hardcoded - config not loaded yet + return ConfigHelper.getShardDiamondToolDurability("pickaxe"); } public float getSpeed() { - return 7f; + return ConfigHelper.getShardDiamondToolSpeed("pickaxe"); } public float getAttackDamageBonus() { diff --git a/src/main/java/net/mcreator/customoregen/item/SharddiamondshovelItem.java b/src/main/java/net/mcreator/customoregen/item/SharddiamondshovelItem.java index 3a1ba86b..989ec464 100644 --- a/src/main/java/net/mcreator/customoregen/item/SharddiamondshovelItem.java +++ b/src/main/java/net/mcreator/customoregen/item/SharddiamondshovelItem.java @@ -8,16 +8,17 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Item; import net.mcreator.customoregen.init.CustomOreGenModItems; +import net.mcreator.customoregen.config.ConfigHelper; public class SharddiamondshovelItem extends ShovelItem { public SharddiamondshovelItem() { super(new Tier() { public int getUses() { - return 200; + return ConfigHelper.getShardDiamondToolDurability("shovel"); } public float getSpeed() { - return 4f; + return ConfigHelper.getShardDiamondToolSpeed("shovel"); } public float getAttackDamageBonus() { diff --git a/src/main/java/net/mcreator/customoregen/procedures/ConfigurableOreDropsProcedure.java b/src/main/java/net/mcreator/customoregen/procedures/ConfigurableOreDropsProcedure.java deleted file mode 100644 index 3761ebbf..00000000 --- a/src/main/java/net/mcreator/customoregen/procedures/ConfigurableOreDropsProcedure.java +++ /dev/null @@ -1,143 +0,0 @@ -package net.mcreator.customoregen.procedures; - -import net.minecraft.world.level.LevelAccessor; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.enchantment.EnchantmentHelper; -import net.minecraft.world.item.enchantment.Enchantments; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.storage.loot.BuiltInLootTables; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.ExperienceOrb; - -import net.mcreator.customoregen.config.ModConfigs; -import net.mcreator.customoregen.init.CustomOreGenModItems; - -import java.util.Random; - -public class ConfigurableOreDropsProcedure { - - public static void execute(LevelAccessor world, double x, double y, double z, Entity entity, String oreType) { - if (world.isClientSide()) - return; - - Random random = new Random(); - int fortuneLevel = 0; - boolean silkTouch = false; - - // Get fortune and silk touch from the tool if mining by player - if (entity instanceof Player) { - Player player = (Player) entity; - ItemStack mainHandItem = player.getMainHandItem(); - fortuneLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_FORTUNE, mainHandItem); - silkTouch = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, mainHandItem) > 0; - } - - // If silk touch, drop the block itself and return - if (silkTouch) { - return; // Let vanilla handle silk touch - } - - int minDrops = 1; - int maxDrops = 2; - boolean enableFortune = true; - ItemStack dropItem = ItemStack.EMPTY; - - // Configure drops based on ore type - switch (oreType) { - case "shard_diamond": - minDrops = ModConfigs.DROPS.shardDiamondOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.shardDiamondOreMaxDrops.get(); - enableFortune = ModConfigs.DROPS.shardDiamondOreEnableFortune.get(); - dropItem = new ItemStack(CustomOreGenModItems.DIAMONDSHARD.get()); - break; - - case "concentrated_diamond": - minDrops = ModConfigs.DROPS.concentratedDiamondOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.concentratedDiamondOreMaxDrops.get(); - enableFortune = ModConfigs.DROPS.concentratedDiamondOreEnableFortune.get(); - dropItem = new ItemStack(Items.DIAMOND); - break; - - case "concentrated_coal": - minDrops = ModConfigs.DROPS.concentratedCoalOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.concentratedCoalOreMaxDrops.get(); - dropItem = new ItemStack(Items.COAL); - break; - - case "pure_golden": - minDrops = ModConfigs.DROPS.pureGoldenOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.pureGoldenOreMaxDrops.get(); - dropItem = new ItemStack(Items.GOLD_NUGGET); - break; - - case "ash_coal": - minDrops = ModConfigs.DROPS.ashCoalOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.ashCoalOreMaxDrops.get(); - dropItem = new ItemStack(Items.COAL); // Temporarily use coal until ASHCOAL item is created - break; - - case "impure_iron": - minDrops = ModConfigs.DROPS.impureIronOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.impureIronOreMaxDrops.get(); - dropItem = new ItemStack(Items.IRON_NUGGET); // Use iron nugget until IMPUREIRON item is created - break; - - case "impure_gold": - minDrops = ModConfigs.DROPS.impureGoldOreMinDrops.get(); - maxDrops = ModConfigs.DROPS.impureGoldOreMaxDrops.get(); - dropItem = new ItemStack(Items.RAW_GOLD); - break; - - default: - return; - } - - // Calculate drops - int dropCount = minDrops + random.nextInt(maxDrops - minDrops + 1); - - // Apply fortune if enabled - if (enableFortune && fortuneLevel > 0) { - int fortuneBonus = random.nextInt(fortuneLevel + 2) - 1; - if (fortuneBonus < 0) - fortuneBonus = 0; - dropCount += fortuneBonus; - } - - // Drop the items - if (!dropItem.isEmpty() && dropCount > 0) { - dropItem.setCount(dropCount); - if (world instanceof ServerLevel) { - ItemEntity itemEntity = new ItemEntity( - (ServerLevel) world, - x + 0.5, y + 0.5, z + 0.5, - dropItem - ); - itemEntity.setDefaultPickUpDelay(); - ((ServerLevel) world).addFreshEntity(itemEntity); - } - } - - // Drop experience if configured - int expAmount = ModConfigs.DROPS.oreExperienceDrops.get(); - if (expAmount > 0 && entity instanceof Player) { - ExperienceOrb expOrb = new ExperienceOrb( - (ServerLevel) world, - x + 0.5, y + 0.5, z + 0.5, - expAmount - ); - ((ServerLevel) world).addFreshEntity(expOrb); - } - } -} diff --git a/src/main/java/net/mcreator/customoregen/procedures/OreexperienceProcedure.java b/src/main/java/net/mcreator/customoregen/procedures/OreexperienceProcedure.java index 851c2612..43420347 100644 --- a/src/main/java/net/mcreator/customoregen/procedures/OreexperienceProcedure.java +++ b/src/main/java/net/mcreator/customoregen/procedures/OreexperienceProcedure.java @@ -8,16 +8,36 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ExperienceOrb; import net.minecraft.world.entity.Entity; import net.minecraft.server.level.ServerLevel; -import net.minecraft.core.BlockPos; + +import net.mcreator.customoregen.config.ModConfigs; public class OreexperienceProcedure { + /** + * Ajoute de l'expérience lors de la casse d'un minerai personnalisé. + *

+ * Ne recasse PAS le bloc : le bloc est déjà détruit par + * {@code onDestroyedByPlayer} (qui appelle {@code super} et génère les + * drops via la loot table). Cette procédure se contente d'ajouter l'orbe + * d'XP, en respectant Silk Touch et la valeur de configuration. + */ public static void execute(LevelAccessor world, double x, double y, double z, Entity entity) { + // Uniquement côté serveur : l'XP ne doit pas être spawnée côté client. + if (world.isClientSide()) + return; if (entity == null) return; - if (!(EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, (entity instanceof LivingEntity _livEnt ? _livEnt.getMainHandItem() : ItemStack.EMPTY)) != 0)) { - world.destroyBlock(BlockPos.containing(x, y, z), false); - if (world instanceof ServerLevel _level) - _level.addFreshEntity(new ExperienceOrb(_level, x, y, z, 2)); - } + + // Pas d'XP si l'outil est enchanté Silk Touch (comportement vanilla). + ItemStack mainHand = (entity instanceof LivingEntity living) ? living.getMainHandItem() : ItemStack.EMPTY; + boolean silkTouch = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, mainHand) > 0; + if (silkTouch) + return; + + int amount = ModConfigs.SPEC.isLoaded() ? ModConfigs.DROPS.oreExperienceDrops.get() : 2; + if (amount <= 0) + return; + + if (world instanceof ServerLevel level) + level.addFreshEntity(new ExperienceOrb(level, x + 0.5, y + 0.5, z + 0.5, amount)); } } diff --git a/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java b/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java index 47b06194..d268fd01 100644 --- a/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java +++ b/src/main/java/net/mcreator/customoregen/worldgen/BiomeBand.java @@ -1,12 +1,16 @@ package net.mcreator.customoregen.worldgen; import net.minecraft.core.Holder; +import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biomes; import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.server.ServerLifecycleHooks; +import net.mcreator.customoregen.config.ModConfigs; import java.util.ArrayList; import java.util.List; @@ -129,6 +133,8 @@ public enum BiomeBand { } private static void addBOP(List> list, String... ids) { + // Respecte le toggle de configuration enableBOPBiomes (true par défaut). + if (!bopEnabled()) return; for (String id : ids) { ResourceKey key = ResourceKey.create(Registries.BIOME, new ResourceLocation("biomesoplenty", id)); @@ -141,11 +147,50 @@ public enum BiomeBand { private static List> resolveHolders(List> keys) { List> holders = new ArrayList<>(); for (ResourceKey key : keys) { - ForgeRegistries.BIOMES.getHolder(key).ifPresent(holders::add); + Holder holder = resolveOne(key); + if (holder != null) + holders.add(holder); } return holders; } + /** + * Résout un holder de biome de façon robuste : + * 1) registre vanilla {@link BuiltInRegistries} (toujours peuplé pour les + * biomes vanilla, fiable pendant la génération du monde) ; + * 2) registre Forge (biomes ajoutés par d'autres mods, ex. Biomes O' Plenty). + */ + /** + * Résout un holder de biome de façon robuste. + *

+ * Pendant la génération du monde, {@code ForgeRegistries.BIOMES} peut être + * vide (notamment sur les threads de génération asynchrone). On passe donc + * d'abord par le registre de biomes du serveur — celui-là même qu'utilise la + * worldgen — avant de retomber sur le registre Forge (biomes de mods). + */ + private static Holder resolveOne(ResourceKey key) { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + if (server != null) { + Registry reg = server.registryAccess().registryOrThrow(Registries.BIOME); + Holder holder = reg.getHolder(key).orElse(null); + if (holder != null) + return holder; + } + Holder holder = ForgeRegistries.BIOMES.getHolder(key).orElse(null); + if (holder != null) + return holder; + return ForgeRegistries.BIOMES.getHolder(key.location()).orElse(null); + } + + /** Holder de secours (plaine), résolu via le registre du serveur. */ + private static Holder fallbackHolder; + + public static Holder fallback() { + if (fallbackHolder == null) + fallbackHolder = resolveOne(Biomes.PLAINS); + return fallbackHolder; + } + public static List> allPossible() { List> all = new ArrayList<>(); for (BiomeBand band : values()) { @@ -159,8 +204,10 @@ public enum BiomeBand { } public static double getTemperatureAtZ(int blockZ, net.minecraft.world.level.levelgen.synth.ImprovedNoise noise) { - double raw = blockZ / 4000.0; - double noiseVal = noise.noise(blockZ * 0.00033, 0, 0) * 0.8; + // La largeur de bande est configurable (par défaut 4000 blocs). + double bandWidth = bandWidth(); + double raw = blockZ / bandWidth; + double noiseVal = noise.noise(blockZ * (1.32 / bandWidth), 0, 0) * 0.8; return Math.max(-3.0, Math.min(3.0, raw + noiseVal)); } @@ -179,4 +226,14 @@ public enum BiomeBand { idx = Math.max(0, Math.min(values().length - 1, idx)); return values()[idx]; } + + // --- Accès sûrs à la configuration (valeurs par défaut si non chargée) --- + + private static int bandWidth() { + return ModConfigs.SPEC.isLoaded() ? ModConfigs.WORLD_GEN.temperatureBandWidth.get() : 4000; + } + + private static boolean bopEnabled() { + return !ModConfigs.SPEC.isLoaded() || ModConfigs.WORLD_GEN.enableBOPBiomes.get(); + } } diff --git a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java index 289f8fb0..6091ddbe 100644 --- a/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java +++ b/src/main/java/net/mcreator/customoregen/worldgen/LatitudeBiomeSource.java @@ -9,6 +9,7 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.levelgen.synth.ImprovedNoise; +import net.mcreator.customoregen.config.ModConfigs; import java.util.List; import java.util.stream.Stream; @@ -27,7 +28,6 @@ public class LatitudeBiomeSource extends BiomeSource { private final ImprovedNoise moistureNoise; private final ImprovedNoise oceanNoise; private final ImprovedNoise biomeSelectorNoise; - private final List> possibleBiomes; public LatitudeBiomeSource(long seed) { this.seed = seed; @@ -36,7 +36,6 @@ public class LatitudeBiomeSource extends BiomeSource { this.moistureNoise = new ImprovedNoise(rng); this.oceanNoise = new ImprovedNoise(rng); this.biomeSelectorNoise = new ImprovedNoise(rng); - this.possibleBiomes = BiomeBand.allPossible(); } @Override @@ -46,7 +45,9 @@ public class LatitudeBiomeSource extends BiomeSource { @Override protected Stream> collectPossibleBiomes() { - return possibleBiomes.stream(); + // Résolution paresseuse : le registre du serveur n'est pas forcément + // disponible au moment de la construction du BiomeSource. + return BiomeBand.allPossible().stream(); } @Override @@ -58,18 +59,18 @@ public class LatitudeBiomeSource extends BiomeSource { double temperature = BiomeBand.getTemperatureAtZ(blockZ, temperatureNoise); double moisture = BiomeBand.getMoistureAtX(blockX, blockZ, moistureNoise); - if (BiomeBand.isOceanAt(blockX, blockZ, temperature, oceanNoise)) { + if (oceansEnabled() && BiomeBand.isOceanAt(blockX, blockZ, temperature, oceanNoise)) { List> oceans = BiomeBand.oceanFor(temperature); double pick = biomeSelectorNoise.noise(blockX * 0.005, blockZ * 0.005, 1000); int idx = (int) ((pick * 0.5 + 0.5) * oceans.size()); - return oceans.get(Math.max(0, Math.min(oceans.size() - 1, idx))); + return select(oceans, idx); } if (blockY < 0) { List> underground = BiomeBand.undergroundFor(temperature); double pick = biomeSelectorNoise.noise(blockX * 0.01, blockZ * 0.01, 2000); int idx = (int) ((pick * 0.5 + 0.5) * underground.size()); - return underground.get(Math.max(0, Math.min(underground.size() - 1, idx))); + return select(underground, idx); } BiomeBand band = BiomeBand.fromTemperature(temperature); @@ -78,9 +79,35 @@ public class LatitudeBiomeSource extends BiomeSource { biomes = BiomeBand.TEMPERATE.surface(); } - double pick = biomeSelectorNoise.noise(blockX * 0.0008, blockZ * 0.0008, 3000); + double selectorScale = 2.4 / biomeSize(); + double pick = biomeSelectorNoise.noise(blockX * selectorScale, blockZ * selectorScale, 3000); double adjusted = pick * 0.5 + moisture * 0.3; int idx = (int) ((adjusted * 0.5 + 0.5) * biomes.size()); - return biomes.get(Math.max(0, Math.min(biomes.size() - 1, idx))); + return select(biomes, idx); + } + + /** + * Sélectionne un biome dans la liste à l'indice donné, sans jamais lever + * d'exception : si la liste est vide (résolution de holders échouée), + * retourne un biome de secours garanti. + */ + private Holder select(List> list, int idx) { + if (list.isEmpty()) { + Holder fb = BiomeBand.fallback(); + if (fb != null) + return fb; + } + int clamped = Math.max(0, Math.min(list.size() - 1, idx)); + return list.get(clamped); + } + + // --- Accès sûrs à la configuration (valeurs par défaut si non chargée) --- + + private static boolean oceansEnabled() { + return !ModConfigs.SPEC.isLoaded() || ModConfigs.WORLD_GEN.enableOceans.get(); + } + + private static int biomeSize() { + return ModConfigs.SPEC.isLoaded() ? ModConfigs.WORLD_GEN.biomeSize.get() : 3000; } } diff --git a/src/main/java/net/mcreator/customoregen/worldgen/PlainsSpawnHandler.java b/src/main/java/net/mcreator/customoregen/worldgen/PlainsSpawnHandler.java index fbbd9a50..4856c9ac 100644 --- a/src/main/java/net/mcreator/customoregen/worldgen/PlainsSpawnHandler.java +++ b/src/main/java/net/mcreator/customoregen/worldgen/PlainsSpawnHandler.java @@ -1,6 +1,7 @@ package net.mcreator.customoregen.worldgen; import net.mcreator.customoregen.CustomOreGenMod; +import net.mcreator.customoregen.config.ModConfigs; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.biome.Biomes; @@ -14,17 +15,14 @@ import net.minecraft.world.entity.player.Player; @Mod.EventBusSubscriber(modid = CustomOreGenMod.MODID) public class PlainsSpawnHandler { - private static boolean hasSetSpawn = false; - @SubscribeEvent public static void onPlayerJoin(EntityJoinLevelEvent event) { - if (hasSetSpawn) return; if (!(event.getEntity() instanceof Player player)) return; if (!(event.getLevel() instanceof ServerLevel level)) return; if (!level.dimensionType().natural()) return; - hasSetSpawn = true; - + // Garde naturel : si le spawn a déjà été déplacé (non nul), on ne fait plus rien. + // Évite le booléen statique global qui ne se déclenchait qu'une fois par serveur. if (level.getSharedSpawnPos().getX() != 0 || level.getSharedSpawnPos().getZ() != 0) return; BlockPos spawn = findPlainsSpawn(level); @@ -33,7 +31,7 @@ public class PlainsSpawnHandler { } private static BlockPos findPlainsSpawn(ServerLevel level) { - int radius = 100; + int radius = ModConfigs.SPEC.isLoaded() ? ModConfigs.WORLD_GEN.spawnSearchRadius.get() : 100; BlockPos bestPos = new BlockPos(0, 64, 0); double bestDistance = Double.MAX_VALUE; diff --git a/src/main/java/net/mcreator/customoregen/worldgen/WelcomeMessageHandler.java b/src/main/java/net/mcreator/customoregen/worldgen/WelcomeMessageHandler.java index e2d6161e..ec9c4a4f 100644 --- a/src/main/java/net/mcreator/customoregen/worldgen/WelcomeMessageHandler.java +++ b/src/main/java/net/mcreator/customoregen/worldgen/WelcomeMessageHandler.java @@ -1,6 +1,7 @@ package net.mcreator.customoregen.worldgen; import net.mcreator.customoregen.CustomOreGenMod; +import net.mcreator.customoregen.config.ModConfigs; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; @@ -13,19 +14,22 @@ import net.minecraftforge.fml.common.Mod; @Mod.EventBusSubscriber(modid = CustomOreGenMod.MODID) public class WelcomeMessageHandler { - private static boolean hasShownMessage = false; + private static final String WELCOMED_KEY = "custom_ore_gen_welcomed"; @SubscribeEvent public static void onPlayerJoin(EntityJoinLevelEvent event) { - if (hasShownMessage) return; if (!(event.getEntity() instanceof Player player)) return; if (!(event.getLevel() instanceof ServerLevel level)) return; - hasShownMessage = true; + // Message configurable et envoyé UNE fois par joueur (persisté dans ses données). + if (ModConfigs.SPEC.isLoaded() && !ModConfigs.WORLD_GEN.enableWelcomeMessage.get()) return; + if (player.getPersistentData().getBoolean(WELCOMED_KEY)) return; ChunkGenerator generator = level.getChunkSource().getGenerator(); if (!(generator.getBiomeSource() instanceof LatitudeBiomeSource)) return; + player.getPersistentData().putBoolean(WELCOMED_KEY, true); + player.sendSystemMessage(Component.literal("")); player.sendSystemMessage(Component.literal("\u00A76\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550")); player.sendSystemMessage(Component.literal("\u00A7e Custom Ore Gen \u00BB Mode Latitude")); diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 2961c429..651c484e 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -4,7 +4,7 @@ license="Not specified" [[mods]] modId="custom_ore_gen" -version="2.2.0-forge" +version="4.5-forge" displayName="Custom Ore Gen" displayURL="https://lanro.eu" credits="Created using mod maker MCreator - https://mcreator.net/about"