diff --git a/build.gradle b/build.gradle index ab8ef641..69e0ec49 100644 --- a/build.gradle +++ b/build.gradle @@ -39,6 +39,7 @@ idea { } minecraft { + accessTransformer = file("src/main/resources/META-INF/accesstransformer.cfg") // The mappings can be changed at any time and must be in the following format. // Channel: Version: // official MCVersion Official field/method names from Mojang mapping files diff --git a/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea b/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea index 3fb0164c..cc4df587 100644 --- a/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea +++ b/src/generated/resources/.cache/fed443662143001aeb5341375f6f5ef31d10baea @@ -1,10 +1,14 @@ -// 1.20.1 2025-11-11T12:39:11.546555 CreateNuclear Generated Registry Entries +// 1.20.1 2025-11-24T20:36:32.0462092 CreateNuclear Generated Registry Entries 5edbd74546f4088818e02bb7a5c5eb2ecfe25623 data/createnuclear/forge/biome_modifier/lead_ore.json 72173023e6a31748692e750db0f5fa8c555d1009 data/createnuclear/forge/biome_modifier/striated_ores_overworld.json fa32145101dc12ec914684fec8c5cbb995d2c051 data/createnuclear/forge/biome_modifier/uranium_ore.json +bec3aa19be2740b8347902856a2ad920b0641804 data/createnuclear/worldgen/biome/irradiated_plain.json b68555f371c9700aa4ecfa9370b010de8fe25b60 data/createnuclear/worldgen/configured_feature/lead_ore.json 4f11c0a518c0de7857919983fc638ba551c6630a data/createnuclear/worldgen/configured_feature/striated_ores_overworld.json b0e1ee7314412507fd7346cb48b29d105f6186ad data/createnuclear/worldgen/configured_feature/uranium_ore.json +59d61c02881d710b0426a0955f6945b7a12d219f data/createnuclear/worldgen/density_function/irradiated/erosion.json +59d61c02881d710b0426a0955f6945b7a12d219f data/createnuclear/worldgen/density_function/irradiated/final_density.json +0c0e4c64dfa900623b5660f08007b3449a1c67bb data/createnuclear/worldgen/noise_settings/irradiated_noise.json d45ed5f7008864ba4f60c409038ad428a280fd7f data/createnuclear/worldgen/placed_feature/lead_ore.json f26be417cb34461ecb180e77a9a749eaaf4c9880 data/createnuclear/worldgen/placed_feature/striated_ores_overworld.json bed936158c61471513252910d9e3b0e2de610f1a data/createnuclear/worldgen/placed_feature/uranium_ore.json diff --git a/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_plain.json b/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_plain.json new file mode 100644 index 00000000..0e531893 --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/biome/irradiated_plain.json @@ -0,0 +1,49 @@ +{ + "carvers": { + "air": "minecraft:nether_cave" + }, + "downfall": 0.0, + "effects": { + "fog_color": 329011, + "mood_sound": { + "block_search_extent": 8, + "offset": 2.0, + "sound": "minecraft:ambient.cave", + "tick_delay": 6000 + }, + "particle": { + "options": { + "type": "createnuclear:irradiated_particles", + "t": 0 + }, + "probability": 0.025 + }, + "sky_color": 0, + "water_color": 4159204, + "water_fog_color": 329011 + }, + "features": [ + [], + [], + [], + [ + "minecraft:blue_ice" + ], + [ + "minecraft:void_start_platform" + ] + ], + "has_precipitation": false, + "spawn_costs": {}, + "spawners": { + "ambient": [], + "axolotls": [], + "creature": [], + "misc": [], + "monster": [], + "underground_water_creature": [], + "water_ambient": [], + "water_creature": [] + }, + "temperature": 2.0 +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json new file mode 100644 index 00000000..feb1cdbd --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/erosion.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:add", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 0, + "to_value": -1.0, + "to_y": 90 + }, + "argument2": { + "type": "minecraft:old_blended_noise", + "smear_scale_multiplier": 8.0, + "xz_factor": 80.0, + "xz_scale": 0.25, + "y_factor": 160.0, + "y_scale": 0.375 + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json new file mode 100644 index 00000000..feb1cdbd --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/density_function/irradiated/final_density.json @@ -0,0 +1,18 @@ +{ + "type": "minecraft:add", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 0, + "to_value": -1.0, + "to_y": 90 + }, + "argument2": { + "type": "minecraft:old_blended_noise", + "smear_scale_multiplier": 8.0, + "xz_factor": 80.0, + "xz_scale": 0.25, + "y_factor": 160.0, + "y_scale": 0.375 + } +} \ No newline at end of file diff --git a/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json b/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json new file mode 100644 index 00000000..34944bbc --- /dev/null +++ b/src/generated/resources/data/createnuclear/worldgen/noise_settings/irradiated_noise.json @@ -0,0 +1,363 @@ +{ + "aquifers_enabled": false, + "default_block": { + "Name": "createnuclear:steel_block" + }, + "default_fluid": { + "Name": "minecraft:air" + }, + "disable_mob_generation": false, + "legacy_random_source": false, + "noise": { + "height": 256, + "min_y": -32, + "size_horizontal": 1, + "size_vertical": 2 + }, + "noise_router": { + "barrier": 1.0, + "continents": "minecraft:overworld/continents", + "depth": "minecraft:overworld/depth", + "erosion": "createnuclear:irradiated/erosion", + "final_density": { + "type": "minecraft:blend_density", + "argument": "createnuclear:irradiated/final_density" + }, + "fluid_level_floodedness": 0.0, + "fluid_level_spread": 0.0, + "initial_density_without_jaggedness": { + "type": "minecraft:add", + "argument1": 0.1171875, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 0.0, + "from_y": -30, + "to_value": 1.0, + "to_y": -40 + }, + "argument2": { + "type": "minecraft:add", + "argument1": -0.1171875, + "argument2": { + "type": "minecraft:add", + "argument1": -0.078125, + "argument2": { + "type": "minecraft:mul", + "argument1": { + "type": "minecraft:y_clamped_gradient", + "from_value": 1.0, + "from_y": 240, + "to_value": 0.0, + "to_y": 256 + }, + "argument2": { + "type": "minecraft:add", + "argument1": 0.078125, + "argument2": { + "type": "minecraft:clamp", + "input": { + "type": "minecraft:add", + "argument1": -0.703125, + "argument2": { + "type": "minecraft:mul", + "argument1": 4.0, + "argument2": { + "type": "minecraft:quarter_negative", + "argument": { + "type": "minecraft:mul", + "argument1": "minecraft:overworld/depth", + "argument2": { + "type": "minecraft:cache_2d", + "argument": "minecraft:overworld/factor" + } + } + } + } + }, + "max": 64.0, + "min": -30.0 + } + } + } + } + } + } + }, + "lava": 0.0, + "ridges": "minecraft:overworld/ridges", + "temperature": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:temperature", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.25, + "y_scale": 0.0 + }, + "vegetation": { + "type": "minecraft:shifted_noise", + "noise": "minecraft:vegetation", + "shift_x": "minecraft:shift_x", + "shift_y": 0.0, + "shift_z": "minecraft:shift_z", + "xz_scale": 0.0, + "y_scale": 0.0 + }, + "vein_gap": 0.0, + "vein_ridged": 0.0, + "vein_toggle": 0.0 + }, + "ore_veins_enabled": false, + "sea_level": 32, + "spawn_target": [ + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + -1.0, + -0.16 + ] + }, + { + "continentalness": [ + -0.11, + 1.0 + ], + "depth": 0.0, + "erosion": [ + -1.0, + 1.0 + ], + "humidity": [ + -1.0, + 1.0 + ], + "offset": 0.0, + "temperature": [ + -1.0, + 1.0 + ], + "weirdness": [ + 0.16, + 1.0 + ] + } + ], + "surface_rule": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_plain" + ] + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0465, + "min_threshold": 0.035, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:lead_ore" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.0545, + "min_threshold": 0.039, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:lead_block" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:noise_threshold", + "max_threshold": 0.069, + "min_threshold": 0.0545, + "noise": "createnuclear:irradiated/erosion" + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "above_bottom": 5 + }, + "random_name": "minecraft:bedrock_floor", + "true_at_and_below": { + "above_bottom": 0 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "minecraft:bedrock" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:above_preliminary_surface" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": false, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_plain" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:lead_ore" + } + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:stone_depth", + "add_surface_depth": true, + "offset": 0, + "secondary_depth_range": 0, + "surface_type": "floor" + }, + "then_run": { + "type": "minecraft:sequence", + "sequence": [ + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [ + "createnuclear:irradiated_plain" + ] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:raw_lead_block" + } + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:biome", + "biome_is": [] + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:steel_block" + } + } + } + ] + } + } + ] + } + }, + { + "type": "minecraft:condition", + "if_true": { + "type": "minecraft:vertical_gradient", + "false_at_and_above": { + "absolute": 4 + }, + "random_name": "minecraft:lunaslate", + "true_at_and_below": { + "absolute": -4 + } + }, + "then_run": { + "type": "minecraft:block", + "result_state": { + "Name": "createnuclear:enriched_soul_soil" + } + } + } + ] + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java b/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java new file mode 100644 index 00000000..00d41dd8 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/CNParticleTypes.java @@ -0,0 +1,69 @@ +package net.nuclearteam.createnuclear; + +import com.simibubi.create.foundation.particle.ICustomParticleData; +import net.createmod.catnip.lang.Lang; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RegisterParticleProvidersEvent; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.nuclearteam.createnuclear.content.particles.IrradiatedParticlesData; + +import java.util.function.Supplier; + +public enum CNParticleTypes { + IRRADIATED_PARTICLES(IrradiatedParticlesData::new), + ; + + private final ParticleEntry entry; + + CNParticleTypes(Supplier> typeFactory) { + String name = Lang.asId(name()); + entry = new ParticleEntry<>(name, typeFactory); + } + + public static void register(IEventBus modEventBus) { + ParticleEntry.REGISTER.register(modEventBus); + } + + @OnlyIn(Dist.CLIENT) + public static void registerFactories(RegisterParticleProvidersEvent event) { + for (CNParticleTypes particle : values()) + particle.entry.registerFactory(event); + } + + public ParticleType get() { + return entry.object.get(); + } + + public String parameter() { + return entry.name; + } + + + private static class ParticleEntry { + private static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, CreateNuclear.MOD_ID); + + private final String name; + private final Supplier> typeFactory; + private final RegistryObject> object; + + public ParticleEntry(String name, Supplier> typeFactory) { + this.name = name; + this.typeFactory = typeFactory; + + object = REGISTER.register(name, () -> this.typeFactory.get().createType()); + } + + @OnlyIn(Dist.CLIENT) + public void registerFactory(RegisterParticleProvidersEvent event) { + typeFactory.get() + .register(object.get(), event); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java b/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java index 0a00d94f..c5f73f93 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java +++ b/src/main/java/net/nuclearteam/createnuclear/CreateNuclear.java @@ -72,6 +72,7 @@ public static void onInitialize() { CNCreativeModeTabs.register(modEventBus); CNEffects.register(modEventBus); CNPotions.register(modEventBus); + CNParticleTypes.register(modEventBus); CNRecipeTypes.register(modEventBus); CNAttributes.register(modEventBus); diff --git a/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java b/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java index fbf15823..c5c91c36 100644 --- a/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java +++ b/src/main/java/net/nuclearteam/createnuclear/CreateNuclearClient.java @@ -10,6 +10,7 @@ public class CreateNuclearClient { public static void onCtorClient(IEventBus modEventBus, IEventBus forgeEventBus) { modEventBus.addListener(CreateNuclearClient::clientInit); + modEventBus.addListener(CNParticleTypes::registerFactories); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/IrradiationCurseEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/IrradiationCurseEffect.java index 5f3d7042..895909a9 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/effects/IrradiationCurseEffect.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/effects/IrradiationCurseEffect.java @@ -26,7 +26,7 @@ public class IrradiationCurseEffect extends VicinityEffect { public IrradiationCurseEffect(MobEffectCategory category, int color) { super(category, color, amplifier -> 15, - e -> !e.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag) && !e.hasEffect(CNEffects.RADIATION.get()), + (e) -> !e.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag) && !e.hasEffect(CNEffects.RADIATION.get()), timer -> {}, () -> new MobEffectInstance(MobEffects.ABSORPTION, 300)); } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java index bc92be83..ddcff2b8 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/effects/RadiationEffect.java @@ -4,9 +4,11 @@ import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.nuclearteam.createnuclear.CNEffects; import net.nuclearteam.createnuclear.CNTags; +import net.nuclearteam.createnuclear.CreateNuclear; import net.nuclearteam.createnuclear.content.equipment.armor.AntiRadiationArmorItem; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.attributes.AttributeModifier; @@ -20,14 +22,16 @@ public class RadiationEffect extends VicinityEffect { public RadiationEffect() { super(MobEffectCategory.HARMFUL, 15453236, amplifier -> 10, - e -> { - boolean isWearingAntiRadiationArmor = false; - for (ItemStack armor : e.getArmorSlots()) { - if (AntiRadiationArmorItem.Armor.isArmored(armor)) { - isWearingAntiRadiationArmor = true; - break; - } - } + (e) -> { + + boolean isWearingAntiRadiationArmor = AntiRadiationArmorItem.Armor.isFullSet(e.getArmorSlots()); +// for (ItemStack armor : e.getArmorSlots()) { +// CreateNuclear.LOGGER.warn("AntiRadiationArmorItem.Armor.isFullSet(armor) {}", AntiRadiationArmorItem.Armor.isFullSet(armor)); +// if (AntiRadiationArmorItem.Armor.isFullSet(armor)) { +// isWearingAntiRadiationArmor = true; +// break; +// } +// } return !e.getType().is(CNTags.CNEntityTags.IRRADIATED_IMMUNE.tag) && !e.hasEffect(CNEffects.RADIATION.get()) @@ -67,6 +71,12 @@ public boolean isDurationEffectTick(int duration, int amplifier) { public void applyEffectTick(LivingEntity entity, int amplifier) { super.applyEffectTick(entity, amplifier); + // Do not apply damage if the entity is wearing anti-radiation armor + boolean wearingAntiRad = AntiRadiationArmorItem.Armor.isFullSet(entity.getArmorSlots()); + if (wearingAntiRad) { + return; + } + // Apply radiation damage (magic type), scaled by amplifier int damage = 1 << amplifier; entity.hurt(entity.damageSources().magic(), damage); diff --git a/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java b/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java index f3f8b3f5..179f918b 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/effects/VicinityEffect.java @@ -4,23 +4,22 @@ import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.Entity; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.LivingEntity; -import net.nuclearteam.createnuclear.CNBlocks; import net.nuclearteam.createnuclear.CreateNuclear; -import org.jetbrains.annotations.Nullable; +import java.util.HashMap; import java.util.List; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.function.UnaryOperator; +import java.util.Map; +import java.util.UUID; +import java.util.function.*; public class VicinityEffect extends MobEffect { private final UnaryOperator areaSize; private final Predicate filter; private final Supplier[] effects; - private int cooldownTicks = 500; + private final Map cooldowns = new HashMap<>(); @SafeVarargs protected VicinityEffect(MobEffectCategory category, int color, UnaryOperator areaSize, Predicate filter, Consumer timer, Supplier... effects) { @@ -33,21 +32,41 @@ protected VicinityEffect(MobEffectCategory category, int color, UnaryOperator nearbyEntities = entity.level().getEntities(entity, entity.getBoundingBox().inflate(areaSize.apply(amplifier)), e -> e instanceof LivingEntity target && filter.test(target)); + List nearbyEntities = entity.level().getEntities(entity, entity.getBoundingBox().inflate(areaSize.apply(amplifier)), e -> e instanceof LivingEntity target && filter.test(target)); for (Entity nearbyEntity : nearbyEntities) { LivingEntity nearby = (LivingEntity) nearbyEntity; - for (Supplier effect : effects) { - if (cooldownTicks == 0) { - nearby.addEffect(effect.get()); - cooldownTicks = 500; - } else { - cooldownTicks--; - CreateNuclear.LOGGER.warn("Test Duree: {}, entity: {}", cooldownTicks, nearby.getUUID()); + int couldown = getCooldown(nearby); + if (couldown <= 0) { + for (Supplier effect : effects) { + nearby.addEffect(effect.get()); } + + setCooldown(nearby, 500); + + } else { + setCooldown(nearby, couldown - 1); + CreateNuclear.LOGGER.warn("Test Duree: {}, entity: {}", couldown, nearby.getUUID()); } } + + + // Clean up cooldowns only on the server: remove entries whose entity is gone or marked removed. + if (entity.level() instanceof ServerLevel serverLevel) { + cooldowns.entrySet().removeIf(entry -> { + Entity e = serverLevel.getEntity(entry.getKey()); + return e == null || e.isRemoved(); + }); + } + } + + private int getCooldown(LivingEntity entity) { + return cooldowns.getOrDefault(entity.getUUID(), 0); + } + + private void setCooldown(LivingEntity entity, int ticks) { + cooldowns.put(entity.getUUID(), ticks); } @Override diff --git a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java index 2d3a7f18..ee7316f4 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/equipment/armor/AntiRadiationArmorItem.java @@ -8,6 +8,7 @@ import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeModifier; import net.minecraft.world.item.*; @@ -38,15 +39,15 @@ public class AntiRadiationArmorItem { public static class Helmet extends ArmorItem { protected final DyeColor color; - private final Multimap attributeModifiers; +// private final Multimap attributeModifiers; public Helmet(Properties properties, DyeColor color) { super(ARMOR_MATERIAL, HELMET, properties); this.color = color; - ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); - UUID uuid = ARMOR_MODIFIER_UUID_PER_TYPE.get(HELMET); - builder.put(CNAttributes.IRRADIATED_RESISTANCE.get(), new AttributeModifier(uuid, "Armor Resistance Irradiation", 42, AttributeModifier.Operation.ADDITION)); - this.attributeModifiers = builder.build(); +// ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); +// UUID uuid = ARMOR_MODIFIER_UUID_PER_TYPE.get(HELMET); +// builder.put(CNAttributes.IRRADIATED_RESISTANCE.get(), new AttributeModifier(uuid, "Armor Resistance Irradiation", 42, AttributeModifier.Operation.ADDITION)); +// this.attributeModifiers = builder.build(); } @Override @@ -107,10 +108,10 @@ public static TagKey getHelmetTag(String key) { : CNItemTags.ANTI_RADIATION_HELMET_DYE.tag; } - @Override - public Multimap getDefaultAttributeModifiers(EquipmentSlot pEquipmentSlot) { - return pEquipmentSlot == this.type.getSlot() ? this.attributeModifiers : super.getDefaultAttributeModifiers(pEquipmentSlot); - } +// @Override +// public Multimap getDefaultAttributeModifiers(EquipmentSlot pEquipmentSlot) { +// return pEquipmentSlot == this.type.getSlot() ? this.attributeModifiers : super.getDefaultAttributeModifiers(pEquipmentSlot); +// } } public static class Chestplate extends ArmorItem { @@ -321,18 +322,52 @@ public static ItemEntry getLeggingsByColor(DyeColor color) { return leggingsMap.get(color); } - public static boolean isArmored(ItemStack item) { - return helmetMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) || - chestplateMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) || - leggingsMap.values().stream().anyMatch(entry -> entry.is(item.getItem())); + /** + * Returns true if the given ItemStack corresponds to any piece of the anti-radiation armor. + */ + public static boolean isAnyPiece(ItemStack item) { + return helmetMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) + || chestplateMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) + || leggingsMap.values().stream().anyMatch(entry -> entry.is(item.getItem())) + || CNItems.ANTI_RADIATION_BOOTS.is(item.getItem()); + } + + /** + * Returns true when the provided armor stacks contain a full anti-radiation set + * (helmet, chestplate, leggings and boots). + */ + public static boolean isFullSet(Iterable armorStacks) { + boolean hasHelmet = false; + boolean hasChestplate = false; + boolean hasLeggings = false; + boolean hasBoots = false; + + for (ItemStack itemStack : armorStacks) { + Item item = itemStack.getItem(); + if (CNItems.ANTI_RADIATION_HELMETS.contains(item)) { + hasHelmet = true; + } else if (CNItems.ANTI_RADIATION_CHESTPLATES.contains(item)) { + hasChestplate = true; + } else if (CNItems.ANTI_RADIATION_LEGGINGS.contains(item)) { + hasLeggings = true; + } else if (CNItems.ANTI_RADIATION_BOOTS.is(item)) { + hasBoots = true; + } + } + + return hasHelmet && hasChestplate && hasLeggings && hasBoots; + } + + /** + * Returns true when the given entity is fully wearing the anti-radiation set. + */ + public static boolean isFullSet(LivingEntity entity) { + return isFullSet(entity.getArmorSlots()); } + /** Alias for {@link #isAnyPiece(ItemStack)} kept for compatibility. */ public static boolean isArmored2(ItemStack item) { - return CNItems.ANTI_RADIATION_HELMETS.contains(item.getItem()) - || CNItems.ANTI_RADIATION_CHESTPLATES.contains(item.getItem()) - || CNItems.ANTI_RADIATION_LEGGINGS.contains(item.getItem()) - || CNItems.ANTI_RADIATION_BOOTS.is(item.getItem()) - ; + return isAnyPiece(item); } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java index a6406ae2..b9b5cfdb 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/bluePrintItem/ReactorBluePrintMenu.java @@ -11,6 +11,8 @@ import net.minecraft.world.item.Items; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; import net.nuclearteam.createnuclear.CNMenus; import net.nuclearteam.createnuclear.CNTags; @@ -66,7 +68,7 @@ protected void initAndReadInventory(ItemStack contentHolder) { } @Override - protected net.minecraftforge.items.ItemStackHandler createGhostInventory() { + protected ItemStackHandler createGhostInventory() { return getItemStorage(contentHolder); } @@ -100,7 +102,7 @@ private void addPatternSlots() { }; for (int[] pos : positions) {// up and down not middle - this.addSlot(new net.minecraftforge.items.SlotItemHandler(ghostInventory,i, startWidth + incr * pos[0], startHeight + incr * pos[1])); + this.addSlot(new SlotItemHandler(ghostInventory,i, startWidth + incr * pos[0], startHeight + incr * pos[1])); i++; } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java index cbdee861..9f732b96 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/casing/ReactorCasing.java @@ -3,9 +3,12 @@ import com.simibubi.create.content.equipment.wrench.IWrenchable; import com.simibubi.create.foundation.block.IBE; import net.minecraft.MethodsReturnNonnullByDefault; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Vec3i; +import net.minecraft.core.*; +import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; import net.minecraft.util.StringRepresentable; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -13,21 +16,32 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.biome.BiomeResolver; +import net.minecraft.world.level.biome.Biomes; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; +import net.minecraft.world.level.chunk.ChunkStatus; +import net.minecraft.world.level.levelgen.structure.BoundingBox; +import net.minecraft.world.phys.Vec3; import net.nuclearteam.createnuclear.CNBlockEntityTypes; import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlock; import net.nuclearteam.createnuclear.content.multiblock.controller.ReactorControllerBlockEntity; import net.nuclearteam.createnuclear.content.multiblock.input.ReactorInput; import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault @@ -44,6 +58,8 @@ public ReactorCasing(Properties properties, TypeBlock tBlock) { @Override // Called when the block is placed on the world public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { super.onPlace(state, level, pos, oldState, movedByPiston); + // change nearby chunks' biomes to the mod biome (radius in blocks) + changeBiome(CNBiomes.Irradiated.PLAIN, 12, pos, (ServerLevel) level); List players = level.players(); FindController(pos, level, players, true); } @@ -97,6 +113,45 @@ public ReactorControllerBlock FindController(BlockPos blockPos, Level level, Lis return null; } + public void changeBiome(ResourceKey biomeResourceKey, int radius, BlockPos center, ServerLevel serverLevel) { + // radius is in blocks; we convert to chunk/section coords + Registry biomeRegistry = serverLevel.registryAccess().registryOrThrow(Registries.BIOME); + Holder biomeHolder = biomeRegistry.getHolderOrThrow(biomeResourceKey); + + // If the center biome is already the target biome, skip whole operation + Holder current = serverLevel.getBiome(center); + Optional> currentKey = current.unwrapKey(); + if (currentKey.isPresent() && currentKey.get().equals(biomeResourceKey)) { + CreateNuclear.LOGGER.info("changeBiome: center already irradiated: {}", currentKey.get()); + return; + } + + int minX = center.getX() - radius; + int maxX = center.getX() + radius; + int minZ = center.getZ() - radius; + int maxZ = center.getZ() + radius; + + ArrayList chunks = new ArrayList<>(); + + for (int cz = SectionPos.blockToSectionCoord(minZ); cz <= SectionPos.blockToSectionCoord(maxZ); ++cz) { + for (int cx = SectionPos.blockToSectionCoord(minX); cx <= SectionPos.blockToSectionCoord(maxX); ++cx) { + ChunkAccess chunkAccess = serverLevel.getChunk(cx, cz, ChunkStatus.FULL, false); + if (chunkAccess != null) { + chunkAccess.fillBiomesFromNoise(makeResolver(biomeHolder), serverLevel.getChunkSource().randomState().sampler()); + chunkAccess.setUnsaved(true); + chunks.add(chunkAccess); + } + } + } + + // Inform players/clients about biome changes for affected chunks + serverLevel.getChunkSource().chunkMap.resendBiomesForChunks(chunks); + } + + public static BiomeResolver makeResolver(Holder biomeHolder) { + return (x, y, z, climateSampler) -> biomeHolder; + } + @Override public Class getBlockEntityClass() { return ReactorCasingEntity.class; diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java new file mode 100644 index 00000000..e199d6a0 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticles.java @@ -0,0 +1,50 @@ +package net.nuclearteam.createnuclear.content.particles; + +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.particle.*; +import net.minecraft.util.RandomSource; + +import javax.annotation.Nullable; + +public class IrradiatedParticles extends TextureSheetParticle { + protected IrradiatedParticles(ClientLevel pLevel, double pX, double pY, double pZ, + SpriteSet spriteSet, double pXSpeed, double pYSpeed, double pZSpeed) { + super(pLevel, pX, pY, pZ, pXSpeed, pYSpeed, pZSpeed); + + RandomSource randomSource = level.random; + + this.xo = randomSource.nextGaussian() * (double)1.0E-6f; + this.yo = randomSource.nextGaussian() * (double)1.0E-4f; + this.zo = randomSource.nextGaussian() * (double)1.0E-6f; + + this.quadSize *= this.random.nextFloat() * 0.6f + 0.6f; + this.hasPhysics = false; + this.gravity = 0.0f; + + this.friction = 0.8f; + this.lifetime = 40; + + this.setSpriteFromAge(spriteSet); + + } + + @Override + public ParticleRenderType getRenderType() { + return ParticleRenderType.PARTICLE_SHEET_TRANSLUCENT; + } + + public static class Provider implements ParticleProvider { + private final SpriteSet spriteSet; + + public Provider(SpriteSet spriteSet) { + this.spriteSet = spriteSet; + } + + @Nullable + @Override + public Particle createParticle(IrradiatedParticlesData pType, ClientLevel pLevel, double pX, double pY, double pZ, + double pXSpeed, double pYSpeed, double pZSpeed) { + return new IrradiatedParticles(pLevel, pX, pY, pZ, this.spriteSet, pXSpeed, pYSpeed, pZSpeed); + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java new file mode 100644 index 00000000..feec3db6 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/particles/IrradiatedParticlesData.java @@ -0,0 +1,84 @@ +package net.nuclearteam.createnuclear.content.particles; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.foundation.particle.ICustomParticleDataWithSprite; +import net.minecraft.client.particle.ParticleEngine.SpriteParticleRegistration; +import net.minecraft.core.particles.ParticleOptions; +import net.minecraft.core.particles.ParticleType; +import net.minecraft.network.FriendlyByteBuf; +import net.nuclearteam.createnuclear.CNParticleTypes; + +import java.util.Locale; + +public class IrradiatedParticlesData implements ParticleOptions, ICustomParticleDataWithSprite { + + public static final Codec CODEC = RecordCodecBuilder.create(i -> + i.group( + Codec.INT.fieldOf("t").forGetter(p -> p.t) + ) + .apply(i, IrradiatedParticlesData::new) + ); + + public static final Deserializer DESERIALIZER = + new Deserializer<>() { + @Override + public IrradiatedParticlesData fromCommand(ParticleType particleType, StringReader reader) throws CommandSyntaxException { + return new IrradiatedParticlesData(); + } + + @Override + public IrradiatedParticlesData fromNetwork(ParticleType particleType, FriendlyByteBuf buffer) { + return new IrradiatedParticlesData(); + } + }; + + + int t; + + public IrradiatedParticlesData(int _t) { + t = _t; + } + + public IrradiatedParticlesData() { + this(0); + } + + @Override + public ParticleType getType() { + return CNParticleTypes.IRRADIATED_PARTICLES.get(); + } + + @Override + public void writeToNetwork(FriendlyByteBuf buffer) { + buffer.writeInt(t); + } + + @Override + public String writeToString() { + return String.format(Locale.ROOT, "%s %d", CNParticleTypes.IRRADIATED_PARTICLES.parameter(), t); + } + + @Override + public Deserializer getDeserializer() { + return DESERIALIZER; + } + + @Override + public Codec getCodec(ParticleType type) { + return CODEC; + } + + @Override + public SpriteParticleRegistration getMetaFactory() { + return IrradiatedParticles.Provider::new; + } + + + + + + +} diff --git a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java index ca843bc0..38730852 100644 --- a/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java +++ b/src/main/java/net/nuclearteam/createnuclear/foundation/events/CommentEvents.java @@ -1,5 +1,6 @@ package net.nuclearteam.createnuclear.foundation.events; +import net.minecraft.core.Holder; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.util.TimeUtil; @@ -12,15 +13,19 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.LevelEvent; import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent.Phase; import net.minecraftforge.event.TickEvent.ServerTickEvent; import net.minecraftforge.event.entity.EntityJoinLevelEvent; import net.minecraftforge.event.entity.living.*; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.Event; import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.nuclearteam.createnuclear.CNEffects; @@ -29,6 +34,8 @@ import net.nuclearteam.createnuclear.CNTags; import net.nuclearteam.createnuclear.content.contraptions.irradiated.IrradiatedAnimal; import net.nuclearteam.createnuclear.content.contraptions.irradiated.chicken.IrradiatedChicken; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import org.spongepowered.asm.mixin.MixinEnvironment; @Mod.EventBusSubscriber public class CommentEvents { @@ -49,6 +56,23 @@ public static void onEntityJoinWorld(EntityJoinLevelEvent event) { } } + @SubscribeEvent + public static void onServerWorldTick(LivingEvent.LivingTickEvent event) { + LivingEntity entityLiving = event.getEntity(); + Level world = entityLiving.level(); + if (world == null) + return; + + if (world.isClientSide) + return; + if (entityLiving.tickCount % 20 == 0) return; + if (entityLiving instanceof Player p && p.isSpectator()) return; + Holder biome = world.getBiome(entityLiving.getOnPos()); + if (biome.is(CNBiomes.Irradiated.PLAIN)){ + entityLiving.addEffect(new MobEffectInstance(CNEffects.RADIATION.get(),600,0, false, true, true)); + } + } + @SubscribeEvent public static void onEntityInteract(PlayerInteractEvent.EntityInteract event) { Entity entity = event.getTarget(); diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java index e13ab777..2da7db37 100644 --- a/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/data/GeneratedEntriesProvider.java @@ -12,6 +12,10 @@ import net.nuclearteam.createnuclear.infrastructure.worldgen.CNBiomeModifiers; import net.nuclearteam.createnuclear.infrastructure.worldgen.CNConfiguredFeatures; import net.nuclearteam.createnuclear.infrastructure.worldgen.CNPlacedFeatures; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNDensityFunctions; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseData; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseGeneratorSettings; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -23,6 +27,10 @@ public class GeneratedEntriesProvider extends DatapackBuiltinEntriesProvider { .add(Registries.CONFIGURED_FEATURE, (RegistryBootstrap) CNConfiguredFeatures::bootstrap) .add(Registries.PLACED_FEATURE, CNPlacedFeatures::bootstrap) .add(ForgeRegistries.Keys.BIOME_MODIFIERS, CNBiomeModifiers::bootstrap) + .add(Registries.BIOME, CNBiomes::bootstrapRegistries) + .add(Registries.DENSITY_FUNCTION, CNDensityFunctions::bootstrapRegistries) + .add(Registries.NOISE_SETTINGS, CNNoiseGeneratorSettings::bootstrapRegistries) + .add(Registries.NOISE, CNNoiseData::bootstrapRegistries) ; public GeneratedEntriesProvider(PackOutput output, CompletableFuture registries) { diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java new file mode 100644 index 00000000..e20dbd6b --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNBiomes.java @@ -0,0 +1,28 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.*; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.nuclearteam.createnuclear.CreateNuclear; +import org.jetbrains.annotations.NotNull; + +public class CNBiomes { + public static final class Irradiated { + public static final ResourceKey PLAIN = key("irradiated_plain"); + } + + public static void bootstrapRegistries(BootstapContext context) { + HolderGetter featureLookup = context.lookup(Registries.PLACED_FEATURE); + HolderGetter> carverLookup = context.lookup(Registries.CONFIGURED_CARVER); + + context.register(Irradiated.PLAIN, IrradiatedBiomes.createPlain(featureLookup, carverLookup)); + } + + public static @NotNull ResourceKey key(String id) { + return ResourceKey.create(Registries.BIOME, CreateNuclear.asResource(id)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java new file mode 100644 index 00000000..1528bd14 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNDensityFunctions.java @@ -0,0 +1,50 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.DensityFunctions; +import net.minecraft.world.level.levelgen.NoiseRouterData; +import net.minecraft.world.level.levelgen.synth.BlendedNoise; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class CNDensityFunctions { + public static final ResourceKey NOODLES = createKey("caves/noodles"); + + public static final class Irradiated { + public static final ResourceKey EROSION = createKey("irradiated/erosion"); + public static final ResourceKey FINAL_DENSITY = createKey("irradiated/final_density"); + } + + private static ResourceKey createKey(String id) { + return ResourceKey.create(Registries.DENSITY_FUNCTION, CreateNuclear.asResource(id)); + } + + public static void bootstrapRegistries(BootstapContext context) { + var vanillaRegistry = context.lookup(Registries.DENSITY_FUNCTION); + var noiseRegistry = context.lookup(Registries.NOISE); +// DensityFunction shiftX = getFunction(vanillaRegistry, NoiseRouterData.SHIFT_X); +// DensityFunction shiftZ = getFunction(vanillaRegistry, NoiseRouterData.SHIFT_Z); +// DensityFunction y = getFunction(vanillaRegistry, NoiseRouterData.Y); + + context.register(Irradiated.EROSION, DensityFunctions.add( + DensityFunctions.yClampedGradient(0, 90, 1, -1), + BlendedNoise.createUnseeded(0.25, 0.375, 80.0, 160.0, 8.0) + )); + + context.register(Irradiated.FINAL_DENSITY, DensityFunctions.add( + DensityFunctions.yClampedGradient(0, 90, 1, -1), + BlendedNoise.createUnseeded(0.25, 0.375, 80.0, 160.0, 8.0) + )); + } + + private static DensityFunction registerAndWrap(BootstapContext context, ResourceKey key, DensityFunction densityFunction) { + return new DensityFunctions.HolderHolder(context.register(key, densityFunction)); + } + + public static DensityFunction getFunction(HolderGetter densityFunctions, ResourceKey key) { + return new DensityFunctions.HolderHolder(densityFunctions.getOrThrow(key)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java new file mode 100644 index 00000000..a5245463 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseData.java @@ -0,0 +1,33 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.synth.NormalNoise.NoiseParameters; +import net.nuclearteam.createnuclear.CreateNuclear; + +public class CNNoiseData { + public static final ResourceKey EROSION = createKey("irradiated/erosion"); + public static final ResourceKey BASALT_MARE = createKey("irradiated/basalt_mare"); + public static final ResourceKey BASALT_MARE_HEIGHT = createKey("irradiated/basalt_mare_height"); + + private static ResourceKey createKey(String id) { + return ResourceKey.create(Registries.NOISE, CreateNuclear.asResource(id)); + } + + public static void bootstrapRegistries(BootstapContext context) { +// register(context, EROSION, -11, 1, 1, 0, 1, 1); +// register(context, BASALT_MARE, 5, 0, 0.1, 0.2, 0.1, 0, 0, 0, 0); +// register(context, BASALT_MARE_HEIGHT, -12, 0.3); + } + + private static void register( + BootstapContext context, + ResourceKey key, + int firstOctave, + double amplitude, + double... otherAmplitudes + ) { + context.register(key, new NoiseParameters(firstOctave, amplitude, otherAmplitudes)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java new file mode 100644 index 00000000..52e6d466 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/CNNoiseGeneratorSettings.java @@ -0,0 +1,100 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.core.registries.Registries; +import net.minecraft.data.worldgen.BootstapContext; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.biome.OverworldBiomeBuilder; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.*; +import net.minecraft.world.level.levelgen.synth.NormalNoise; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule.IrradiatedSurfaceRules; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule.IrradiatedSurfaceRules2; +import org.jetbrains.annotations.NotNull; + +public class CNNoiseGeneratorSettings { + public static final ResourceKey IRRADIATED = key("irradiated_noise"); + + public static void bootstrapRegistries(BootstapContext context) { + HolderGetter densityLookup = context.lookup(Registries.DENSITY_FUNCTION); + HolderGetter noiseLookup = context.lookup(Registries.NOISE); + + context.register(IRRADIATED, new NoiseGeneratorSettings( + NoiseSettings.create(-32, 256, 1, 2), + CNBlocks.STEEL_BLOCK.get().defaultBlockState(), + Blocks.AIR.defaultBlockState(), + CNNoiseGeneratorSettings.irradiated(densityLookup, noiseLookup), + IrradiatedSurfaceRules2.DEFAULT_RULE, + new OverworldBiomeBuilder().spawnTarget(), + 32, + false, + false, + false, + false + )); + } + + public static NoiseRouter irradiated(HolderGetter densityLookup, HolderGetter noiseLookup) { + DensityFunction shiftX = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.SHIFT_X); + DensityFunction shiftZ = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.SHIFT_Z); + DensityFunction y = CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.Y); + return new NoiseRouter( + DensityFunctions.constant(1), // barrierNoise + DensityFunctions.zero(), // fluidLevelFloodednessNoise + DensityFunctions.zero(), // fluidLevelSpreadNoise + DensityFunctions.zero(), // lavaNoise + DensityFunctions.shiftedNoise2d( + shiftX, shiftZ, 0.25, noiseLookup.getOrThrow(Noises.TEMPERATURE) + ), // temperature + DensityFunctions.shiftedNoise2d( + shiftX, shiftZ, 0, noiseLookup.getOrThrow(Noises.VEGETATION) + ), // vegetation + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.CONTINENTS), // continents + CNDensityFunctions.getFunction(densityLookup, CNDensityFunctions.Irradiated.EROSION), // erosion + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.DEPTH), // depth + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.RIDGES), // ridges + DensityFunctions.add( + DensityFunctions.constant(0.1171875), + DensityFunctions.mul( + DensityFunctions.yClampedGradient( + -30, -40, 0, 1 + ), + DensityFunctions.add( + DensityFunctions.constant(-0.1171875), + DensityFunctions.add( + DensityFunctions.constant(-0.078125), + DensityFunctions.mul( + DensityFunctions.yClampedGradient( + 240, 256, 1, 0 + ), + DensityFunctions.add( + DensityFunctions.constant(0.078125), + DensityFunctions.add( + DensityFunctions.constant(-0.703125), + DensityFunctions.mul( + DensityFunctions.constant(4), + DensityFunctions.mul( + CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.DEPTH), + DensityFunctions.cache2d(CNDensityFunctions.getFunction(densityLookup, NoiseRouterData.FACTOR)) + ).quarterNegative() + ) + ).clamp(-30, 64) + ) + ) + ) + ) + ) + ), // initialDensityWithoutJaggedness + DensityFunctions.blendDensity(CNDensityFunctions.getFunction(densityLookup, CNDensityFunctions.Irradiated.FINAL_DENSITY)), // finalDensity + DensityFunctions.zero(), // veinToggle + DensityFunctions.zero(), // veinRidged + DensityFunctions.zero() // veinGap + ); + } + + private static @NotNull ResourceKey key(String id) { + return ResourceKey.create(Registries.NOISE_SETTINGS, CreateNuclear.asResource(id)); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java new file mode 100644 index 00000000..7b067fb6 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/IrradiatedBiomes.java @@ -0,0 +1,59 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome; + +import net.minecraft.core.HolderGetter; +import net.minecraft.data.worldgen.Carvers; +import net.minecraft.data.worldgen.placement.MiscOverworldPlacements; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.level.biome.*; +import net.minecraft.world.level.levelgen.GenerationStep; +import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.nuclearteam.createnuclear.CNEntityType; +import net.nuclearteam.createnuclear.content.particles.IrradiatedParticlesData; + +public class IrradiatedBiomes { + public static Biome createPlain(HolderGetter featureLookup, HolderGetter> carverLookup) { + return IrradiatedBiomes.irradiated(featureLookup, carverLookup, new BiomeGenerationSettings.Builder(featureLookup, carverLookup)); + } + + public static void monsters(MobSpawnSettings.Builder builder, int zombieWeight, int zombieVillagerWeight, int skeletonWeight) { +// builder.addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(CNEntityType.IRRADIATED_CAT.get(), 100, 2, 4)); +// builder.addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(CNEntityType.IRRADIATED_CHICKEN.get(), 100, 1, 4)); +// builder.addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(CNEntityType.IRRADIATED_WOLF.get(), 100, 2, 4)); + } + + public static void addDefaultIrradiatedOres(BiomeGenerationSettings.Builder builder) { + builder.addFeature(GenerationStep.Decoration.UNDERGROUND_STRUCTURES, MiscOverworldPlacements.BLUE_ICE); + builder.addCarver(GenerationStep.Carving.AIR, Carvers.NETHER_CAVE); + } + + public static void addDefaultSoftDisks(BiomeGenerationSettings.Builder builder) { + // builder.addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, GCOrePlacedFeatures.BASALT_DISK_MOON); + builder.addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, MiscOverworldPlacements.VOID_START_PLATFORM); + } + public static Biome irradiated(HolderGetter featureGetter, HolderGetter> carverGetter, BiomeGenerationSettings.Builder generation) { + MobSpawnSettings.Builder spawnBuilder = new MobSpawnSettings.Builder(); + BiomeSpecialEffects.Builder effectBuilder = new BiomeSpecialEffects.Builder(); + effectBuilder.waterColor(4159204) + .waterFogColor(329011) + .fogColor(329011) + .skyColor(0) + .ambientParticle(new AmbientParticleSettings(new IrradiatedParticlesData(), 0.025F)) + .ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS) + ; + + IrradiatedBiomes.addDefaultIrradiatedOres(generation); + IrradiatedBiomes.addDefaultSoftDisks(generation); + IrradiatedBiomes.monsters(spawnBuilder, 95,5,100); +// generation.addCarver(GenerationStep.Carving.AIR, ) + + return new Biome.BiomeBuilder() + .mobSpawnSettings(spawnBuilder.build()) + .hasPrecipitation(false) + .temperature(2f) + .downfall(0f) + .specialEffects(effectBuilder.build()) + .generationSettings(generation.build()) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java new file mode 100644 index 00000000..25ba3b0a --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/BiomeTagRule.java @@ -0,0 +1,35 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.registries.Registries; +import net.minecraft.tags.TagKey; +import net.minecraft.util.KeyDispatchDataCodec; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.SurfaceRules; +import org.jetbrains.annotations.NotNull; + +public record BiomeTagRule(@NotNull TagKey tag) implements SurfaceRules.ConditionSource { + private static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(TagKey.codec(Registries.BIOME).fieldOf("tag").forGetter(rule -> rule.tag)).apply(instance, BiomeTagRule::new)); + + @Override + public KeyDispatchDataCodec codec() { + return KeyDispatchDataCodec.of(BiomeTagRule.CODEC); + } + + @Override + public SurfaceRules.Condition apply(SurfaceRules.Context context) { + return null; + } + + private class Predicate extends SurfaceRules.LazyYCondition { + protected Predicate(SurfaceRules.Context context) { + super(context); + } + + @Override + protected boolean compute() { + return this.context.biome.get().is(BiomeTagRule.this.tag); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java new file mode 100644 index 00000000..19a78bfb --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules.java @@ -0,0 +1,30 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule; + +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import org.jetbrains.annotations.NotNull; + +public class IrradiatedSurfaceRules { + private static final SurfaceRules.RuleSource BEDROCK = block(Blocks.BEDROCK); + public static final SurfaceRules.RuleSource HARD_ROCK = block(CNBlocks.ENRICHED_SOUL_SOIL.get()); + + public static final SurfaceRules.RuleSource IRRADIATED = createDefaultRule(); + + public static @NotNull SurfaceRules.RuleSource createDefaultRule() { + return SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.isBiome(CNBiomes.Irradiated.PLAIN), + HARD_ROCK + ), + SurfaceRules.ifTrue(SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), BEDROCK) + ); + } + + private static @NotNull SurfaceRules.RuleSource block(@NotNull Block block) { + return SurfaceRules.state(block.defaultBlockState()); + } +} \ No newline at end of file diff --git a/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules2.java b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules2.java new file mode 100644 index 00000000..5f832072 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/infrastructure/worldgen/biome/surfacerule/IrradiatedSurfaceRules2.java @@ -0,0 +1,91 @@ +package net.nuclearteam.createnuclear.infrastructure.worldgen.biome.surfacerule; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import net.minecraft.core.Registry; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.SurfaceRules.RuleSource; +import net.minecraft.world.level.levelgen.SurfaceRules.ConditionSource; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.nuclearteam.createnuclear.CNBlocks; +import net.nuclearteam.createnuclear.CreateNuclear; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNBiomes; +import net.nuclearteam.createnuclear.infrastructure.worldgen.biome.CNNoiseData; +import org.jetbrains.annotations.NotNull; + +public class IrradiatedSurfaceRules2 { + private static final ConditionSource IS_MARE = biome(CNBiomes.Irradiated.PLAIN); + private static final ConditionSource IS_HIGHLANDS = biome(); + + private static final RuleSource BEDROCK = block(Blocks.BEDROCK); + private static final RuleSource LUNASLATE = block(CNBlocks.ENRICHED_SOUL_SOIL.get()); + private static final RuleSource MOON_DIRT = block(CNBlocks.STEEL_BLOCK.get()); + private static final RuleSource MOON_ROCK = block(CNBlocks.LEAD_BLOCK.get()); + private static final RuleSource MOON_TURF = block(CNBlocks.LEAD_ORE.get()); + private static final RuleSource MOON_BASALT = block(CNBlocks.RAW_LEAD_BLOCK.get()); + private static final RuleSource DEBUG_STATE = block(CNBlocks.REACTOR_CASING.get()); + + private static final RuleSource SECONDARY_MATERIAL = SurfaceRules.sequence( + SurfaceRules.ifTrue(IS_MARE, MOON_BASALT), + SurfaceRules.ifTrue(IS_HIGHLANDS, MOON_DIRT) + ); + private static final RuleSource SURFACE_MATERIAL = SurfaceRules.sequence( + SurfaceRules.ifTrue(IS_MARE, MOON_BASALT), + SurfaceRules.ifTrue(IS_HIGHLANDS, MOON_TURF) + ); + private static final RuleSource SURFACE_GENERATION = SurfaceRules.sequence( + SurfaceRules.ifTrue(SurfaceRules.ON_FLOOR, SURFACE_MATERIAL), + SurfaceRules.ifTrue(SurfaceRules.UNDER_FLOOR, SECONDARY_MATERIAL) + ); + + public static final RuleSource DEFAULT_RULE = createDefaultRule(); + + public static @NotNull RuleSource createDefaultRule() { + return SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.isBiome(CNBiomes.Irradiated.PLAIN), + SurfaceRules.sequence( + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.035, 0.0465), + MOON_TURF + ), + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.039, 0.0545), + MOON_ROCK + ), + SurfaceRules.ifTrue( + SurfaceRules.noiseCondition(CNNoiseData.EROSION, 0.0545, 0.069), + MOON_BASALT + ) + ) + ), + + SurfaceRules.ifTrue(SurfaceRules.verticalGradient("bedrock_floor", VerticalAnchor.bottom(), VerticalAnchor.aboveBottom(5)), BEDROCK), + SurfaceRules.ifTrue(SurfaceRules.abovePreliminarySurface(), SURFACE_GENERATION), + SurfaceRules.ifTrue(SurfaceRules.verticalGradient("lunaslate", VerticalAnchor.absolute(-4), VerticalAnchor.absolute(4)), LUNASLATE) + ); + } + + private static @NotNull RuleSource block(@NotNull Block block) { + return SurfaceRules.state(block.defaultBlockState()); + } + + public static SurfaceRules.@NotNull ConditionSource biome(@NotNull TagKey biome) { + return new BiomeTagRule(biome); + } + + @SafeVarargs + public static SurfaceRules.@NotNull ConditionSource biome(@NotNull ResourceKey @NotNull ... keys) { + return SurfaceRules.isBiome(keys); + } + + public static void register() { + Registry.register(BuiltInRegistries.MATERIAL_RULE, CreateNuclear.asResource("irradiated_surface"), Codec.unit(DEFAULT_RULE)); + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 79226f6f..8d9a24bb 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,3 +1,11 @@ public net.minecraft.world.item.crafting.RecipeManager f_44007_ # recipes public net.minecraft.world.item.alchemy.PotionBrewing m_43513_(Lnet/minecraft/world/item/alchemy/Potion;Lnet/minecraft/world/item/Item;Lnet/minecraft/world/item/alchemy/Potion;)V + +public net.minecraft.world.level.levelgen.SurfaceRules$Context +public net.minecraft.world.level.levelgen.SurfaceRules$LazyYCondition +public net.minecraft.world.level.levelgen.SurfaceRules$Condition +public net.minecraft.world.level.levelgen.SurfaceRules$Context f_189555_ # biome +public net.minecraft.world.level.levelgen.NoiseRouterData f_209448_ # SHIFT_X +public net.minecraft.world.level.levelgen.NoiseRouterData f_209447_ # Y +public net.minecraft.world.level.levelgen.NoiseRouterData f_209449_ # SHIFT_Z \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/particles/irradiated_particles.json b/src/main/resources/assets/createnuclear/particles/irradiated_particles.json new file mode 100644 index 00000000..4c09429a --- /dev/null +++ b/src/main/resources/assets/createnuclear/particles/irradiated_particles.json @@ -0,0 +1,5 @@ +{ + "textures": [ + "createnuclear:irradiated_particles" + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png b/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png new file mode 100644 index 00000000..c3e80185 Binary files /dev/null and b/src/main/resources/assets/createnuclear/textures/particle/irradiated_particles.png differ diff --git a/src/main/resources/createnuclear.forge.mixins.json b/src/main/resources/createnuclear.forge.mixins.json index 1a26dd56..10717a86 100644 --- a/src/main/resources/createnuclear.forge.mixins.json +++ b/src/main/resources/createnuclear.forge.mixins.json @@ -6,6 +6,7 @@ "mixins": [ "BaseFireBlockMixin" ], + "accessWidener": "createnuclear.accesswidener", "client": [ ], "injectors": {