diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 751345e2f..306a249ea 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -5628,11 +5628,10 @@ ac265a674626e0e832330086fd18fe0be37fc327 data/create/recipes/weathered_copper_ti 5942a571f79c40524bbf408775cf91de4715f2b6 data/create/recipes/weathered_copper_tile_stairs_from_weathered_copper_tiles_stonecutting.json 2d549ea56fb226c0e31e66c0391996093f8bece9 data/create/tags/blocks/brittle.json d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/blocks/casing.json -418c6da531d6206e3cbe4049dce3db23c4270bed data/create/tags/blocks/fan_heaters.json 443f75adbf3d2f6fb0aad4b344372669470065b8 data/create/tags/blocks/fan_transparent.json 6e5d3b2123fbb00e7f439c091623619502551bca data/create/tags/blocks/non_movable.json 10781e8cfcbb3486327aace3aa00e437fb44b331 data/create/tags/blocks/ore_override_stone.json -197ed7ee3b284045c005011d28c38ac5b2e44d8c data/create/tags/blocks/passive_boiler_heaters.json +418c6da531d6206e3cbe4049dce3db23c4270bed data/create/tags/blocks/passive_boiler_heaters.json 74f4ba5f6f61c30e27947c6fb4557e888d018285 data/create/tags/blocks/safe_nbt.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json diff --git a/src/generated/resources/data/create/tags/blocks/fan_heaters.json b/src/generated/resources/data/create/tags/blocks/fan_heaters.json deleted file mode 100644 index dc4ef4afb..000000000 --- a/src/generated/resources/data/create/tags/blocks/fan_heaters.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "replace": false, - "values": [ - "create:blaze_burner", - "create:lit_blaze_burner", - "#minecraft:fire", - "#minecraft:campfires", - "minecraft:magma_block", - "minecraft:lava" - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/passive_boiler_heaters.json b/src/generated/resources/data/create/tags/blocks/passive_boiler_heaters.json index 509d23e72..dc4ef4afb 100644 --- a/src/generated/resources/data/create/tags/blocks/passive_boiler_heaters.json +++ b/src/generated/resources/data/create/tags/blocks/passive_boiler_heaters.json @@ -1,6 +1,11 @@ { "replace": false, "values": [ - "#create:fan_heaters" + "create:blaze_burner", + "create:lit_blaze_burner", + "#minecraft:fire", + "#minecraft:campfires", + "minecraft:magma_block", + "minecraft:lava" ] } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 3937784c0..e17957caf 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -652,7 +652,7 @@ public class AllBlocks { .properties(p -> p.lightLevel(BlazeBurnerBlock::getLight)) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) - .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.FAN_HEATERS.tag) + .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .loot((lt, block) -> lt.add(block, BlazeBurnerBlock.buildLootTable())) .blockstate((c, p) -> p.simpleBlock(c.getEntry(), AssetLookup.partialBaseModel(c, p))) .onRegister(movementBehaviour(new BlazeBurnerMovementBehaviour())) @@ -669,7 +669,7 @@ public class AllBlocks { .properties(p -> p.lightLevel(LitBlazeBurnerBlock::getLight)) .transform(pickaxeOnly()) .addLayer(() -> RenderType::cutoutMipped) - .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.FAN_HEATERS.tag) + .tag(AllBlockTags.FAN_TRANSPARENT.tag, AllBlockTags.PASSIVE_BOILER_HEATERS.tag) .loot((lt, block) -> lt.dropOther(block, AllItems.EMPTY_BLAZE_BURNER.get())) .blockstate((c, p) -> p.getVariantBuilder(c.get()) .forAllStates(state -> ConfiguredModel.builder() diff --git a/src/main/java/com/simibubi/create/AllEntityDataSerializers.java b/src/main/java/com/simibubi/create/AllEntityDataSerializers.java index afbb63ebe..6227bea7d 100644 --- a/src/main/java/com/simibubi/create/AllEntityDataSerializers.java +++ b/src/main/java/com/simibubi/create/AllEntityDataSerializers.java @@ -2,17 +2,21 @@ package com.simibubi.create; import com.simibubi.create.content.logistics.trains.entity.CarriageSyncDataSerializer; +import net.minecraft.network.syncher.EntityDataSerializer; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; +import net.minecraftforge.registries.RegistryObject; + public class AllEntityDataSerializers { + private static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.Keys.ENTITY_DATA_SERIALIZERS, Create.ID); public static final CarriageSyncDataSerializer CARRIAGE_DATA = new CarriageSyncDataSerializer(); - public static void register(RegisterEvent event) { - event.register(ForgeRegistries.Keys.ENTITY_DATA_SERIALIZERS, helper -> { - helper.register(Create.asResource("carriage_data"), CARRIAGE_DATA); - }); - } + public static final RegistryObject CARRIAGE_DATA_ENTRY = REGISTER.register("carriage_data", () -> CARRIAGE_DATA); + public static void register(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } } diff --git a/src/main/java/com/simibubi/create/AllParticleTypes.java b/src/main/java/com/simibubi/create/AllParticleTypes.java index d5c098fd4..eb1d938bc 100644 --- a/src/main/java/com/simibubi/create/AllParticleTypes.java +++ b/src/main/java/com/simibubi/create/AllParticleTypes.java @@ -14,14 +14,15 @@ import com.simibubi.create.content.curiosities.bell.SoulBaseParticle; import com.simibubi.create.content.curiosities.bell.SoulParticle; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.core.Registry; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; -import net.minecraft.resources.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.event.RegisterParticleProvidersEvent; -import net.minecraftforge.registries.RegisterEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; public enum AllParticleTypes { @@ -37,21 +38,17 @@ public enum AllParticleTypes { SOUL(SoulParticle.Data::new), SOUL_BASE(SoulBaseParticle.Data::new), SOUL_PERIMETER(SoulParticle.PerimeterData::new), - SOUL_EXPANDING_PERIMETER(SoulParticle.ExpandingPerimeterData::new) - ; + SOUL_EXPANDING_PERIMETER(SoulParticle.ExpandingPerimeterData::new); - private ParticleEntry entry; + private final ParticleEntry entry; AllParticleTypes(Supplier> typeFactory) { - String asId = Lang.asId(this.name()); - entry = new ParticleEntry<>(new ResourceLocation(Create.ID, asId), typeFactory); + String name = Lang.asId(name()); + entry = new ParticleEntry<>(name, typeFactory); } - public static void register(RegisterEvent event) { - event.register(Registry.PARTICLE_TYPE_REGISTRY, helper -> { - for (AllParticleTypes particle : values()) - particle.entry.register(helper); - }); + public static void register(IEventBus modEventBus) { + ParticleEntry.REGISTER.register(modEventBus); } @OnlyIn(Dist.CLIENT) @@ -61,39 +58,31 @@ public enum AllParticleTypes { } public ParticleType get() { - return entry.getOrCreateType(); + return entry.object.get(); } public String parameter() { - return Lang.asId(name()); + return entry.name; } - private class ParticleEntry { - Supplier> typeFactory; - ParticleType type; - ResourceLocation id; + private static class ParticleEntry { + private static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, Create.ID); - public ParticleEntry(ResourceLocation id, Supplier> typeFactory) { - this.id = 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; - } - void register(RegisterEvent.RegisterHelper> helper) { - helper.register(id, getOrCreateType()); - } - - ParticleType getOrCreateType() { - if (type != null) - return type; - type = typeFactory.get() - .createType(); - return type; + object = REGISTER.register(name, () -> this.typeFactory.get().createType()); } @OnlyIn(Dist.CLIENT) - void registerFactory(RegisterParticleProvidersEvent event) { + public void registerFactory(RegisterParticleProvidersEvent event) { typeFactory.get() - .register(getOrCreateType(), event); + .register(object.get(), event); } } diff --git a/src/main/java/com/simibubi/create/AllRecipeTypes.java b/src/main/java/com/simibubi/create/AllRecipeTypes.java index d803d6f4b..08e8ffffe 100644 --- a/src/main/java/com/simibubi/create/AllRecipeTypes.java +++ b/src/main/java/com/simibubi/create/AllRecipeTypes.java @@ -4,6 +4,8 @@ import java.util.Optional; import java.util.Set; import java.util.function.Supplier; +import org.jetbrains.annotations.Nullable; + import com.google.common.collect.ImmutableSet; import com.simibubi.create.compat.jei.ConversionRecipe; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCraftingRecipe; @@ -38,7 +40,10 @@ import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.SimpleRecipeSerializer; import net.minecraft.world.level.Level; -import net.minecraftforge.registries.RegisterEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; public enum AllRecipeTypes implements IRecipeTypeInfo { @@ -61,34 +66,43 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { MECHANICAL_CRAFTING(MechanicalCraftingRecipe.Serializer::new), SEQUENCED_ASSEMBLY(SequencedAssemblyRecipeSerializer::new), - TOOLBOX_DYEING(() -> new SimpleRecipeSerializer<>(ToolboxDyeingRecipe::new), RecipeType.CRAFTING); + TOOLBOX_DYEING(() -> new SimpleRecipeSerializer<>(ToolboxDyeingRecipe::new), () -> RecipeType.CRAFTING, false); - ; + private final ResourceLocation id; + private final RegistryObject> serializerObject; + @Nullable + private final RegistryObject> typeObject; + private final Supplier> type; - private ResourceLocation id; - private Supplier> serializerSupplier; - private Supplier> typeSupplier; - private RecipeSerializer serializer; - private RecipeType type; - - AllRecipeTypes(Supplier> serializerSupplier, Supplier> typeSupplier) { - this.id = Create.asResource(Lang.asId(name())); - this.serializerSupplier = serializerSupplier; - this.typeSupplier = typeSupplier; - } - - AllRecipeTypes(Supplier> serializerSupplier, RecipeType existingType) { - this(serializerSupplier, () -> existingType); + AllRecipeTypes(Supplier> serializerSupplier, Supplier> typeSupplier, boolean registerType) { + String name = Lang.asId(name()); + id = Create.asResource(name); + serializerObject = Registers.SERIALIZER_REGISTER.register(name, serializerSupplier); + if (registerType) { + typeObject = Registers.TYPE_REGISTER.register(name, typeSupplier); + type = typeObject; + } else { + typeObject = null; + type = typeSupplier; + } } AllRecipeTypes(Supplier> serializerSupplier) { - this.id = Create.asResource(Lang.asId(name())); - this.serializerSupplier = serializerSupplier; - this.typeSupplier = () -> RecipeType.simple(id); + String name = Lang.asId(name()); + id = Create.asResource(name); + serializerObject = Registers.SERIALIZER_REGISTER.register(name, serializerSupplier); + typeObject = Registers.TYPE_REGISTER.register(name, () -> RecipeType.simple(id)); + type = typeObject; } AllRecipeTypes(ProcessingRecipeFactory processingFactory) { - this(processingSerializer(processingFactory)); + this(() -> new ProcessingRecipeSerializer<>(processingFactory)); + } + + public static void register(IEventBus modEventBus) { + ShapedRecipe.setCraftingSize(9, 9); + Registers.SERIALIZER_REGISTER.register(modEventBus); + Registers.TYPE_REGISTER.register(modEventBus); } @Override @@ -99,13 +113,13 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { @SuppressWarnings("unchecked") @Override public > T getSerializer() { - return (T) serializer; + return (T) serializerObject.get(); } @SuppressWarnings("unchecked") @Override public > T getType() { - return (T) type; + return (T) type.get(); } public > Optional find(C inv, Level world) { @@ -113,30 +127,6 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { .getRecipeFor(getType(), inv, world); } - public static void register(RegisterEvent event) { - event.register(Registry.RECIPE_SERIALIZER_REGISTRY, helper -> { - ShapedRecipe.setCraftingSize(9, 9); - - for (AllRecipeTypes r : AllRecipeTypes.values()) { - r.serializer = r.serializerSupplier.get(); - helper.register(r.id, r.serializer); - } - }); - - event.register(Registry.RECIPE_TYPE_REGISTRY, helper -> { - for (AllRecipeTypes r : AllRecipeTypes.values()) { - r.type = r.typeSupplier.get(); - if (r.type == RecipeType.CRAFTING) - continue; - helper.register(r.id, r.type); - } - }); - } - - private static Supplier> processingSerializer(ProcessingRecipeFactory factory) { - return () -> new ProcessingRecipeSerializer<>(factory); - } - public static final Set RECIPE_DENY_SET = ImmutableSet.of(new ResourceLocation("occultism", "spirit_trade"), new ResourceLocation("occultism", "ritual")); @@ -149,4 +139,9 @@ public enum AllRecipeTypes implements IRecipeTypeInfo { .endsWith("_manual_only"); } + private static class Registers { + private static final DeferredRegister> SERIALIZER_REGISTER = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Create.ID); + private static final DeferredRegister> TYPE_REGISTER = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, Create.ID); + } + } diff --git a/src/main/java/com/simibubi/create/AllSoundEvents.java b/src/main/java/com/simibubi/create/AllSoundEvents.java index 8c8e56a8a..863a39757 100644 --- a/src/main/java/com/simibubi/create/AllSoundEvents.java +++ b/src/main/java/com/simibubi/create/AllSoundEvents.java @@ -6,12 +6,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; -import com.google.common.collect.Lists; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; import net.minecraft.core.Registry; import net.minecraft.core.Vec3i; @@ -26,12 +24,15 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegisterEvent; +import net.minecraftforge.registries.RegistryObject; //@EventBusSubscriber(bus = Bus.FORGE) public class AllSoundEvents { - public static final Map entries = new HashMap<>(); + public static final Map ALL = new HashMap<>(); + public static final SoundEntry SCHEMATICANNON_LAUNCH_BLOCK = create("schematicannon_launch_block").subtitle("Schematicannon fires") @@ -304,21 +305,21 @@ public class AllSoundEvents { return new SoundEntryBuilder(id); } + public static void prepare() { + for (SoundEntry entry : ALL.values()) + entry.prepare(); + } + public static void register(RegisterEvent event) { event.register(Registry.SOUND_EVENT_REGISTRY, helper -> { - for (SoundEntry entry : entries.values()) + for (SoundEntry entry : ALL.values()) entry.register(helper); }); } - public static void prepare() { - for (SoundEntry entry : entries.values()) - entry.prepare(); - } - public static JsonObject provideLangEntries() { JsonObject object = new JsonObject(); - for (SoundEntry entry : entries.values()) + for (SoundEntry entry : ALL.values()) if (entry.hasSubtitle()) object.addProperty(entry.getSubtitleKey(), entry.getSubtitle()); return object; @@ -366,7 +367,7 @@ public class AllSoundEvents { try { JsonObject json = new JsonObject(); - entries.entrySet() + ALL.entrySet() .stream() .sorted(Map.Entry.comparingByKey()) .forEach(entry -> { @@ -382,12 +383,15 @@ public class AllSoundEvents { } + public record ConfiguredSoundEvent(Supplier event, float volume, float pitch) { + } + public static class SoundEntryBuilder { protected ResourceLocation id; protected String subtitle = "unregistered"; protected SoundSource category = SoundSource.BLOCKS; - protected List>> wrappedEvents; + protected List wrappedEvents; protected List variants; protected int attenuationDistance; @@ -426,11 +430,15 @@ public class AllSoundEvents { return this; } - public SoundEntryBuilder playExisting(SoundEvent event, float volume, float pitch) { - wrappedEvents.add(Pair.of(event, Couple.create(volume, pitch))); + public SoundEntryBuilder playExisting(Supplier event, float volume, float pitch) { + wrappedEvents.add(new ConfiguredSoundEvent(event, volume, pitch)); return this; } + public SoundEntryBuilder playExisting(SoundEvent event, float volume, float pitch) { + return playExisting(() -> event, volume, pitch); + } + public SoundEntryBuilder playExisting(SoundEvent event) { return playExisting(event, 1, 1); } @@ -439,7 +447,7 @@ public class AllSoundEvents { SoundEntry entry = wrappedEvents.isEmpty() ? new CustomSoundEntry(id, variants, subtitle, category, attenuationDistance) : new WrappedSoundEntry(id, subtitle, wrappedEvents, category, attenuationDistance); - entries.put(entry.getId(), entry); + ALL.put(entry.getId(), entry); return entry; } @@ -528,52 +536,53 @@ public class AllSoundEvents { private static class WrappedSoundEntry extends SoundEntry { - private List>> wrappedEvents; - private List>> compiledEvents; + private List wrappedEvents; + private List compiledEvents; public WrappedSoundEntry(ResourceLocation id, String subtitle, - List>> wrappedEvents, SoundSource category, int attenuationDistance) { + List wrappedEvents, SoundSource category, int attenuationDistance) { super(id, subtitle, category, attenuationDistance); this.wrappedEvents = wrappedEvents; - compiledEvents = Lists.newArrayList(); + compiledEvents = new ArrayList<>(); } @Override public void prepare() { for (int i = 0; i < wrappedEvents.size(); i++) { - ResourceLocation location = Create.asResource(getIdOf(i)); - SoundEvent sound = new SoundEvent(location); - compiledEvents.add(Pair.of(sound, wrappedEvents.get(i) - .getSecond())); + ConfiguredSoundEvent wrapped = wrappedEvents.get(i); + ResourceLocation location = getIdOf(i); + RegistryObject event = RegistryObject.create(location, ForgeRegistries.SOUND_EVENTS); + compiledEvents.add(new CompiledSoundEvent(event, wrapped.volume(), wrapped.pitch())); } } @Override public void register(RegisterEvent.RegisterHelper helper) { - for (Pair> pair : compiledEvents) { - SoundEvent soundEvent = pair.getFirst(); - helper.register(soundEvent.getLocation(), soundEvent); + for (CompiledSoundEvent compiledEvent : compiledEvents) { + ResourceLocation location = compiledEvent.event().getId(); + helper.register(location, new SoundEvent(location)); } } @Override public SoundEvent getMainEvent() { return compiledEvents.get(0) - .getFirst(); + .event().get(); } - protected String getIdOf(int i) { - return i == 0 ? id.getPath() : id.getPath() + "_compounded_" + i; + protected ResourceLocation getIdOf(int i) { + return new ResourceLocation(id.getNamespace(), i == 0 ? id.getPath() : id.getPath() + "_compounded_" + i); } @Override public void write(JsonObject json) { for (int i = 0; i < wrappedEvents.size(); i++) { - Pair> pair = wrappedEvents.get(i); + ConfiguredSoundEvent event = wrappedEvents.get(i); JsonObject entry = new JsonObject(); JsonArray list = new JsonArray(); JsonObject s = new JsonObject(); - s.addProperty("name", pair.getFirst() + s.addProperty("name", event.event() + .get() .getLocation() .toString()); s.addProperty("type", "event"); @@ -583,33 +592,35 @@ public class AllSoundEvents { entry.add("sounds", list); if (i == 0 && hasSubtitle()) entry.addProperty("subtitle", getSubtitleKey()); - json.add(getIdOf(i), entry); + json.add(getIdOf(i).getPath(), entry); } } @Override public void play(Level world, Player entity, double x, double y, double z, float volume, float pitch) { - for (Pair> pair : compiledEvents) { - Couple volPitch = pair.getSecond(); - world.playSound(entity, x, y, z, pair.getFirst(), category, volPitch.getFirst() * volume, - volPitch.getSecond() * pitch); + for (CompiledSoundEvent event : compiledEvents) { + world.playSound(entity, x, y, z, event.event().get(), category, event.volume() * volume, + event.pitch() * pitch); } } @Override public void playAt(Level world, double x, double y, double z, float volume, float pitch, boolean fade) { - for (Pair> pair : compiledEvents) { - Couple volPitch = pair.getSecond(); - world.playLocalSound(x, y, z, pair.getFirst(), category, volPitch.getFirst() * volume, - volPitch.getSecond() * pitch, fade); + for (CompiledSoundEvent event : compiledEvents) { + world.playLocalSound(x, y, z, event.event().get(), category, event.volume() * volume, + event.pitch() * pitch, fade); } } + + private record CompiledSoundEvent(RegistryObject event, float volume, float pitch) { + } + } private static class CustomSoundEntry extends SoundEntry { protected List variants; - protected SoundEvent event; + protected RegistryObject event; public CustomSoundEntry(ResourceLocation id, List variants, String subtitle, SoundSource category, int attenuationDistance) { @@ -619,17 +630,18 @@ public class AllSoundEvents { @Override public void prepare() { - event = new SoundEvent(id); + event = RegistryObject.create(id, ForgeRegistries.SOUND_EVENTS); } @Override public void register(RegisterEvent.RegisterHelper helper) { - helper.register(id, event); + ResourceLocation location = event.getId(); + helper.register(location, new SoundEvent(location)); } @Override public SoundEvent getMainEvent() { - return event; + return event.get(); } @Override @@ -661,12 +673,12 @@ public class AllSoundEvents { @Override public void play(Level world, Player entity, double x, double y, double z, float volume, float pitch) { - world.playSound(entity, x, y, z, event, category, volume, pitch); + world.playSound(entity, x, y, z, event.get(), category, volume, pitch); } @Override public void playAt(Level world, double x, double y, double z, float volume, float pitch, boolean fade) { - world.playLocalSound(x, y, z, event, category, volume, pitch, fade); + world.playLocalSound(x, y, z, event.get(), category, volume, pitch, fade); } } diff --git a/src/main/java/com/simibubi/create/AllStructureProcessorTypes.java b/src/main/java/com/simibubi/create/AllStructureProcessorTypes.java new file mode 100644 index 000000000..047f68f9a --- /dev/null +++ b/src/main/java/com/simibubi/create/AllStructureProcessorTypes.java @@ -0,0 +1,19 @@ +package com.simibubi.create; + +import com.simibubi.create.content.schematics.SchematicProcessor; + +import net.minecraft.core.Registry; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +public class AllStructureProcessorTypes { + private static final DeferredRegister> REGISTER = DeferredRegister.create(Registry.STRUCTURE_PROCESSOR_REGISTRY, Create.ID); + + public static final RegistryObject> SCHEMATIC = REGISTER.register("schematic", () -> () -> SchematicProcessor.CODEC); + + public static void register(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } +} diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index cb9cb2e48..1d731f55b 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -111,9 +111,11 @@ public class AllTags { public enum AllBlockTags { BRITTLE, - FAN_HEATERS, + CASING, FAN_TRANSPARENT, + NON_MOVABLE, ORE_OVERRIDE_STONE, + PASSIVE_BOILER_HEATERS, SAFE_NBT, SEATS, TOOLBOXES, @@ -121,10 +123,6 @@ public class AllTags { WINDMILL_SAILS, WINDOWABLE, WRENCH_PICKUP, - CASING, - NON_MOVABLE, - - PASSIVE_BOILER_HEATERS, RELOCATION_NOT_SUPPORTED(FORGE), WG_STONE(FORGE), @@ -207,10 +205,13 @@ public class AllTags { BLAZE_BURNER_FUEL_REGULAR(MOD, "blaze_burner_fuel/regular"), BLAZE_BURNER_FUEL_SPECIAL(MOD, "blaze_burner_fuel/special"), + CASING, CREATE_INGOTS, CRUSHED_ORES, + PRESSURIZED_AIR_SOURCES, SANDPAPER, SEATS, + SLEEPERS, TOOLBOXES, UPRIGHT_ON_BELT, VALVE_HANDLES, @@ -218,9 +219,6 @@ public class AllTags { VANILLA_STRIPPED_WOOD, MODDED_STRIPPED_LOGS, MODDED_STRIPPED_WOOD, - CASING, - SLEEPERS, - PRESSURIZED_AIR_SOURCES, STRIPPED_LOGS(FORGE), STRIPPED_WOOD(FORGE), @@ -402,10 +400,9 @@ public class AllTags { AllBlockTags.FAN_TRANSPARENT.includeAll(BlockTags.CAMPFIRES); AllBlockTags.FAN_TRANSPARENT.add(Blocks.IRON_BARS); - AllBlockTags.FAN_HEATERS.includeAll(BlockTags.FIRE); - AllBlockTags.FAN_HEATERS.includeAll(BlockTags.CAMPFIRES); - AllBlockTags.FAN_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.LAVA); - AllBlockTags.FAN_HEATERS.includeIn(AllBlockTags.PASSIVE_BOILER_HEATERS); + AllBlockTags.PASSIVE_BOILER_HEATERS.includeAll(BlockTags.FIRE); + AllBlockTags.PASSIVE_BOILER_HEATERS.includeAll(BlockTags.CAMPFIRES); + AllBlockTags.PASSIVE_BOILER_HEATERS.add(Blocks.MAGMA_BLOCK, Blocks.LAVA); AllBlockTags.SAFE_NBT.includeAll(BlockTags.SIGNS); AllBlockTags.SAFE_NBT.includeAll(BlockTags.BANNERS); diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index 922fbdaaf..50e187d42 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -20,7 +20,6 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.AllArmInteracti import com.simibubi.create.content.logistics.trains.GlobalRailwayManager; import com.simibubi.create.content.palettes.AllPaletteBlocks; import com.simibubi.create.content.palettes.PalettesItemGroup; -import com.simibubi.create.content.schematics.SchematicProcessor; import com.simibubi.create.content.schematics.ServerSchematicLoader; import com.simibubi.create.content.schematics.filtering.SchematicInstances; import com.simibubi.create.foundation.advancement.AllAdvancements; @@ -37,7 +36,9 @@ import com.simibubi.create.foundation.data.recipe.SequencedAssemblyRecipeGen; import com.simibubi.create.foundation.data.recipe.StandardRecipeGen; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.CreateRegistry; -import com.simibubi.create.foundation.worldgen.AllWorldFeatures; +import com.simibubi.create.foundation.worldgen.AllFeatures; +import com.simibubi.create.foundation.worldgen.AllPlacementModifiers; +import com.simibubi.create.foundation.worldgen.BuiltinRegistration; import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.data.DataGenerator; @@ -92,6 +93,10 @@ public class Create { public static void onCtor() { ModLoadingContext modLoadingContext = ModLoadingContext.get(); + IEventBus modEventBus = FMLJavaModLoadingContext.get() + .getModEventBus(); + IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; + AllSoundEvents.prepare(); AllBlocks.register(); AllItems.register(); @@ -101,31 +106,30 @@ public class Create { AllContainerTypes.register(); AllEntityTypes.register(); AllTileEntities.register(); + AllEnchantments.register(); + AllRecipeTypes.register(modEventBus); + AllParticleTypes.register(modEventBus); + AllStructureProcessorTypes.register(modEventBus); + AllEntityDataSerializers.register(modEventBus); + AllFeatures.register(modEventBus); + AllPlacementModifiers.register(modEventBus); + BuiltinRegistration.register(modEventBus); + + AllConfigs.register(modLoadingContext); + AllMovementBehaviours.registerDefaults(); AllInteractionBehaviours.registerDefaults(); AllDisplayBehaviours.registerDefaults(); ContraptionMovementSetting.registerDefaults(); AllArmInteractionPointTypes.register(); - AllWorldFeatures.register(); - AllEnchantments.register(); - AllConfigs.register(modLoadingContext); - BlockSpoutingBehaviour.register(); + BlockSpoutingBehaviour.registerDefaults(); ForgeMod.enableMilkFluid(); - CopperRegistries.inject(); - IEventBus modEventBus = FMLJavaModLoadingContext.get() - .getModEventBus(); - IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; - modEventBus.addListener(Create::init); modEventBus.addListener(EventPriority.LOWEST, Create::gatherData); - modEventBus.addListener(AllWorldFeatures::registerOreFeatures); - modEventBus.addListener(AllRecipeTypes::register); - modEventBus.addListener(AllParticleTypes::register); modEventBus.addListener(AllSoundEvents::register); - modEventBus.addListener(AllEntityDataSerializers::register); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus)); @@ -141,23 +145,24 @@ public class Create { event.enqueueWork(() -> { AllAdvancements.register(); AllTriggers.register(); - SchematicProcessor.register(); - AllWorldFeatures.registerFeatures(); - AllWorldFeatures.registerPlacementTypes(); BoilerHeaters.registerDefaults(); }); } public static void gatherData(GatherDataEvent event) { DataGenerator gen = event.getGenerator(); - gen.addProvider(true, new AllAdvancements(gen)); - gen.addProvider(true, new LangMerger(gen)); - gen.addProvider(true, AllSoundEvents.provider(gen)); - gen.addProvider(true, new StandardRecipeGen(gen)); - gen.addProvider(true, new MechanicalCraftingRecipeGen(gen)); - gen.addProvider(true, new SequencedAssemblyRecipeGen(gen)); - ProcessingRecipeGen.registerAll(gen); - AllWorldFeatures.generateBiomeModifiers(event); + if (event.includeClient()) { + gen.addProvider(true, new LangMerger(gen)); + gen.addProvider(true, AllSoundEvents.provider(gen)); + } + if (event.includeServer()) { + gen.addProvider(true, new AllAdvancements(gen)); + gen.addProvider(true, new StandardRecipeGen(gen)); + gen.addProvider(true, new MechanicalCraftingRecipeGen(gen)); + gen.addProvider(true, new SequencedAssemblyRecipeGen(gen)); + ProcessingRecipeGen.registerAll(gen); +// AllOreFeatureConfigEntries.gatherData(event); + } } public static CreateRegistrate registrate() { diff --git a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java index f96d95176..8915492b8 100644 --- a/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java +++ b/src/main/java/com/simibubi/create/api/behaviour/BlockSpoutingBehaviour.java @@ -46,7 +46,7 @@ public abstract class BlockSpoutingBehaviour { public abstract int fillBlock(Level world, BlockPos pos, SpoutTileEntity spout, FluidStack availableFluid, boolean simulate); - public static void register() { + public static void registerDefaults() { addCustomSpoutInteraction(Create.asResource("ticon_casting"), new SpoutCasting()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java index 38297459a..5b42f848f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java @@ -588,7 +588,7 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor public static HeatLevel getHeatLevelOf(BlockState state) { if (state.hasProperty(BlazeBurnerBlock.HEAT_LEVEL)) return state.getValue(BlazeBurnerBlock.HEAT_LEVEL); - return AllTags.AllBlockTags.FAN_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; + return AllTags.AllBlockTags.PASSIVE_BOILER_HEATERS.matches(state) ? HeatLevel.SMOULDERING : HeatLevel.NONE; } public Couple getTanks() { diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java b/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java index 677fad057..0937f2b7d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/AllArmorMaterials.java @@ -13,7 +13,7 @@ import net.minecraft.world.item.crafting.Ingredient; public enum AllArmorMaterials implements ArmorMaterial { - COPPER("copper", 7, new int[] { 1, 3, 4, 2 }, 25, AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, + COPPER("copper", 7, new int[] { 1, 3, 4, 2 }, 25, () -> AllSoundEvents.COPPER_ARMOR_EQUIP.getMainEvent(), 0.0F, 0.0F, () -> Ingredient.of(Items.COPPER_INGOT)) ; @@ -23,13 +23,13 @@ public enum AllArmorMaterials implements ArmorMaterial { private final int maxDamageFactor; private final int[] damageReductionAmountArray; private final int enchantability; - private final SoundEvent soundEvent; + private final Supplier soundEvent; private final float toughness; private final float knockbackResistance; private final Supplier repairMaterial; private AllArmorMaterials(String name, int maxDamageFactor, int[] damageReductionAmountArray, int enchantability, - SoundEvent soundEvent, float toughness, float knockbackResistance, Supplier repairMaterial) { + Supplier soundEvent, float toughness, float knockbackResistance, Supplier repairMaterial) { this.name = name; this.maxDamageFactor = maxDamageFactor; this.damageReductionAmountArray = damageReductionAmountArray; @@ -57,7 +57,7 @@ public enum AllArmorMaterials implements ArmorMaterial { @Override public SoundEvent getEquipSound() { - return this.soundEvent; + return this.soundEvent.get(); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java index 150aa9494..6a467744d 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java @@ -59,17 +59,27 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { super.read(compound, clientPacket); } - @Override - public void write(CompoundTag compound, boolean clientPacket) { + protected void writeCommon(CompoundTag compound) { compound.putFloat("OnAbove", onWhenAbove); compound.putFloat("OffBelow", offWhenBelow); + compound.putBoolean("Inverted", inverted); + } + + @Override + public void write(CompoundTag compound, boolean clientPacket) { + writeCommon(compound); compound.putFloat("Current", currentLevel); compound.putBoolean("Powered", redstoneState); - compound.putBoolean("Inverted", inverted); compound.putBoolean("PoweredAfterDelay", poweredAfterDelay); super.write(compound, clientPacket); } + @Override + public void writeSafe(CompoundTag compound) { + writeCommon(compound); + super.writeSafe(compound); + } + public float getStockLevel() { return currentLevel; } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index a07359ac7..e5507d8e7 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -5,6 +5,7 @@ import java.util.Optional; import javax.annotation.Nullable; import com.mojang.serialization.Codec; +import com.simibubi.create.AllStructureProcessorTypes; import com.simibubi.create.foundation.utility.NBTProcessors; import net.minecraft.core.BlockPos; @@ -21,18 +22,12 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProc import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate; public class SchematicProcessor extends StructureProcessor { - + public static final SchematicProcessor INSTANCE = new SchematicProcessor(); public static final Codec CODEC = Codec.unit(() -> { return INSTANCE; }); - - public static StructureProcessorType TYPE; - - public static void register() { - TYPE = StructureProcessorType.register("schematic", CODEC); - } - + @Nullable @Override public StructureTemplate.StructureBlockInfo process(LevelReader world, BlockPos pos, BlockPos anotherPos, StructureTemplate.StructureBlockInfo rawInfo, @@ -65,7 +60,7 @@ public class SchematicProcessor extends StructureProcessor { @Override protected StructureProcessorType getType() { - return TYPE; + return AllStructureProcessorTypes.SCHEMATIC.get(); } } diff --git a/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java b/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java index 8220e50df..6f03e44c5 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java +++ b/src/main/java/com/simibubi/create/foundation/config/CWorldGen.java @@ -1,22 +1,30 @@ package com.simibubi.create.foundation.config; -import com.simibubi.create.foundation.worldgen.AllWorldFeatures; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.worldgen.AllOreFeatureConfigEntries; import net.minecraftforge.common.ForgeConfigSpec.Builder; public class CWorldGen extends ConfigBase { + /** + * Increment this number if all worldgen config entries should be overwritten + * in this update. Worlds from the previous version will overwrite potentially + * changed values with the new defaults. + */ + public static final int FORCED_UPDATE_VERSION = 2; + public final ConfigBool disable = b(false, "disableWorldGen", Comments.disable); @Override protected void registerAll(Builder builder) { super.registerAll(builder); - AllWorldFeatures.fillConfig(builder); + AllOreFeatureConfigEntries.fillConfig(builder, Create.ID); } @Override public String getName() { - return "worldgen.v" + AllWorldFeatures.forcedUpdateVersion; + return "worldgen.v" + FORCED_UPDATE_VERSION; } private static class Comments { diff --git a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java b/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java index 5b8565da3..352975c79 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java +++ b/src/main/java/com/simibubi/create/foundation/config/ConfigBase.java @@ -63,6 +63,10 @@ public abstract class ConfigBase { return i(current, min, Integer.MAX_VALUE, name, comment); } + protected ConfigInt i(int current, String name, String... comment) { + return i(current, Integer.MIN_VALUE, Integer.MAX_VALUE, name, comment); + } + protected > ConfigEnum e(T defaultValue, String name, String... comment) { return new ConfigEnum<>(name, defaultValue, comment); } diff --git a/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java b/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java index c6d012ce0..f197203bd 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java +++ b/src/main/java/com/simibubi/create/foundation/config/ContraptionMovementSetting.java @@ -31,7 +31,10 @@ public enum ContraptionMovementSetting { public static ContraptionMovementSetting get(Block block) { if (block instanceof IMovementSettingProvider provider) return provider.getContraptionMovementSetting(); - return SETTING_SUPPLIERS.get(block).get(); + Supplier supplier = SETTING_SUPPLIERS.get(block); + if (supplier == null) + return null; + return supplier.get(); } public static boolean allAre(Collection blocks, ContraptionMovementSetting are) { diff --git a/src/main/java/com/simibubi/create/foundation/data/DynamicDataProvider.java b/src/main/java/com/simibubi/create/foundation/data/DynamicDataProvider.java new file mode 100644 index 000000000..6526a8b05 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/DynamicDataProvider.java @@ -0,0 +1,87 @@ +package com.simibubi.create.foundation.data; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + +import org.jetbrains.annotations.Nullable; + +import com.google.gson.JsonElement; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.Encoder; +import com.mojang.serialization.JsonOps; +import com.simibubi.create.Create; + +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.RegistryAccess.RegistryData; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.DataProvider; +import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.ForgeHooks; + +public class DynamicDataProvider implements DataProvider { + private final DataGenerator generator; + private final String name; + private final RegistryAccess registryAccess; + private final RegistryAccess.RegistryData registryData; + private final Map values; + + public DynamicDataProvider(DataGenerator generator, String name, RegistryAccess registryAccess, RegistryAccess.RegistryData registryData, Map values) { + this.generator = generator; + this.name = name; + this.registryAccess = registryAccess; + this.registryData = registryData; + this.values = values; + } + + @Nullable + public static DynamicDataProvider create(DataGenerator generator, String name, RegistryAccess registryAccess, ResourceKey> registryKey, Map values) { + @SuppressWarnings("unchecked") + RegistryAccess.RegistryData registryData = (RegistryData) RegistryAccess.REGISTRIES.get(registryKey); + if (registryData == null) { + return null; + } + return new DynamicDataProvider<>(generator, name, registryAccess, registryData, values); + } + + @Override + public void run(CachedOutput cache) throws IOException { + Path path = generator.getOutputFolder(); + DynamicOps ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess); + + dumpValues(path, cache, ops, registryData.key(), values, registryData.codec()); + } + + private void dumpValues(Path rootPath, CachedOutput cache, DynamicOps ops, ResourceKey> registryKey, Map values, Encoder encoder) { + DataGenerator.PathProvider pathProvider = generator.createPathProvider(DataGenerator.Target.DATA_PACK, ForgeHooks.prefixNamespace(registryKey.location())); + + for (Entry entry : values.entrySet()) { + dumpValue(pathProvider.json(entry.getKey()), cache, ops, encoder, entry.getValue()); + } + } + + // From WorldgenRegistryDumpReport + private void dumpValue(Path path, CachedOutput cache, DynamicOps ops, Encoder encoder, T value) { + try { + Optional optional = encoder.encodeStart(ops, value).resultOrPartial((message) -> { + Create.LOGGER.error("Couldn't serialize element {}: {}", path, message); + }); + if (optional.isPresent()) { + DataProvider.saveStable(cache, optional.get(), path); + } + } catch (IOException e) { + Create.LOGGER.error("Couldn't save element {}", path, e); + } + } + + @Override + public String getName() { + return name; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java index ef879d3b6..ed573d2c6 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java @@ -133,7 +133,7 @@ public class PonderUI extends NavigatableSimiScreen { return ui; } - PonderUI(List scenes) { + protected PonderUI(List scenes) { ResourceLocation component = scenes.get(0) .getComponent(); if (ForgeRegistries.ITEMS.containsKey(component)) @@ -567,65 +567,8 @@ public class PonderUI extends NavigatableSimiScreen { noWidgetsHovered &= !child.isMouseOver(mouseX, mouseY); int tooltipColor = Theme.i(Theme.Key.TEXT_DARKER); - { - // Chapter title - ms.pushPose(); - ms.translate(0, 0, 400); - int x = 31 + 20 + 8; - int y = 31; - - String title = activeScene.getTitle(); - int wordWrappedHeight = font.wordWrapHeight(title, left.x - 51); - - int streakHeight = 35 - 9 + wordWrappedHeight; - UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade)); - UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade)); - new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) - .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) - .at(21, 21, 100) - .withBounds(30, 30) - .render(ms); - - GuiGameElement.of(stack) - .scale(2) - .at(x - 39, y - 11) - .render(ms); - - font.draw(ms, Lang.translateDirect(PONDERING), x, y - 6, tooltipColor); - y += 8; - x += 0; - ms.translate(x, y, 0); - ms.mulPose(Vector3f.XN.rotationDegrees(indexDiff * -75)); - ms.translate(0, 0, 5); - FontHelper.drawSplitString(ms, font, title, 0, 0, left.x - 51, Theme.c(Theme.Key.TEXT) - .scaleAlpha(1 - indexDiff) - .getRGB()); - ms.popPose(); - - if (chapter != null) { - ms.pushPose(); - - ms.translate(chap.x - 4 - 4, chap.y, 0); - UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade)); - - drawRightAlignedString(font, ms, Lang.translateDirect(IN_CHAPTER) - .getString(), 0, 0, tooltipColor); - drawRightAlignedString(font, ms, chapter.getTitle(), 0, 12, Theme.i(Theme.Key.TEXT)); - - ms.popPose(); - } - - Color c1 = Theme.c(Theme.Key.PONDER_BACK_ARROW) - .setAlpha(0x40); - Color c2 = Theme.c(Theme.Key.PONDER_BACK_ARROW) - .setAlpha(0x20); - Color c3 = Theme.c(Theme.Key.PONDER_BACK_ARROW) - .setAlpha(0x10); - UIRenderHelper.breadcrumbArrow(ms, width / 2 - 20, height - 51, 0, 20, 20, 5, c1, c2); - UIRenderHelper.breadcrumbArrow(ms, width / 2 + 20, height - 51, 0, -20, 20, -5, c1, c2); - UIRenderHelper.breadcrumbArrow(ms, width / 2 - 90, height - 51, 0, 70, 20, 5, c1, c3); - UIRenderHelper.breadcrumbArrow(ms, width / 2 + 90, height - 51, 0, -70, 20, -5, c1, c3); - } + renderChapterTitle(ms, fade, indexDiff, activeScene, tooltipColor); + renderNavigationMenu(ms); if (identifyMode) { if (noWidgetsHovered && mouseY < height - 80) { @@ -637,17 +580,8 @@ public class PonderUI extends NavigatableSimiScreen { ((MutableComponent) minecraft.options.keyDrop.getTranslatedKeyMessage()) .withStyle(ChatFormatting.WHITE)) .withStyle(ChatFormatting.GRAY); - - // renderOrderedTooltip(ms, textRenderer.wrapLines(text, width / 3), 0, 0); renderComponentTooltip(ms, font.getSplitter() .splitLines(text, width / 3, Style.EMPTY), 0, 0, font); - /* - * String tooltip = Lang .createTranslationTextComponent(IDENTIFY_MODE, - * client.gameSettings.keyBindDrop.getBoundKeyLocalizedText().applyTextStyle( - * TextFormatting.WHITE)) .applyTextStyle(TextFormatting.GRAY) - * .getFormattedText(); renderTooltip(font.listFormattedStringToWidth(tooltip, - * width / 3), 0, 0); - */ } else renderTooltip(ms, hoveredTooltipItem, 0, 0); if (hoveredBlockPos != null && PonderIndex.editingModeActive() && !userViewMode) { @@ -677,30 +611,12 @@ public class PonderUI extends NavigatableSimiScreen { else slowMode.dim(); - { - // Scene overlay - float scenePT = skipCooling > 0 ? 0 : partialTicks; - ms.pushPose(); - ms.translate(0, 0, 100); - renderOverlay(ms, index, scenePT); - if (indexDiff > 1 / 512f) - renderOverlay(ms, lazyIndexValue < index ? index - 1 : index + 1, scenePT); - ms.popPose(); - } + renderSceneOverlay(ms, partialTicks, lazyIndexValue, indexDiff); boolean finished = activeScene.isFinished(); - // Next up: - if (finished && nextScene != null && nextUp.getValue() > 1 / 16f && !nextScene.getId() - .equals(Create.asResource("creative_motor_mojang"))) { - ms.pushPose(); - ms.translate(right.x + 10, right.y - 6 + nextUp.getValue(partialTicks) * 5, 400); - int boxWidth = (Math.max(font.width(nextScene.getTitle()), font.width(Lang.translateDirect(NEXT_UP))) + 5); - renderSpeechBox(ms, 0, 0, boxWidth, 20, right.isHoveredOrFocused(), Pointing.DOWN, false); - ms.translate(0, -29, 100); - drawCenteredString(ms, font, Lang.translateDirect(NEXT_UP), 0, 0, Theme.i(Theme.Key.TEXT_DARKER)); - drawCenteredString(ms, font, nextScene.getTitle(), 0, 10, Theme.i(Theme.Key.TEXT)); - ms.popPose(); + if (finished) { + jumpToNextScene(ms, partialTicks, nextScene); } // Widgets @@ -725,6 +641,13 @@ public class PonderUI extends NavigatableSimiScreen { nextUp.updateChaseTarget(0); } + renderPonderTags(ms, mouseX, mouseY, partialTicks, fade, activeScene); + + renderHoverTooltips(ms, tooltipColor); + RenderSystem.enableDepthTest(); + } + + protected void renderPonderTags(PoseStack ms, int mouseX, int mouseY, float partialTicks, float fade, PonderScene activeScene) { // Tags List sceneTags = activeScene.getTags(); boolean highlightAll = sceneTags.contains(PonderTag.Highlight.ALL); @@ -765,7 +688,34 @@ public class PonderUI extends NavigatableSimiScreen { ms.popPose(); }); + } + protected void renderSceneOverlay(PoseStack ms, float partialTicks, float lazyIndexValue, float indexDiff) { + // Scene overlay + float scenePT = skipCooling > 0 ? 0 : partialTicks; + ms.pushPose(); + ms.translate(0, 0, 100); + renderOverlay(ms, index, scenePT); + if (indexDiff > 1 / 512f) + renderOverlay(ms, lazyIndexValue < index ? index - 1 : index + 1, scenePT); + ms.popPose(); + } + + protected void jumpToNextScene(PoseStack ms, float partialTicks, PonderScene nextScene) { + if (nextScene != null && nextUp.getValue() > 1 / 16f && !nextScene.getId() + .equals(Create.asResource("creative_motor_mojang"))) { + ms.pushPose(); + ms.translate(right.x + 10, right.y - 6 + nextUp.getValue(partialTicks) * 5, 400); + int boxWidth = (Math.max(font.width(nextScene.getTitle()), font.width(Lang.translateDirect(NEXT_UP))) + 5); + renderSpeechBox(ms, 0, 0, boxWidth, 20, right.isHoveredOrFocused(), Pointing.DOWN, false); + ms.translate(0, -29, 100); + drawCenteredString(ms, font, Lang.translateDirect(NEXT_UP), 0, 0, Theme.i(Theme.Key.TEXT_DARKER)); + drawCenteredString(ms, font, nextScene.getTitle(), 0, 10, Theme.i(Theme.Key.TEXT)); + ms.popPose(); + } + } + + protected void renderHoverTooltips(PoseStack ms, int tooltipColor) { ms.pushPose(); ms.translate(0, 0, 500); int tooltipY = height - 16; @@ -784,8 +734,67 @@ public class PonderUI extends NavigatableSimiScreen { if (PonderIndex.editingModeActive() && userMode.isHoveredOrFocused()) drawCenteredString(ms, font, "Editor View", userMode.x + 10, tooltipY, tooltipColor); ms.popPose(); + } - RenderSystem.enableDepthTest(); + protected void renderChapterTitle(PoseStack ms, float fade, float indexDiff, PonderScene activeScene, int tooltipColor) { + // Chapter title + ms.pushPose(); + ms.translate(0, 0, 400); + int x = 31 + 20 + 8; + int y = 31; + + String title = activeScene.getTitle(); + int wordWrappedHeight = font.wordWrapHeight(title, left.x - 51); + + int streakHeight = 35 - 9 + wordWrappedHeight; + UIRenderHelper.streak(ms, 0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade)); + UIRenderHelper.streak(ms, 180, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (30 * fade)); + new BoxElement().withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) + .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) + .at(21, 21, 100) + .withBounds(30, 30) + .render(ms); + + GuiGameElement.of(stack) + .scale(2) + .at(x - 39f, y - 11f) + .render(ms); + + font.draw(ms, Lang.translateDirect(PONDERING), x, y - 6, tooltipColor); + y += 8; + x += 0; + ms.translate(x, y, 0); + ms.mulPose(Vector3f.XN.rotationDegrees(indexDiff * -75)); + ms.translate(0, 0, 5); + FontHelper.drawSplitString(ms, font, title, 0, 0, left.x - 51, Theme.c(Theme.Key.TEXT) + .scaleAlpha(1 - indexDiff) + .getRGB()); + ms.popPose(); + if (chapter != null) { + ms.pushPose(); + + ms.translate(chap.x - 8, chap.y, 0); + UIRenderHelper.streak(ms, 180, 4, 10, 26, (int) (150 * fade)); + + drawRightAlignedString(font, ms, Lang.translateDirect(IN_CHAPTER) + .getString(), 0, 0, tooltipColor); + drawRightAlignedString(font, ms, chapter.getTitle(), 0, 12, Theme.i(Theme.Key.TEXT)); + + ms.popPose(); + } + } + + protected void renderNavigationMenu(PoseStack ms) { + Color c1 = Theme.c(Theme.Key.PONDER_BACK_ARROW) + .setAlpha(0x40); + Color c2 = Theme.c(Theme.Key.PONDER_BACK_ARROW) + .setAlpha(0x20); + Color c3 = Theme.c(Theme.Key.PONDER_BACK_ARROW) + .setAlpha(0x10); + UIRenderHelper.breadcrumbArrow(ms, width / 2 - 20, height - 51, 0, 20, 20, 5, c1, c2); + UIRenderHelper.breadcrumbArrow(ms, width / 2 + 20, height - 51, 0, -20, 20, -5, c1, c2); + UIRenderHelper.breadcrumbArrow(ms, width / 2 - 90, height - 51, 0, 70, 20, 5, c1, c3); + UIRenderHelper.breadcrumbArrow(ms, width / 2 + 90, height - 51, 0, -70, 20, -5, c1, c3); } private void renderOverlay(PoseStack ms, int i, float partialTicks) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java b/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java index 4986354f5..236d38d16 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java +++ b/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java @@ -1,36 +1,50 @@ package com.simibubi.create.foundation.utility; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; import javax.annotation.Nonnull; import net.minecraft.world.level.LevelAccessor; -import net.minecraftforge.common.util.NonNullFunction; public class WorldAttached { - static List> allMaps = new ArrayList<>(); - Map attached; - private final NonNullFunction factory; + // weak references to prevent leaking hashmaps when a WorldAttached is GC'd during runtime + static List>> allMaps = new ArrayList<>(); + private final Map attached; + private final Function factory; - public WorldAttached(NonNullFunction factory) { + public WorldAttached(Function factory) { this.factory = factory; attached = new HashMap<>(); - allMaps.add(attached); + allMaps.add(new WeakReference<>(attached)); } public static void invalidateWorld(LevelAccessor world) { - allMaps.forEach(m -> m.remove(world)); + var i = allMaps.iterator(); + while (i.hasNext()) { + Map map = i.next() + .get(); + if (map == null) { + // If the map has been GC'd, remove the weak reference + i.remove(); + } else { + // Prevent leaks + map.remove(world); + } + } } @Nonnull public T get(LevelAccessor world) { T t = attached.get(world); - if (t != null) - return t; + if (t != null) return t; T entry = factory.apply(world); put(world, entry); return entry; @@ -40,4 +54,47 @@ public class WorldAttached { attached.put(world, entry); } + /** + * Replaces the entry with a new one from the factory and returns the new entry. + */ + @Nonnull + public T replace(LevelAccessor world) { + attached.remove(world); + + return get(world); + } + + /** + * Replaces the entry with a new one from the factory and returns the new entry. + */ + @Nonnull + public T replace(LevelAccessor world, Consumer finalizer) { + T remove = attached.remove(world); + + if (remove != null) + finalizer.accept(remove); + + return get(world); + } + + /** + * Deletes all entries after calling a function on them. + * + * @param finalizer Do something with all of the world-value pairs + */ + public void empty(BiConsumer finalizer) { + attached.forEach(finalizer); + attached.clear(); + } + + /** + * Deletes all entries after calling a function on them. + * + * @param finalizer Do something with all of the values + */ + public void empty(Consumer finalizer) { + attached.values() + .forEach(finalizer); + attached.clear(); + } } diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllFeatures.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllFeatures.java new file mode 100644 index 000000000..5fa2a98c2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/AllFeatures.java @@ -0,0 +1,20 @@ +package com.simibubi.create.foundation.worldgen; + +import com.simibubi.create.Create; + +import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; + +public class AllFeatures { + private static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.FEATURES, Create.ID); + + public static final RegistryObject STANDARD_ORE = REGISTER.register("standard_ore", () -> new StandardOreFeature()); + public static final RegistryObject LAYERED_ORE = REGISTER.register("layered_ore", () -> new LayeredOreFeature()); + + public static void register(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllLayerPatterns.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllLayerPatterns.java index 4908780fe..395894742 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/AllLayerPatterns.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/AllLayerPatterns.java @@ -7,7 +7,7 @@ import net.minecraft.world.level.block.Blocks; public class AllLayerPatterns { - public static NonNullSupplier + public static final NonNullSupplier CINNABAR = () -> LayerPattern.builder() .layer(l -> l.weight(1) @@ -25,7 +25,7 @@ public class AllLayerPatterns { .block(AllPaletteStoneTypes.LIMESTONE.getBaseBlock())) .build(); - public static NonNullSupplier MAGNETITE = () -> LayerPattern.builder() + public static final NonNullSupplier MAGNETITE = () -> LayerPattern.builder() .layer(l -> l.weight(1) .passiveBlock()) .layer(l -> l.weight(2) @@ -41,7 +41,7 @@ public class AllLayerPatterns { .block(Blocks.CALCITE)) .build(); - public static NonNullSupplier OCHRESTONE = () -> LayerPattern.builder() + public static final NonNullSupplier OCHRESTONE = () -> LayerPattern.builder() .layer(l -> l.weight(1) .passiveBlock()) .layer(l -> l.weight(2) @@ -56,7 +56,7 @@ public class AllLayerPatterns { .size(1, 2)) .build(); - public static NonNullSupplier MALACHITE = () -> LayerPattern.builder() + public static final NonNullSupplier MALACHITE = () -> LayerPattern.builder() .layer(l -> l.weight(2) .passiveBlock()) .layer(l -> l.weight(4) @@ -72,7 +72,7 @@ public class AllLayerPatterns { .block(Blocks.SMOOTH_BASALT)) .build(); - public static NonNullSupplier SCORIA = () -> LayerPattern.builder() + public static final NonNullSupplier SCORIA = () -> LayerPattern.builder() .layer(l -> l.weight(1) .passiveBlock()) .layer(l -> l.weight(2) @@ -88,7 +88,7 @@ public class AllLayerPatterns { .block(Blocks.DIORITE)) .build(); - public static NonNullSupplier LIMESTONE = () -> LayerPattern.builder() + public static final NonNullSupplier LIMESTONE = () -> LayerPattern.builder() .layer(l -> l.weight(1) .passiveBlock()) .layer(l -> l.weight(2) @@ -100,7 +100,7 @@ public class AllLayerPatterns { .size(1, 4)) .build(); - public static NonNullSupplier SCORIA_NETHER = () -> LayerPattern.builder() + public static final NonNullSupplier SCORIA_NETHER = () -> LayerPattern.builder() .inNether() .layer(l -> l.weight(1) .passiveBlock()) @@ -115,7 +115,7 @@ public class AllLayerPatterns { .block(Blocks.SMOOTH_BASALT)) .build(); - public static NonNullSupplier SCORCHIA_NETHER = () -> LayerPattern.builder() + public static final NonNullSupplier SCORCHIA_NETHER = () -> LayerPattern.builder() .inNether() .layer(l -> l.weight(2) .passiveBlock()) diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllOreFeatureConfigEntries.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllOreFeatureConfigEntries.java new file mode 100644 index 000000000..0e23c7919 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/AllOreFeatureConfigEntries.java @@ -0,0 +1,106 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.HashMap; +import java.util.Map; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.data.DynamicDataProvider; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.worldgen.OreFeatureConfigEntry.DatagenExtension; + +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.data.DataGenerator; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.BiomeTags; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.data.event.GatherDataEvent; + +public class AllOreFeatureConfigEntries { + public static final OreFeatureConfigEntry ZINC_ORE = + create("zinc_ore", 12, 8, -63, 70) + .standardDatagenExt() + .withBlocks(Couple.create(AllBlocks.ZINC_ORE, AllBlocks.DEEPSLATE_ZINC_ORE)) + .biomeTag(BiomeTags.IS_OVERWORLD) + .parent(); + + public static final OreFeatureConfigEntry STRIATED_ORES_OVERWORLD = + create("striated_ores_overworld", 32, 1 / 12f, -30, 70) + .layeredDatagenExt() + .withLayerPattern(AllLayerPatterns.SCORIA) + .withLayerPattern(AllLayerPatterns.CINNABAR) + .withLayerPattern(AllLayerPatterns.MAGNETITE) + .withLayerPattern(AllLayerPatterns.MALACHITE) + .withLayerPattern(AllLayerPatterns.LIMESTONE) + .withLayerPattern(AllLayerPatterns.OCHRESTONE) + .biomeTag(BiomeTags.IS_OVERWORLD) + .parent(); + + public static final OreFeatureConfigEntry STRIATED_ORES_NETHER = + create("striated_ores_nether", 32, 1 / 12f, 40, 90) + .layeredDatagenExt() + .withLayerPattern(AllLayerPatterns.SCORIA_NETHER) + .withLayerPattern(AllLayerPatterns.SCORCHIA_NETHER) + .biomeTag(BiomeTags.IS_NETHER) + .parent(); + + // + + private static OreFeatureConfigEntry create(String name, int clusterSize, float frequency, + int minHeight, int maxHeight) { + ResourceLocation id = Create.asResource(name); + OreFeatureConfigEntry configDrivenFeatureEntry = new OreFeatureConfigEntry(id, clusterSize, frequency, minHeight, maxHeight); + return configDrivenFeatureEntry; + } + + public static void fillConfig(ForgeConfigSpec.Builder builder, String namespace) { + OreFeatureConfigEntry.ALL + .forEach((id, entry) -> { + if (id.getNamespace().equals(namespace)) { + builder.push(entry.getName()); + entry.addToConfig(builder); + builder.pop(); + } + }); + } + + public static void init() {} + + public static void gatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + RegistryAccess registryAccess = RegistryAccess.BUILTIN.get(); + + // + + Map> configuredFeatures = new HashMap<>(); + for (Map.Entry entry : OreFeatureConfigEntry.ALL.entrySet()) { + DatagenExtension datagenExt = entry.getValue().datagenExt(); + if (datagenExt != null) { + configuredFeatures.put(entry.getKey(), datagenExt.getConfiguredFeature()); + } + } + + DynamicDataProvider> configuredFeatureProvider = DynamicDataProvider.create(generator, "Create's Configured Features", registryAccess, Registry.CONFIGURED_FEATURE_REGISTRY, configuredFeatures); + if (configuredFeatureProvider != null) { + generator.addProvider(true, configuredFeatureProvider); + } + + // + + Map placedFeatures = new HashMap<>(); + for (Map.Entry entry : OreFeatureConfigEntry.ALL.entrySet()) { + DatagenExtension datagenExt = entry.getValue().datagenExt(); + if (datagenExt != null) { + placedFeatures.put(entry.getKey(), datagenExt.getPlacedFeature()); + } + } + + DynamicDataProvider placedFeatureProvider = DynamicDataProvider.create(generator, "Create's Placed Features", registryAccess, Registry.PLACED_FEATURE_REGISTRY, placedFeatures); + if (placedFeatureProvider != null) { + generator.addProvider(true, placedFeatureProvider); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllPlacementModifiers.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllPlacementModifiers.java new file mode 100644 index 000000000..fd8ce11bc --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/AllPlacementModifiers.java @@ -0,0 +1,19 @@ +package com.simibubi.create.foundation.worldgen; + +import com.simibubi.create.Create; + +import net.minecraft.core.Registry; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +public class AllPlacementModifiers { + private static final DeferredRegister> REGISTER = DeferredRegister.create(Registry.PLACEMENT_MODIFIER_REGISTRY, Create.ID); + + public static final RegistryObject> CONFIG_DRIVEN = REGISTER.register("config_driven", () -> () -> ConfigDrivenPlacement.CODEC); + + public static void register(IEventBus modEventBus) { + REGISTER.register(modEventBus); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java b/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java deleted file mode 100644 index fabcec9b4..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/AllWorldFeatures.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import com.google.common.collect.ImmutableList; -import com.google.gson.JsonElement; -import com.mojang.serialization.JsonOps; -import com.simibubi.create.AllBlocks; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.utility.Couple; - -import net.minecraft.core.HolderSet; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.data.BuiltinRegistries; -import net.minecraft.data.DataGenerator; -import net.minecraft.resources.RegistryOps; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.BiomeTags; -import net.minecraft.tags.TagKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.levelgen.GenerationStep.Decoration; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.common.data.JsonCodecProvider; -import net.minecraftforge.common.world.BiomeModifier; -import net.minecraftforge.common.world.ForgeBiomeModifiers.AddFeaturesBiomeModifier; -import net.minecraftforge.data.event.GatherDataEvent; -import net.minecraftforge.registries.ForgeRegistries.Keys; -import net.minecraftforge.registries.RegisterEvent; - -public class AllWorldFeatures { - - public static final Map ENTRIES = new HashMap<>(); - - // - - public static final ConfigDrivenFeatureEntry ZINC_ORE = - register("zinc_ore", 12, 8, BiomeTags.IS_OVERWORLD).between(-63, 70) - .withBlocks(Couple.create(AllBlocks.ZINC_ORE, AllBlocks.DEEPSLATE_ZINC_ORE)); - - public static final ConfigDrivenFeatureEntry STRIATED_ORES_OVERWORLD = - register("striated_ores_overworld", 32, 1 / 12f, BiomeTags.IS_OVERWORLD).between(-30, 70) - .withLayerPattern(AllLayerPatterns.SCORIA) - .withLayerPattern(AllLayerPatterns.CINNABAR) - .withLayerPattern(AllLayerPatterns.MAGNETITE) - .withLayerPattern(AllLayerPatterns.MALACHITE) - .withLayerPattern(AllLayerPatterns.LIMESTONE) - .withLayerPattern(AllLayerPatterns.OCHRESTONE); - - public static final ConfigDrivenFeatureEntry STRIATED_ORES_NETHER = - register("striated_ores_nether", 32, 1 / 12f, BiomeTags.IS_NETHER).between(40, 90) - .withLayerPattern(AllLayerPatterns.SCORIA_NETHER) - .withLayerPattern(AllLayerPatterns.SCORCHIA_NETHER); - - // - - private static ConfigDrivenFeatureEntry register(String id, int clusterSize, float frequency, - TagKey biomeTag) { - ConfigDrivenFeatureEntry configDrivenFeatureEntry = new ConfigDrivenFeatureEntry(id, clusterSize, frequency); - configDrivenFeatureEntry.biomeTag = biomeTag; - ENTRIES.put(Create.asResource(id), configDrivenFeatureEntry); - return configDrivenFeatureEntry; - } - - /** - * Increment this number if all worldgen entries should be overwritten in this - * update. Worlds from the previous version will overwrite potentially changed - * values with the new defaults. - */ - public static final int forcedUpdateVersion = 2; - - public static void registerFeatures() { - ENTRIES.entrySet() - .forEach(entry -> { - String id = Create.ID + "_" + entry.getKey() - .getPath(); - ConfigDrivenFeatureEntry featureEntry = entry.getValue(); - featureEntry.configuredFeature = BuiltinRegistries.register(BuiltinRegistries.CONFIGURED_FEATURE, id, - featureEntry.factory.apply(featureEntry)); - featureEntry.placedFeature = - BuiltinRegistries.register(BuiltinRegistries.PLACED_FEATURE, id, new PlacedFeature( - featureEntry.configuredFeature, ImmutableList.of(new ConfigDrivenDecorator(featureEntry.id)))); - }); - } - - public static void fillConfig(ForgeConfigSpec.Builder builder) { - ENTRIES.values() - .forEach(entry -> { - builder.push(entry.id); - entry.addToConfig(builder); - builder.pop(); - }); - } - - public static void register() {} - - public static void registerOreFeatures(RegisterEvent event) { - event.register(Registry.FEATURE_REGISTRY, helper -> { - helper.register(Create.asResource("config_driven_ore"), VanillaStyleOreFeature.INSTANCE); - helper.register(Create.asResource("config_driven_layered_ore"), LayeredOreFeature.INSTANCE); - }); - } - - public static void registerPlacementTypes() { - ConfigDrivenDecorator.TYPE = - Registry.register(Registry.PLACEMENT_MODIFIERS, "create_config_driven", () -> ConfigDrivenDecorator.CODEC); - } - - public static void generateBiomeModifiers(GatherDataEvent event) { - Map modifiers = new HashMap<>(); - RegistryOps ops = RegistryOps.create(JsonOps.INSTANCE, RegistryAccess.builtinCopy()); - - for (Entry entry : ENTRIES.entrySet()) { - ConfigDrivenFeatureEntry feature = entry.getValue(); - HolderSet biomes = new HolderSet.Named<>(ops.registry(Registry.BIOME_REGISTRY) - .get(), feature.biomeTag); - modifiers.put(entry.getKey(), new AddFeaturesBiomeModifier(biomes, HolderSet.direct(feature.placedFeature), - Decoration.UNDERGROUND_ORES)); - } - - DataGenerator generator = event.getGenerator(); - generator.addProvider(event.includeServer(), JsonCodecProvider.forDatapackRegistry(generator, - event.getExistingFileHelper(), Create.ID, ops, Keys.BIOME_MODIFIERS, modifiers)); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureBase.java b/src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeature.java similarity index 65% rename from src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureBase.java rename to src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeature.java index ba211f1ed..a2299fb3e 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureBase.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeature.java @@ -2,24 +2,25 @@ package com.simibubi.create.foundation.worldgen; import java.util.function.Function; +import com.mojang.serialization.Codec; + import net.minecraft.core.BlockPos; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; -public abstract class OreFeatureBase extends Feature { - - public OreFeatureBase() { - super(ConfigDrivenOreConfiguration.CODEC); +public abstract class BaseConfigDrivenOreFeature extends Feature { + public BaseConfigDrivenOreFeature(Codec configCodec) { + super(configCodec); } public boolean canPlaceOre(BlockState pState, Function pAdjacentStateAccessor, - RandomSource pRandom, ConfigDrivenOreConfiguration pConfig, OreConfiguration.TargetBlockState pTargetState, + RandomSource pRandom, BaseConfigDrivenOreFeatureConfiguration pConfig, OreConfiguration.TargetBlockState pTargetState, BlockPos.MutableBlockPos pMatablePos) { if (!pTargetState.target.test(pState, pRandom)) return false; - if (shouldSkipAirCheck(pRandom, pConfig.discardChanceOnAirExposure)) + if (shouldSkipAirCheck(pRandom, pConfig.getDiscardChanceOnAirExposure())) return true; return !isAdjacentToAir(pAdjacentStateAccessor, pMatablePos); diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeatureConfiguration.java b/src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeatureConfiguration.java new file mode 100644 index 000000000..1c741236f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/BaseConfigDrivenOreFeatureConfiguration.java @@ -0,0 +1,25 @@ +package com.simibubi.create.foundation.worldgen; + +import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; + +public class BaseConfigDrivenOreFeatureConfiguration implements FeatureConfiguration { + protected final OreFeatureConfigEntry entry; + protected final float discardChanceOnAirExposure; + + public BaseConfigDrivenOreFeatureConfiguration(OreFeatureConfigEntry entry, float discardChance) { + this.entry = entry; + this.discardChanceOnAirExposure = discardChance; + } + + public OreFeatureConfigEntry getEntry() { + return entry; + } + + public int getClusterSize() { + return entry.clusterSize.get(); + } + + public float getDiscardChanceOnAirExposure() { + return discardChanceOnAirExposure; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/BiomeFilter.java b/src/main/java/com/simibubi/create/foundation/worldgen/BiomeFilter.java deleted file mode 100644 index 4f6599610..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/BiomeFilter.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.function.Function; - -import net.minecraft.core.HolderSet; -import net.minecraft.resources.RegistryOps; -import net.minecraft.world.level.biome.Biome; - -public interface BiomeFilter extends Function, HolderSet> { - -} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/BuiltinRegistration.java b/src/main/java/com/simibubi/create/foundation/worldgen/BuiltinRegistration.java new file mode 100644 index 000000000..fceb17b7c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/BuiltinRegistration.java @@ -0,0 +1,41 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.Map; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.worldgen.OreFeatureConfigEntry.DatagenExtension; + +import net.minecraft.core.Registry; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraftforge.common.world.BiomeModifier; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +public class BuiltinRegistration { + private static final DeferredRegister> CONFIGURED_FEATURE_REGISTER = DeferredRegister.create(Registry.CONFIGURED_FEATURE_REGISTRY, Create.ID); + private static final DeferredRegister PLACED_FEATURE_REGISTER = DeferredRegister.create(Registry.PLACED_FEATURE_REGISTRY, Create.ID); + private static final DeferredRegister BIOME_MODIFIER_REGISTER = DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIERS, Create.ID); + + static { + for (Map.Entry entry : OreFeatureConfigEntry.ALL.entrySet()) { + ResourceLocation id = entry.getKey(); + if (id.getNamespace().equals(Create.ID)) { + DatagenExtension datagenExt = entry.getValue().datagenExt(); + if (datagenExt != null) { + CONFIGURED_FEATURE_REGISTER.register(id.getPath(), () -> datagenExt.getConfiguredFeature()); + PLACED_FEATURE_REGISTER.register(id.getPath(), () -> datagenExt.getPlacedFeature()); + BIOME_MODIFIER_REGISTER.register(id.getPath(), () -> datagenExt.getBiomeModifier()); + } + } + } + } + + public static void register(IEventBus modEventBus) { + CONFIGURED_FEATURE_REGISTER.register(modEventBus); + PLACED_FEATURE_REGISTER.register(modEventBus); + BIOME_MODIFIER_REGISTER.register(modEventBus); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java deleted file mode 100644 index 206fbc209..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenDecorator.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.simibubi.create.Create; - -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.levelgen.placement.PlacementContext; -import net.minecraft.world.level.levelgen.placement.PlacementModifier; -import net.minecraft.world.level.levelgen.placement.PlacementModifierType; - -public class ConfigDrivenDecorator extends PlacementModifier { - - public static PlacementModifierType TYPE; - - public static final Codec CODEC = RecordCodecBuilder.create((p_67849_) -> { - return p_67849_.group(Codec.STRING.fieldOf("key") - .forGetter(t -> t.key.getPath())) - .apply(p_67849_, ConfigDrivenDecorator::new); - }); - - private ResourceLocation key; - - public ConfigDrivenDecorator(String key) { - this.key = Create.asResource(key); - } - - @Override - public PlacementModifierType type() { - return TYPE; - } - - @Override - public Stream getPositions(PlacementContext context, RandomSource random, BlockPos pos) { - ConfigDrivenOreConfiguration config = (ConfigDrivenOreConfiguration) entry().configuredFeature.value() - .config(); - - float frequency = config.getFrequency(); - int floored = Mth.floor(frequency); - int count = floored + (random.nextFloat() < frequency - floored ? 1 : 0); - if (count == 0) - return Stream.empty(); - - int maxY = config.getMaxY(); - int minY = config.getMinY(); - - return IntStream.range(0, count) - .mapToObj($ -> pos) - .map(p -> { - int i = p.getX(); - int j = p.getZ(); - int k = random.nextInt(maxY - minY) + minY; - return new BlockPos(i, k, j); - }); - } - - protected ConfigDrivenFeatureEntry entry() { - return AllWorldFeatures.ENTRIES.get(key); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java deleted file mode 100644 index f6b15b983..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenFeatureEntry.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import com.google.common.collect.ImmutableList; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.ConfigBase; -import com.simibubi.create.foundation.utility.Couple; -import com.tterrag.registrate.util.nullness.NonNullSupplier; - -import net.minecraft.core.Holder; -import net.minecraft.data.worldgen.features.OreFeatures; -import net.minecraft.tags.TagKey; -import net.minecraft.world.level.biome.Biome; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; -import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; -import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState; -import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import net.minecraftforge.common.ForgeConfigSpec; - -public class ConfigDrivenFeatureEntry extends ConfigBase { - - public final String id; - public TagKey biomeTag; - - private NonNullSupplier block; - private NonNullSupplier deepblock; - private NonNullSupplier netherblock; - - private List> layers = new ArrayList<>(); - - protected ConfigInt clusterSize; - protected ConfigInt minHeight; - protected ConfigInt maxHeight; - protected ConfigFloat frequency; - - Function> factory; - Holder> configuredFeature; - Holder placedFeature; - - public ConfigDrivenFeatureEntry(String id, int clusterSize, float frequency) { - this.id = id; - this.factory = this::standardFactory; - this.clusterSize = i(clusterSize, 0, "clusterSize"); - this.minHeight = i(0, 0, "minHeight"); - this.maxHeight = i(256, 0, "maxHeight"); - this.frequency = f(frequency, 0, 512, "frequency", "Amount of clusters generated per Chunk.", - " >1 to spawn multiple.", " <1 to make it a chance.", " 0 to disable."); - } - - public ConfigDrivenFeatureEntry withLayerPattern(NonNullSupplier pattern) { - this.layers.add(pattern); - this.factory = this::layersFactory; - return this; - } - - public ConfigDrivenFeatureEntry withBlock(NonNullSupplier block) { - this.block = this.deepblock = block; - return this; - } - - public ConfigDrivenFeatureEntry withNetherBlock(NonNullSupplier block) { - this.netherblock = block; - return this; - } - - public ConfigDrivenFeatureEntry withBlocks(Couple> blocks) { - this.block = blocks.getFirst(); - this.deepblock = blocks.getSecond(); - return this; - } - - public ConfigDrivenFeatureEntry between(int minHeight, int maxHeight) { - allValues.remove(this.minHeight); - allValues.remove(this.maxHeight); - this.minHeight = i(minHeight, -64, "minHeight"); - this.maxHeight = i(maxHeight, -64, "maxHeight"); - return this; - } - - private ConfiguredFeature layersFactory(ConfigDrivenFeatureEntry entry) { - ConfigDrivenOreConfiguration config = new ConfigDrivenOreConfiguration(ImmutableList.of(), 0, id); - LayeredOreFeature.LAYER_PATTERNS.put(Create.asResource(id), layers.stream() - .map(NonNullSupplier::get) - .toList()); - return new ConfiguredFeature<>(LayeredOreFeature.INSTANCE, config); - } - - private ConfiguredFeature standardFactory(ConfigDrivenFeatureEntry entry) { - ConfigDrivenOreConfiguration config = new ConfigDrivenOreConfiguration(createTarget(), 0, id); - return new ConfiguredFeature<>(VanillaStyleOreFeature.INSTANCE, config); - } - - private List createTarget() { - List list = new ArrayList<>(); - if (block != null) - list.add(OreConfiguration.target(OreFeatures.STONE_ORE_REPLACEABLES, block.get() - .defaultBlockState())); - if (deepblock != null) - list.add(OreConfiguration.target(OreFeatures.DEEPSLATE_ORE_REPLACEABLES, deepblock.get() - .defaultBlockState())); - if (netherblock != null) - list.add(OreConfiguration.target(OreFeatures.NETHER_ORE_REPLACEABLES, netherblock.get() - .defaultBlockState())); - return list; - } - - public void addToConfig(ForgeConfigSpec.Builder builder) { - registerAll(builder); - } - - @Override - public String getName() { - return id; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenLayeredOreFeatureConfiguration.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenLayeredOreFeatureConfiguration.java new file mode 100644 index 000000000..4066b20b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenLayeredOreFeatureConfiguration.java @@ -0,0 +1,33 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.List; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +public class ConfigDrivenLayeredOreFeatureConfiguration extends BaseConfigDrivenOreFeatureConfiguration { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> { + return instance.group( + OreFeatureConfigEntry.CODEC + .fieldOf("entry") + .forGetter(config -> config.entry), + Codec.floatRange(0.0F, 1.0F) + .fieldOf("discard_chance_on_air_exposure") + .forGetter(config -> config.discardChanceOnAirExposure), + Codec.list(LayerPattern.CODEC) + .fieldOf("layer_patterns") + .forGetter(config -> config.layerPatterns) + ).apply(instance, ConfigDrivenLayeredOreFeatureConfiguration::new); + }); + + private final List layerPatterns; + + public ConfigDrivenLayeredOreFeatureConfiguration(OreFeatureConfigEntry entry, float discardChance, List layerPatterns) { + super(entry, discardChance); + this.layerPatterns = layerPatterns; + } + + public List getLayerPatterns() { + return layerPatterns; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreConfiguration.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreConfiguration.java deleted file mode 100644 index 7c567861f..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreConfiguration.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.List; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.AllConfigs; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration; -import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState; - -public class ConfigDrivenOreConfiguration implements FeatureConfiguration { - - public static final Codec CODEC = RecordCodecBuilder.create((p_67849_) -> { - return p_67849_.group(Codec.list(TargetBlockState.CODEC) - .fieldOf("targets") - .forGetter((p_161027_) -> { - return p_161027_.targetStates; - }), Codec.floatRange(0.0F, 1.0F) - .fieldOf("discard_chance_on_air_exposure") - .forGetter((p_161020_) -> { - return p_161020_.discardChanceOnAirExposure; - }), - Codec.STRING.fieldOf("key") - .forGetter(t -> t.key.getPath())) - .apply(p_67849_, ConfigDrivenOreConfiguration::new); - }); - - public final List targetStates; - public final float discardChanceOnAirExposure; - public final ResourceLocation key; - - public ConfigDrivenOreConfiguration(List targetStates, float discardChance, String key) { - this.targetStates = targetStates; - this.discardChanceOnAirExposure = discardChance; - this.key = Create.asResource(key); - } - - public int getSize() { - return entry().clusterSize.get(); - } - - public int getMinY() { - return entry().minHeight.get(); - } - - public int getMaxY() { - return entry().maxHeight.get(); - } - - public List getLayers() { - return LayeredOreFeature.LAYER_PATTERNS.get(key); - } - - public float getFrequency() { - if (AllConfigs.COMMON.worldGen.disable.get()) - return 0; - return entry().frequency.getF(); - } - - protected ConfigDrivenFeatureEntry entry() { - return AllWorldFeatures.ENTRIES.get(key); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeatureConfiguration.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeatureConfiguration.java new file mode 100644 index 000000000..d554cc139 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenOreFeatureConfiguration.java @@ -0,0 +1,35 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.List; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState; + +public class ConfigDrivenOreFeatureConfiguration extends BaseConfigDrivenOreFeatureConfiguration { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> { + return instance.group( + OreFeatureConfigEntry.CODEC + .fieldOf("entry") + .forGetter(config -> config.entry), + Codec.floatRange(0.0F, 1.0F) + .fieldOf("discard_chance_on_air_exposure") + .forGetter(config -> config.discardChanceOnAirExposure), + Codec.list(TargetBlockState.CODEC) + .fieldOf("targets") + .forGetter(config -> config.targetStates) + ).apply(instance, ConfigDrivenOreFeatureConfiguration::new); + }); + + private final List targetStates; + + public ConfigDrivenOreFeatureConfiguration(OreFeatureConfigEntry entry, float discardChance, List targetStates) { + super(entry, discardChance); + this.targetStates = targetStates; + } + + public List getTargetStates() { + return targetStates; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenPlacement.java b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenPlacement.java new file mode 100644 index 000000000..11d9651a5 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/ConfigDrivenPlacement.java @@ -0,0 +1,79 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import com.simibubi.create.foundation.config.AllConfigs; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.placement.PlacementContext; +import net.minecraft.world.level.levelgen.placement.PlacementModifier; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; + +public class ConfigDrivenPlacement extends PlacementModifier { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> { + return instance.group( + OreFeatureConfigEntry.CODEC + .fieldOf("entry") + .forGetter(ConfigDrivenPlacement::getEntry) + ).apply(instance, ConfigDrivenPlacement::new); + }); + + private final OreFeatureConfigEntry entry; + + public ConfigDrivenPlacement(OreFeatureConfigEntry entry) { + this.entry = entry; + } + + @Override + public Stream getPositions(PlacementContext context, RandomSource random, BlockPos pos) { + int count = getCount(getFrequency(), random); + if (count == 0) { + return Stream.empty(); + } + + int minY = getMinY(); + int maxY = getMaxY(); + + return IntStream.range(0, count) + .mapToObj(i -> pos) + .map(p -> { + int x = random.nextInt(16) + p.getX(); + int z = random.nextInt(16) + p.getZ(); + int y = Mth.randomBetweenInclusive(random, minY, maxY); + return new BlockPos(x, y, z); + }); + } + + public int getCount(float frequency, RandomSource random) { + int floored = Mth.floor(frequency); + return floored + (random.nextFloat() < (frequency - floored) ? 1 : 0); + } + + @Override + public PlacementModifierType type() { + return AllPlacementModifiers.CONFIG_DRIVEN.get(); + } + + public OreFeatureConfigEntry getEntry() { + return entry; + } + + public float getFrequency() { + if (AllConfigs.COMMON.worldGen.disable.get()) + return 0; + return entry.frequency.getF(); + } + + public int getMinY() { + return entry.minHeight.get(); + } + + public int getMaxY() { + return entry.maxHeight.get(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/LayerPattern.java b/src/main/java/com/simibubi/create/foundation/worldgen/LayerPattern.java index 6b0722d2d..a346ee5cd 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/LayerPattern.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/LayerPattern.java @@ -6,8 +6,9 @@ import java.util.List; import javax.annotation.Nullable; import com.google.common.collect.ImmutableList; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.worldgen.LayerPattern.Layer.LayerBuilder; import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.data.worldgen.features.OreFeatures; @@ -20,16 +21,13 @@ import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguratio import net.minecraftforge.common.util.NonNullConsumer; public class LayerPattern { + public static final Codec CODEC = Codec.list(Layer.CODEC) + .xmap(LayerPattern::new, pattern -> pattern.layers); - List layers; + public final List layers; - public LayerPattern() { - layers = new ArrayList<>(); - } - - public static Builder builder() { - LayerPattern ore = new LayerPattern(); - return ore.new Builder(); + public LayerPattern(List layers) { + this.layers = layers; } public Layer rollNext(@Nullable Layer previous, RandomSource random) { @@ -49,42 +47,60 @@ public class LayerPattern { return null; } - class Builder { - + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private final List layers = new ArrayList<>(); private boolean netherMode; - public LayerPattern build() { - return LayerPattern.this; - } - public Builder inNether() { netherMode = true; return this; } - public Builder layer(NonNullConsumer builder) { - Layer layer = new Layer(); - LayerBuilder layerBuilder = layer.new LayerBuilder(); + public Builder layer(NonNullConsumer builder) { + Layer.Builder layerBuilder = new Layer.Builder(); layerBuilder.netherMode = netherMode; builder.accept(layerBuilder); layers.add(layerBuilder.build()); return this; } + public LayerPattern build() { + return new LayerPattern(layers); + } } - static class Layer { + public static class Layer { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> { + return instance.group( + Codec.list(Codec.list(TargetBlockState.CODEC)) + .fieldOf("targets") + .forGetter(layer -> layer.targets), + Codec.intRange(0, Integer.MAX_VALUE) + .fieldOf("min_size") + .forGetter(layer -> layer.minSize), + Codec.intRange(0, Integer.MAX_VALUE) + .fieldOf("max_size") + .forGetter(layer -> layer.maxSize), + Codec.intRange(0, Integer.MAX_VALUE) + .fieldOf("weight") + .forGetter(layer -> layer.weight) + ).apply(instance, Layer::new); + }); - public List> targets; - public int minSize; - public int maxSize; - public int weight; + public final List> targets; + public final int minSize; + public final int maxSize; + public final int weight; - public Layer() { - this.targets = new ArrayList<>(); - this.minSize = 1; - this.maxSize = 1; - this.weight = 1; + public Layer(List> targets, int minSize, int maxSize, int weight) { + this.targets = targets; + this.minSize = minSize; + this.maxSize = maxSize; + this.weight = weight; } public List rollBlock(RandomSource random) { @@ -93,36 +109,35 @@ public class LayerPattern { return targets.get(random.nextInt(targets.size())); } - class LayerBuilder { - + public static class Builder { + private final List> targets = new ArrayList<>(); + private int minSize = 1; + private int maxSize = 1; + private int weight = 1; private boolean netherMode; - private Layer build() { - return Layer.this; - } - - public LayerBuilder block(NonNullSupplier block) { + public Builder block(NonNullSupplier block) { return block(block.get()); } - public LayerBuilder passiveBlock() { + public Builder passiveBlock() { return blocks(Blocks.STONE.defaultBlockState(), Blocks.DEEPSLATE.defaultBlockState()); } - public LayerBuilder block(Block block) { + public Builder block(Block block) { if (netherMode) { - Layer.this.targets.add(ImmutableList.of(OreConfiguration + this.targets.add(ImmutableList.of(OreConfiguration .target(OreFeatures.NETHER_ORE_REPLACEABLES, block.defaultBlockState()))); return this; } return blocks(block.defaultBlockState(), block.defaultBlockState()); } - public LayerBuilder blocks(Block block, Block deepblock) { + public Builder blocks(Block block, Block deepblock) { return blocks(block.defaultBlockState(), deepblock.defaultBlockState()); } - public LayerBuilder blocks(Couple> blocksByDepth) { + public Builder blocks(Couple> blocksByDepth) { return blocks(blocksByDepth.getFirst() .get() .defaultBlockState(), @@ -131,26 +146,27 @@ public class LayerPattern { .defaultBlockState()); } - private LayerBuilder blocks(BlockState stone, BlockState deepslate) { - Layer.this.targets.add( + private Builder blocks(BlockState stone, BlockState deepslate) { + this.targets.add( ImmutableList.of(OreConfiguration.target(OreFeatures.STONE_ORE_REPLACEABLES, stone), OreConfiguration.target(OreFeatures.DEEPSLATE_ORE_REPLACEABLES, deepslate))); return this; } - public LayerBuilder weight(int weight) { - Layer.this.weight = weight; + public Builder weight(int weight) { + this.weight = weight; return this; } - public LayerBuilder size(int min, int max) { - Layer.this.minSize = min; - Layer.this.maxSize = max; + public Builder size(int min, int max) { + this.minSize = min; + this.maxSize = max; return this; } + public Layer build() { + return new Layer(targets, minSize, maxSize, weight); + } } - } - } diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/LayeredOreFeature.java b/src/main/java/com/simibubi/create/foundation/worldgen/LayeredOreFeature.java index a1b994614..19e3f7545 100644 --- a/src/main/java/com/simibubi/create/foundation/worldgen/LayeredOreFeature.java +++ b/src/main/java/com/simibubi/create/foundation/worldgen/LayeredOreFeature.java @@ -1,16 +1,13 @@ package com.simibubi.create.foundation.worldgen; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import com.simibubi.create.foundation.worldgen.LayerPattern.Layer; import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos.MutableBlockPos; import net.minecraft.core.SectionPos; -import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.WorldGenLevel; @@ -22,19 +19,18 @@ import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState; -public class LayeredOreFeature extends OreFeatureBase { - - public static final Map> LAYER_PATTERNS = new HashMap<>(); - - public static final LayeredOreFeature INSTANCE = new LayeredOreFeature(); - - public boolean place(FeaturePlaceContext pContext) { +public class LayeredOreFeature extends BaseConfigDrivenOreFeature { + public LayeredOreFeature() { + super(ConfigDrivenLayeredOreFeatureConfiguration.CODEC); + } + @Override + public boolean place(FeaturePlaceContext pContext) { RandomSource random = pContext.random(); BlockPos blockpos = pContext.origin(); WorldGenLevel worldgenlevel = pContext.level(); - ConfigDrivenOreConfiguration config = pContext.config(); - List patternPool = config.getLayers(); + ConfigDrivenLayeredOreFeatureConfiguration config = pContext.config(); + List patternPool = config.getLayerPatterns(); if (patternPool.isEmpty()) return false; @@ -42,8 +38,8 @@ public class LayeredOreFeature extends OreFeatureBase { LayerPattern layerPattern = patternPool.get(random.nextInt(patternPool.size())); int placedAmount = 0; - int size = config.getSize(); - int radius = Mth.ceil(config.getSize() / 2f); + int size = config.getClusterSize(); + int radius = Mth.ceil(config.getClusterSize() / 2f); int x0 = blockpos.getX() - radius; int y0 = blockpos.getY() - radius; int z0 = blockpos.getZ() - radius; @@ -146,5 +142,4 @@ public class LayeredOreFeature extends OreFeatureBase { bulksectionaccess.close(); return placedAmount > 0; } - } diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureConfigEntry.java b/src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureConfigEntry.java new file mode 100644 index 000000000..cc3563ba1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/OreFeatureConfigEntry.java @@ -0,0 +1,234 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.jetbrains.annotations.Nullable; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.simibubi.create.foundation.config.ConfigBase; +import com.simibubi.create.foundation.utility.Couple; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.core.Holder; +import net.minecraft.core.HolderSet; +import net.minecraft.core.Registry; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.data.worldgen.features.OreFeatures; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.tags.TagKey; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.levelgen.GenerationStep.Decoration; +import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration.TargetBlockState; +import net.minecraft.world.level.levelgen.placement.PlacedFeature; +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.common.world.BiomeModifier; +import net.minecraftforge.common.world.ForgeBiomeModifiers.AddFeaturesBiomeModifier; + +public class OreFeatureConfigEntry extends ConfigBase { + public static final Map ALL = new HashMap<>(); + + public static final Codec CODEC = ResourceLocation.CODEC + .comapFlatMap(OreFeatureConfigEntry::read, entry -> entry.id); + + public final ResourceLocation id; + public final ConfigInt clusterSize; + public final ConfigFloat frequency; + public final ConfigInt minHeight; + public final ConfigInt maxHeight; + + private DatagenExtension datagenExt; + + public OreFeatureConfigEntry(ResourceLocation id, int clusterSize, float frequency, int minHeight, int maxHeight) { + this.id = id; + + this.clusterSize = i(clusterSize, 0, "clusterSize"); + this.frequency = f(frequency, 0, 512, "frequency", "Amount of clusters generated per Chunk.", + " >1 to spawn multiple.", " <1 to make it a chance.", " 0 to disable."); + this.minHeight = i(minHeight, "minHeight"); + this.maxHeight = i(maxHeight, "maxHeight"); + + ALL.put(id, this); + } + + @Nullable + public StandardDatagenExtension standardDatagenExt() { + if (datagenExt == null) { + datagenExt = new StandardDatagenExtension(); + } + if (datagenExt instanceof StandardDatagenExtension standard) { + return standard; + } + return null; + } + + @Nullable + public LayeredDatagenExtension layeredDatagenExt() { + if (datagenExt == null) { + datagenExt = new LayeredDatagenExtension(); + } + if (datagenExt instanceof LayeredDatagenExtension layered) { + return layered; + } + return null; + } + + @Nullable + public DatagenExtension datagenExt() { + if (datagenExt != null) { + return datagenExt; + } + return null; + } + + public void addToConfig(ForgeConfigSpec.Builder builder) { + registerAll(builder); + } + + @Override + public String getName() { + return id.getPath(); + } + + public static DataResult read(ResourceLocation id) { + OreFeatureConfigEntry entry = ALL.get(id); + if (entry != null) { + return DataResult.success(entry); + } else { + return DataResult.error("Not a valid OreFeatureConfigEntry: " + id); + } + } + + public abstract class DatagenExtension { + public TagKey biomeTag; + + protected ConfiguredFeature configuredFeature; + protected PlacedFeature placedFeature; + protected BiomeModifier biomeModifier; + + public DatagenExtension biomeTag(TagKey biomes) { + this.biomeTag = biomes; + return this; + } + + public abstract ConfiguredFeature getConfiguredFeature(); + + public PlacedFeature getPlacedFeature() { + if (placedFeature != null) { + return placedFeature; + } + + Holder> featureHolder = BuiltinRegistries.CONFIGURED_FEATURE.getOrCreateHolderOrThrow(ResourceKey.create(Registry.CONFIGURED_FEATURE_REGISTRY, id)); + placedFeature = new PlacedFeature(featureHolder, List.of(new ConfigDrivenPlacement(OreFeatureConfigEntry.this))); + + return placedFeature; + } + + public BiomeModifier getBiomeModifier() { + if (biomeModifier != null) { + return biomeModifier; + } + + @SuppressWarnings("deprecation") + HolderSet biomes = new HolderSet.Named<>(BuiltinRegistries.BIOME, biomeTag); + Holder featureHolder = BuiltinRegistries.PLACED_FEATURE.getOrCreateHolderOrThrow(ResourceKey.create(Registry.PLACED_FEATURE_REGISTRY, id)); + biomeModifier = new AddFeaturesBiomeModifier(biomes, HolderSet.direct(featureHolder), Decoration.UNDERGROUND_ORES); + + return biomeModifier; + } + + public OreFeatureConfigEntry parent() { + return OreFeatureConfigEntry.this; + } + } + + public class StandardDatagenExtension extends DatagenExtension { + public NonNullSupplier block; + public NonNullSupplier deepBlock; + public NonNullSupplier netherBlock; + + public StandardDatagenExtension withBlock(NonNullSupplier block) { + this.block = block; + this.deepBlock = block; + return this; + } + + public StandardDatagenExtension withBlocks(Couple> blocks) { + this.block = blocks.getFirst(); + this.deepBlock = blocks.getSecond(); + return this; + } + + public StandardDatagenExtension withNetherBlock(NonNullSupplier block) { + this.netherBlock = block; + return this; + } + + @Override + public StandardDatagenExtension biomeTag(TagKey biomes) { + super.biomeTag(biomes); + return this; + } + + @Override + public ConfiguredFeature getConfiguredFeature() { + if (configuredFeature != null) { + return configuredFeature; + } + + List targetStates = new ArrayList<>(); + if (block != null) + targetStates.add(OreConfiguration.target(OreFeatures.STONE_ORE_REPLACEABLES, block.get() + .defaultBlockState())); + if (deepBlock != null) + targetStates.add(OreConfiguration.target(OreFeatures.DEEPSLATE_ORE_REPLACEABLES, deepBlock.get() + .defaultBlockState())); + if (netherBlock != null) + targetStates.add(OreConfiguration.target(OreFeatures.NETHER_ORE_REPLACEABLES, netherBlock.get() + .defaultBlockState())); + + ConfigDrivenOreFeatureConfiguration config = new ConfigDrivenOreFeatureConfiguration(OreFeatureConfigEntry.this, 0, targetStates); + configuredFeature = new ConfiguredFeature<>(AllFeatures.STANDARD_ORE.get(), config); + + return configuredFeature; + } + } + + public class LayeredDatagenExtension extends DatagenExtension { + public final List> layerPatterns = new ArrayList<>(); + + public LayeredDatagenExtension withLayerPattern(NonNullSupplier pattern) { + this.layerPatterns.add(pattern); + return this; + } + + @Override + public LayeredDatagenExtension biomeTag(TagKey biomes) { + super.biomeTag(biomes); + return this; + } + + @Override + public ConfiguredFeature getConfiguredFeature() { + if (configuredFeature != null) { + return configuredFeature; + } + + List layerPatterns = this.layerPatterns.stream() + .map(NonNullSupplier::get) + .toList(); + + ConfigDrivenLayeredOreFeatureConfiguration config = new ConfigDrivenLayeredOreFeatureConfiguration(OreFeatureConfigEntry.this, 0, layerPatterns); + configuredFeature = new ConfiguredFeature<>(AllFeatures.LAYERED_ORE.get(), config); + + return configuredFeature; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/StandardOreFeature.java b/src/main/java/com/simibubi/create/foundation/worldgen/StandardOreFeature.java new file mode 100644 index 000000000..ea27c6b91 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/worldgen/StandardOreFeature.java @@ -0,0 +1,168 @@ +package com.simibubi.create.foundation.worldgen; + +import java.util.BitSet; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.WorldGenLevel; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.BulkSectionAccess; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.levelgen.Heightmap; +import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; +import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; + +public class StandardOreFeature extends BaseConfigDrivenOreFeature { + + public StandardOreFeature() { + super(ConfigDrivenOreFeatureConfiguration.CODEC); + } + + // From OreFeature, slight adjustments + + @Override + public boolean place(FeaturePlaceContext pContext) { + RandomSource random = pContext.random(); + BlockPos blockpos = pContext.origin(); + WorldGenLevel worldgenlevel = pContext.level(); + ConfigDrivenOreFeatureConfiguration oreconfiguration = pContext.config(); + float f = random.nextFloat() * (float)Math.PI; + float f1 = (float)oreconfiguration.getClusterSize() / 8.0F; + int i = Mth.ceil(((float)oreconfiguration.getClusterSize() / 16.0F * 2.0F + 1.0F) / 2.0F); + double d0 = (double)blockpos.getX() + Math.sin((double)f) * (double)f1; + double d1 = (double)blockpos.getX() - Math.sin((double)f) * (double)f1; + double d2 = (double)blockpos.getZ() + Math.cos((double)f) * (double)f1; + double d3 = (double)blockpos.getZ() - Math.cos((double)f) * (double)f1; + double d4 = (double)(blockpos.getY() + random.nextInt(3) - 2); + double d5 = (double)(blockpos.getY() + random.nextInt(3) - 2); + int k = blockpos.getX() - Mth.ceil(f1) - i; + int l = blockpos.getY() - 2 - i; + int i1 = blockpos.getZ() - Mth.ceil(f1) - i; + int j1 = 2 * (Mth.ceil(f1) + i); + int k1 = 2 * (2 + i); + + for(int l1 = k; l1 <= k + j1; ++l1) { + for(int i2 = i1; i2 <= i1 + j1; ++i2) { + if (l <= worldgenlevel.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, l1, i2)) { + return this.doPlace(worldgenlevel, random, oreconfiguration, d0, d1, d2, d3, d4, d5, k, l, i1, j1, k1); + } + } + } + + return false; + } + + protected boolean doPlace(WorldGenLevel pLevel, RandomSource pRandom, ConfigDrivenOreFeatureConfiguration pConfig, double pMinX, + double pMaxX, double pMinZ, double pMaxZ, double pMinY, double pMaxY, int pX, int pY, int pZ, int pWidth, + int pHeight) { + int i = 0; + BitSet bitset = new BitSet(pWidth * pHeight * pWidth); + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); + int j = pConfig.getClusterSize(); + double[] adouble = new double[j * 4]; + + for(int k = 0; k < j; ++k) { + float f = (float)k / (float)j; + double d0 = Mth.lerp((double)f, pMinX, pMaxX); + double d1 = Mth.lerp((double)f, pMinY, pMaxY); + double d2 = Mth.lerp((double)f, pMinZ, pMaxZ); + double d3 = pRandom.nextDouble() * (double)j / 16.0D; + double d4 = ((double)(Mth.sin((float)Math.PI * f) + 1.0F) * d3 + 1.0D) / 2.0D; + adouble[k * 4 + 0] = d0; + adouble[k * 4 + 1] = d1; + adouble[k * 4 + 2] = d2; + adouble[k * 4 + 3] = d4; + } + + for(int l3 = 0; l3 < j - 1; ++l3) { + if (!(adouble[l3 * 4 + 3] <= 0.0D)) { + for(int i4 = l3 + 1; i4 < j; ++i4) { + if (!(adouble[i4 * 4 + 3] <= 0.0D)) { + double d8 = adouble[l3 * 4 + 0] - adouble[i4 * 4 + 0]; + double d10 = adouble[l3 * 4 + 1] - adouble[i4 * 4 + 1]; + double d12 = adouble[l3 * 4 + 2] - adouble[i4 * 4 + 2]; + double d14 = adouble[l3 * 4 + 3] - adouble[i4 * 4 + 3]; + if (d14 * d14 > d8 * d8 + d10 * d10 + d12 * d12) { + if (d14 > 0.0D) { + adouble[i4 * 4 + 3] = -1.0D; + } else { + adouble[l3 * 4 + 3] = -1.0D; + } + } + } + } + } + } + + BulkSectionAccess bulksectionaccess = new BulkSectionAccess(pLevel); + + try { + for(int j4 = 0; j4 < j; ++j4) { + double d9 = adouble[j4 * 4 + 3]; + if (!(d9 < 0.0D)) { + double d11 = adouble[j4 * 4 + 0]; + double d13 = adouble[j4 * 4 + 1]; + double d15 = adouble[j4 * 4 + 2]; + int k4 = Math.max(Mth.floor(d11 - d9), pX); + int l = Math.max(Mth.floor(d13 - d9), pY); + int i1 = Math.max(Mth.floor(d15 - d9), pZ); + int j1 = Math.max(Mth.floor(d11 + d9), k4); + int k1 = Math.max(Mth.floor(d13 + d9), l); + int l1 = Math.max(Mth.floor(d15 + d9), i1); + + for(int i2 = k4; i2 <= j1; ++i2) { + double d5 = ((double)i2 + 0.5D - d11) / d9; + if (d5 * d5 < 1.0D) { + for(int j2 = l; j2 <= k1; ++j2) { + double d6 = ((double)j2 + 0.5D - d13) / d9; + if (d5 * d5 + d6 * d6 < 1.0D) { + for(int k2 = i1; k2 <= l1; ++k2) { + double d7 = ((double)k2 + 0.5D - d15) / d9; + if (d5 * d5 + d6 * d6 + d7 * d7 < 1.0D && !pLevel.isOutsideBuildHeight(j2)) { + int l2 = i2 - pX + (j2 - pY) * pWidth + (k2 - pZ) * pWidth * pHeight; + if (!bitset.get(l2)) { + bitset.set(l2); + blockpos$mutableblockpos.set(i2, j2, k2); + if (pLevel.ensureCanWrite(blockpos$mutableblockpos)) { + LevelChunkSection levelchunksection = bulksectionaccess.getSection(blockpos$mutableblockpos); + if (levelchunksection != null) { + int i3 = SectionPos.sectionRelative(i2); + int j3 = SectionPos.sectionRelative(j2); + int k3 = SectionPos.sectionRelative(k2); + BlockState blockstate = levelchunksection.getBlockState(i3, j3, k3); + + for(OreConfiguration.TargetBlockState oreconfiguration$targetblockstate : pConfig.getTargetStates()) { + if (canPlaceOre(blockstate, bulksectionaccess::getBlockState, pRandom, pConfig, oreconfiguration$targetblockstate, blockpos$mutableblockpos)) { + levelchunksection.setBlockState(i3, j3, k3, oreconfiguration$targetblockstate.state, false); + ++i; + break; + } + } + } + } + } + } + } + } + } + } + } + } + } + } catch (Throwable throwable1) { + try { + bulksectionaccess.close(); + } catch (Throwable throwable) { + throwable1.addSuppressed(throwable); + } + + throw throwable1; + } + + bulksectionaccess.close(); + return i > 0; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/worldgen/VanillaStyleOreFeature.java b/src/main/java/com/simibubi/create/foundation/worldgen/VanillaStyleOreFeature.java deleted file mode 100644 index 66a059375..000000000 --- a/src/main/java/com/simibubi/create/foundation/worldgen/VanillaStyleOreFeature.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.simibubi.create.foundation.worldgen; - -import java.util.BitSet; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.SectionPos; -import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; -import net.minecraft.world.level.WorldGenLevel; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.chunk.BulkSectionAccess; -import net.minecraft.world.level.chunk.LevelChunkSection; -import net.minecraft.world.level.levelgen.Heightmap; -import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext; -import net.minecraft.world.level.levelgen.feature.configurations.OreConfiguration; - -public class VanillaStyleOreFeature extends OreFeatureBase { - - public static final VanillaStyleOreFeature INSTANCE = new VanillaStyleOreFeature(); - - // From OreFeature, slight adjustments - - public boolean place(FeaturePlaceContext pContext) { - - RandomSource random = pContext.random(); - BlockPos blockpos = pContext.origin(); - WorldGenLevel worldgenlevel = pContext.level(); - ConfigDrivenOreConfiguration oreconfiguration = pContext.config(); - - float f = random.nextFloat() * (float) Math.PI; - float diameter = (float) oreconfiguration.getSize() / 8.0F; - int centeringOffset = Mth.ceil(((float) oreconfiguration.getSize() / 8.0F + 1.0F) / 2.0F); - double d0 = blockpos.getX() + Math.sin(f) * diameter; - double d1 = blockpos.getX() - Math.sin(f) * diameter; - double d2 = blockpos.getZ() + Math.cos(f) * diameter; - double d3 = blockpos.getZ() - Math.cos(f) * diameter; - double d4 = (blockpos.getY() + random.nextInt(3) - 2); - double d5 = (blockpos.getY() + random.nextInt(3) - 2); - int k = blockpos.getX() - Mth.ceil(diameter) - centeringOffset; - int l = blockpos.getY() - 2 - centeringOffset; - int i1 = blockpos.getZ() - Mth.ceil(diameter) - centeringOffset; - int j1 = 2 * (Mth.ceil(diameter) + centeringOffset); - int k1 = 2 * (2 + centeringOffset); - - for (int x = k; x <= k + j1; ++x) - for (int z = i1; z <= i1 + j1; ++z) - if (l <= worldgenlevel.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, x, z)) - return this.doPlace(worldgenlevel, random, oreconfiguration, d0, d1, d2, d3, d4, d5, k, l, i1, j1, - k1); - - return false; - } - - protected boolean doPlace(WorldGenLevel pLevel, RandomSource pRandom, ConfigDrivenOreConfiguration pConfig, double pMinX, - double pMaxX, double pMinZ, double pMaxZ, double pMinY, double pMaxY, int pX, int pY, int pZ, int pWidth, - int pHeight) { - int i = 0; - BitSet bitset = new BitSet(pWidth * pHeight * pWidth); - BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); - int j = pConfig.getSize(); - double[] adouble = new double[j * 4]; - - for (int k = 0; k < j; ++k) { - float f = (float) k / (float) j; - double d0 = Mth.lerp(f, pMinX, pMaxX); - double d1 = Mth.lerp(f, pMinY, pMaxY); - double d2 = Mth.lerp(f, pMinZ, pMaxZ); - double d3 = pRandom.nextDouble() * j / 16.0D; - double d4 = ((Mth.sin((float) Math.PI * f) + 1.0F) * d3 + 1.0D) / 2.0D; - adouble[k * 4 + 0] = d0; - adouble[k * 4 + 1] = d1; - adouble[k * 4 + 2] = d2; - adouble[k * 4 + 3] = d4; - } - - for (int l3 = 0; l3 < j - 1; ++l3) { - if (adouble[l3 * 4 + 3] <= 0.0D) - continue; - for (int i4 = l3 + 1; i4 < j; ++i4) { - if (adouble[i4 * 4 + 3] <= 0.0D) - continue; - - double d8 = adouble[l3 * 4 + 0] - adouble[i4 * 4 + 0]; - double d10 = adouble[l3 * 4 + 1] - adouble[i4 * 4 + 1]; - double d12 = adouble[l3 * 4 + 2] - adouble[i4 * 4 + 2]; - double d14 = adouble[l3 * 4 + 3] - adouble[i4 * 4 + 3]; - if (d14 * d14 <= d8 * d8 + d10 * d10 + d12 * d12) - continue; - - if (d14 > 0.0D) - adouble[i4 * 4 + 3] = -1.0D; - else - adouble[l3 * 4 + 3] = -1.0D; - } - } - - BulkSectionAccess bulksectionaccess = new BulkSectionAccess(pLevel); - - try { - for (int j4 = 0; j4 < j; ++j4) { - double d9 = adouble[j4 * 4 + 3]; - if (d9 < 0.0D) - continue; - - double d11 = adouble[j4 * 4 + 0]; - double d13 = adouble[j4 * 4 + 1]; - double d15 = adouble[j4 * 4 + 2]; - int k4 = Math.max(Mth.floor(d11 - d9), pX); - int l = Math.max(Mth.floor(d13 - d9), pY); - int i1 = Math.max(Mth.floor(d15 - d9), pZ); - int j1 = Math.max(Mth.floor(d11 + d9), k4); - int k1 = Math.max(Mth.floor(d13 + d9), l); - int l1 = Math.max(Mth.floor(d15 + d9), i1); - - for (int i2 = k4; i2 <= j1; ++i2) { - double d5 = (i2 + 0.5D - d11) / d9; - if (d5 * d5 >= 1.0D) - continue; - for (int j2 = l; j2 <= k1; ++j2) { - double d6 = (j2 + 0.5D - d13) / d9; - if (d5 * d5 + d6 * d6 >= 1.0D) - continue; - for (int k2 = i1; k2 <= l1; ++k2) { - double d7 = (k2 + 0.5D - d15) / d9; - if (d5 * d5 + d6 * d6 + d7 * d7 >= 1.0D || pLevel.isOutsideBuildHeight(j2)) - continue; - - int l2 = i2 - pX + (j2 - pY) * pWidth + (k2 - pZ) * pWidth * pHeight; - if (bitset.get(l2)) - continue; - bitset.set(l2); - blockpos$mutableblockpos.set(i2, j2, k2); - if (!pLevel.ensureCanWrite(blockpos$mutableblockpos)) - continue; - LevelChunkSection levelchunksection = - bulksectionaccess.getSection(blockpos$mutableblockpos); - if (levelchunksection == null) - continue; - int i3 = SectionPos.sectionRelative(i2); - int j3 = SectionPos.sectionRelative(j2); - int k3 = SectionPos.sectionRelative(k2); - BlockState blockstate = levelchunksection.getBlockState(i3, j3, k3); - - for (OreConfiguration.TargetBlockState oreconfiguration$targetblockstate : pConfig.targetStates) { - if (!canPlaceOre(blockstate, bulksectionaccess::getBlockState, pRandom, pConfig, - oreconfiguration$targetblockstate, blockpos$mutableblockpos)) - continue; - levelchunksection.setBlockState(i3, j3, k3, oreconfiguration$targetblockstate.state, - false); - ++i; - break; - } - } - } - } - } - - } catch (Throwable throwable1) { - try { - bulksectionaccess.close(); - } catch (Throwable throwable) { - throwable1.addSuppressed(throwable); - } - - throw throwable1; - } - - bulksectionaccess.close(); - return i > 0; - } - -}