Defer registration, datagen worldgen

- Use DeferredRegister/RegistryObject where possible
- Refactor worldgen code to be cleaner and support datagen
- Fix zinc ore only generating on chunk corners
- Remove fan_heaters block tag
This commit is contained in:
PepperCode1 2022-08-05 11:39:34 -07:00
parent ded8667ae8
commit 42ffe443ac
39 changed files with 1204 additions and 847 deletions

View file

@ -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

View file

@ -1,11 +0,0 @@
{
"replace": false,
"values": [
"create:blaze_burner",
"create:lit_blaze_burner",
"#minecraft:fire",
"#minecraft:campfires",
"minecraft:magma_block",
"minecraft:lava"
]
}

View file

@ -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"
]
}

View file

@ -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()

View file

@ -2,17 +2,20 @@ package com.simibubi.create;
import com.simibubi.create.content.logistics.trains.entity.CarriageSyncDataSerializer;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DataSerializerEntry;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class AllEntityDataSerializers {
private static final DeferredRegister<DataSerializerEntry> REGISTER = DeferredRegister.create(ForgeRegistries.Keys.DATA_SERIALIZERS, Create.ID);
public static final CarriageSyncDataSerializer CARRIAGE_DATA = new CarriageSyncDataSerializer();
public static void register(RegistryEvent.Register<DataSerializerEntry> event) {
IForgeRegistry<DataSerializerEntry> registry = event.getRegistry();
registry.register(new DataSerializerEntry(CARRIAGE_DATA).setRegistryName(Create.asResource("carriage_data")));
}
public static final RegistryObject<DataSerializerEntry> CARRIAGE_DATA_ENTRY = REGISTER.register("carriage_data", () -> new DataSerializerEntry(CARRIAGE_DATA));
public static void register(IEventBus modEventBus) {
REGISTER.register(modEventBus);
}
}

View file

@ -18,12 +18,13 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.ParticleEngine;
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.ParticleFactoryRegisterEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public enum AllParticleTypes {
@ -39,19 +40,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;
<D extends ParticleOptions> AllParticleTypes(Supplier<? extends ICustomParticleData<D>> 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(RegistryEvent.Register<ParticleType<?>> event) {
for (AllParticleTypes particle : values())
particle.entry.register(event.getRegistry());
public static void register(IEventBus modEventBus) {
ParticleEntry.REGISTER.register(modEventBus);
}
@OnlyIn(Dist.CLIENT)
@ -62,40 +61,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<D extends ParticleOptions> {
Supplier<? extends ICustomParticleData<D>> typeFactory;
ParticleType<D> type;
ResourceLocation id;
private static class ParticleEntry<D extends ParticleOptions> {
private static final DeferredRegister<ParticleType<?>> REGISTER = DeferredRegister.create(ForgeRegistries.PARTICLE_TYPES, Create.ID);
public ParticleEntry(ResourceLocation id, Supplier<? extends ICustomParticleData<D>> typeFactory) {
this.id = id;
private final String name;
private final Supplier<? extends ICustomParticleData<D>> typeFactory;
private final RegistryObject<ParticleType<D>> object;
public ParticleEntry(String name, Supplier<? extends ICustomParticleData<D>> typeFactory) {
this.name = name;
this.typeFactory = typeFactory;
}
void register(IForgeRegistry<ParticleType<?>> registry) {
registry.register(getOrCreateType());
}
ParticleType<D> getOrCreateType() {
if (type != null)
return type;
type = typeFactory.get()
.createType();
type.setRegistryName(id);
return type;
object = REGISTER.register(name, () -> this.typeFactory.get().createType());
}
@OnlyIn(Dist.CLIENT)
void registerFactory(ParticleEngine particles) {
public void registerFactory(ParticleEngine particles) {
typeFactory.get()
.register(getOrCreateType(), particles);
.register(object.get(), particles);
}
}

View file

@ -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.event.RegistryEvent;
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,53 @@ 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<RecipeSerializer<?>> serializerObject;
@Nullable
private final RegistryObject<RecipeType<?>> typeObject;
private final Supplier<RecipeType<?>> type;
private ResourceLocation id;
private Supplier<RecipeSerializer<?>> serializerSupplier;
private Supplier<RecipeType<?>> typeSupplier;
private RecipeSerializer<?> serializer;
private RecipeType<?> type;
AllRecipeTypes(Supplier<RecipeSerializer<?>> serializerSupplier, Supplier<RecipeType<?>> typeSupplier) {
this.id = Create.asResource(Lang.asId(name()));
this.serializerSupplier = serializerSupplier;
this.typeSupplier = typeSupplier;
}
AllRecipeTypes(Supplier<RecipeSerializer<?>> serializerSupplier, RecipeType<?> existingType) {
this(serializerSupplier, () -> existingType);
AllRecipeTypes(Supplier<RecipeSerializer<?>> serializerSupplier, Supplier<RecipeType<?>> 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<RecipeSerializer<?>> serializerSupplier) {
this.id = Create.asResource(Lang.asId(name()));
this.serializerSupplier = serializerSupplier;
this.typeSupplier = () -> simpleType(id);
String name = Lang.asId(name());
id = Create.asResource(name);
serializerObject = Registers.SERIALIZER_REGISTER.register(name, serializerSupplier);
typeObject = Registers.TYPE_REGISTER.register(name, () -> simpleType(id));
type = typeObject;
}
AllRecipeTypes(ProcessingRecipeFactory<?> processingFactory) {
this(processingSerializer(processingFactory));
this(() -> new ProcessingRecipeSerializer<>(processingFactory));
}
public static <T extends Recipe<?>> RecipeType<T> simpleType(ResourceLocation id) {
String stringId = id.toString();
return new RecipeType<T>() {
@Override
public String toString() {
return stringId;
}
};
}
public static void register(IEventBus modEventBus) {
ShapedRecipe.setCraftingSize(9, 9);
Registers.SERIALIZER_REGISTER.register(modEventBus);
Registers.TYPE_REGISTER.register(modEventBus);
}
@Override
@ -99,13 +123,13 @@ public enum AllRecipeTypes implements IRecipeTypeInfo {
@SuppressWarnings("unchecked")
@Override
public <T extends RecipeSerializer<?>> T getSerializer() {
return (T) serializer;
return (T) serializerObject.get();
}
@SuppressWarnings("unchecked")
@Override
public <T extends RecipeType<?>> T getType() {
return (T) type;
return (T) type.get();
}
public <C extends Container, T extends Recipe<C>> Optional<T> find(C inv, Level world) {
@ -113,32 +137,6 @@ public enum AllRecipeTypes implements IRecipeTypeInfo {
.getRecipeFor(getType(), inv, world);
}
public static void register(RegistryEvent.Register<RecipeSerializer<?>> event) {
ShapedRecipe.setCraftingSize(9, 9);
for (AllRecipeTypes r : AllRecipeTypes.values()) {
r.serializer = r.serializerSupplier.get();
r.type = r.typeSupplier.get();
r.serializer.setRegistryName(r.id);
event.getRegistry()
.register(r.serializer);
}
}
private static Supplier<RecipeSerializer<?>> processingSerializer(ProcessingRecipeFactory<?> factory) {
return () -> new ProcessingRecipeSerializer<>(factory);
}
public static <T extends Recipe<?>> RecipeType<T> simpleType(ResourceLocation id) {
String stringId = id.toString();
return Registry.register(Registry.RECIPE_TYPE, id, new RecipeType<T>() {
@Override
public String toString() {
return stringId;
}
});
}
public static final Set<ResourceLocation> RECIPE_DENY_SET =
ImmutableSet.of(new ResourceLocation("occultism", "spirit_trade"), new ResourceLocation("occultism", "ritual"));
@ -151,4 +149,9 @@ public enum AllRecipeTypes implements IRecipeTypeInfo {
.endsWith("_manual_only");
}
private static class Registers {
private static final DeferredRegister<RecipeSerializer<?>> SERIALIZER_REGISTER = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, Create.ID);
private static final DeferredRegister<RecipeType<?>> TYPE_REGISTER = DeferredRegister.create(Registry.RECIPE_TYPE_REGISTRY, Create.ID);
}
}

View file

@ -6,14 +6,12 @@ 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.Gson;
import com.google.gson.GsonBuilder;
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.Vec3i;
import net.minecraft.data.DataGenerator;
@ -28,12 +26,15 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryObject;
//@EventBusSubscriber(bus = Bus.FORGE)
public class AllSoundEvents {
public static final Map<ResourceLocation, SoundEntry> entries = new HashMap<>();
public static final Map<ResourceLocation, SoundEntry> ALL = new HashMap<>();
public static final SoundEntry
SCHEMATICANNON_LAUNCH_BLOCK = create("schematicannon_launch_block").subtitle("Schematicannon fires")
@ -306,20 +307,20 @@ public class AllSoundEvents {
return new SoundEntryBuilder(id);
}
public static void register(RegistryEvent.Register<SoundEvent> event) {
IForgeRegistry<SoundEvent> registry = event.getRegistry();
for (SoundEntry entry : entries.values())
entry.register(registry);
public static void prepare() {
for (SoundEntry entry : ALL.values())
entry.prepare();
}
public static void prepare() {
for (SoundEntry entry : entries.values())
entry.prepare();
public static void register(RegistryEvent.Register<SoundEvent> event) {
IForgeRegistry<SoundEvent> registry = event.getRegistry();
for (SoundEntry entry : ALL.values())
entry.register(registry);
}
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;
@ -370,7 +371,7 @@ public class AllSoundEvents {
try {
JsonObject json = new JsonObject();
entries.entrySet()
ALL.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> {
@ -386,12 +387,15 @@ public class AllSoundEvents {
}
public record ConfiguredSoundEvent(Supplier<SoundEvent> event, float volume, float pitch) {
}
public static class SoundEntryBuilder {
protected ResourceLocation id;
protected String subtitle = "unregistered";
protected SoundSource category = SoundSource.BLOCKS;
protected List<Pair<SoundEvent, Couple<Float>>> wrappedEvents;
protected List<ConfiguredSoundEvent> wrappedEvents;
protected List<ResourceLocation> variants;
protected int attenuationDistance;
@ -430,11 +434,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<SoundEvent> 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);
}
@ -443,7 +451,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;
}
@ -532,50 +540,53 @@ public class AllSoundEvents {
private static class WrappedSoundEntry extends SoundEntry {
private List<Pair<SoundEvent, Couple<Float>>> wrappedEvents;
private List<Pair<SoundEvent, Couple<Float>>> compiledEvents;
private List<ConfiguredSoundEvent> wrappedEvents;
private List<CompiledSoundEvent> compiledEvents;
public WrappedSoundEntry(ResourceLocation id, String subtitle,
List<Pair<SoundEvent, Couple<Float>>> wrappedEvents, SoundSource category, int attenuationDistance) {
List<ConfiguredSoundEvent> 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).setRegistryName(location);
compiledEvents.add(Pair.of(sound, wrappedEvents.get(i)
.getSecond()));
ConfiguredSoundEvent wrapped = wrappedEvents.get(i);
ResourceLocation location = getIdOf(i);
RegistryObject<SoundEvent> event = RegistryObject.create(location, ForgeRegistries.SOUND_EVENTS);
compiledEvents.add(new CompiledSoundEvent(event, wrapped.volume(), wrapped.pitch()));
}
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
for (Pair<SoundEvent, Couple<Float>> pair : compiledEvents)
registry.register(pair.getFirst());
for (CompiledSoundEvent compiledEvent : compiledEvents) {
ResourceLocation location = compiledEvent.event().getId();
registry.register(new SoundEvent(location).setRegistryName(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<SoundEvent, Couple<Float>> 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");
@ -585,33 +596,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<SoundEvent, Couple<Float>> pair : compiledEvents) {
Couple<Float> 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<SoundEvent, Couple<Float>> pair : compiledEvents) {
Couple<Float> 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<SoundEvent> event, float volume, float pitch) {
}
}
private static class CustomSoundEntry extends SoundEntry {
protected List<ResourceLocation> variants;
protected SoundEvent event;
protected RegistryObject<SoundEvent> event;
public CustomSoundEntry(ResourceLocation id, List<ResourceLocation> variants, String subtitle,
SoundSource category, int attenuationDistance) {
@ -621,17 +634,18 @@ public class AllSoundEvents {
@Override
public void prepare() {
event = new SoundEvent(id).setRegistryName(id);
event = RegistryObject.create(id, ForgeRegistries.SOUND_EVENTS);
}
@Override
public void register(IForgeRegistry<SoundEvent> registry) {
registry.register(event);
ResourceLocation location = event.getId();
registry.register(new SoundEvent(location).setRegistryName(location));
}
@Override
public SoundEvent getMainEvent() {
return event;
return event.get();
}
@Override
@ -663,12 +677,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);
}
}

View file

@ -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<StructureProcessorType<?>> REGISTER = DeferredRegister.create(Registry.STRUCTURE_PROCESSOR_REGISTRY, Create.ID);
public static final RegistryObject<StructureProcessorType<SchematicProcessor>> SCHEMATIC = REGISTER.register("schematic", () -> () -> SchematicProcessor.CODEC);
public static void register(IEventBus modEventBus) {
REGISTER.register(modEventBus);
}
}

View file

@ -112,9 +112,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,
@ -122,10 +124,6 @@ public class AllTags {
WINDMILL_SAILS,
WINDOWABLE,
WRENCH_PICKUP,
CASING,
NON_MOVABLE,
PASSIVE_BOILER_HEATERS,
RELOCATION_NOT_SUPPORTED(FORGE),
WG_STONE(FORGE),
@ -208,10 +206,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,
@ -219,9 +220,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);

View file

@ -21,7 +21,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;
@ -38,18 +37,17 @@ 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.core.particles.ParticleType;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.MinecraftForge;
@ -61,7 +59,6 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
import net.minecraftforge.registries.DataSerializerEntry;
@Mod(Create.ID)
public class Create {
@ -97,6 +94,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();
@ -106,34 +107,33 @@ 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.addGenericListener(Feature.class, AllWorldFeatures::registerOreFeatures);
modEventBus.addGenericListener(RecipeSerializer.class, AllRecipeTypes::register);
modEventBus.addGenericListener(ParticleType.class, AllParticleTypes::register);
modEventBus.addGenericListener(SoundEvent.class, AllSoundEvents::register);
modEventBus.addGenericListener(DataSerializerEntry.class, AllEntityDataSerializers::register);
forgeEventBus.addListener(EventPriority.HIGH, SlidingDoorBlock::stopItQuark);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.onCtorClient(modEventBus, forgeEventBus));
Mods.CURIOS.executeIfInstalled(() -> Curios::init);
@ -148,22 +148,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(new AllAdvancements(gen));
gen.addProvider(new LangMerger(gen));
gen.addProvider(AllSoundEvents.provider(gen));
gen.addProvider(new StandardRecipeGen(gen));
gen.addProvider(new MechanicalCraftingRecipeGen(gen));
gen.addProvider(new SequencedAssemblyRecipeGen(gen));
ProcessingRecipeGen.registerAll(gen);
if (event.includeClient()) {
gen.addProvider(new LangMerger(gen));
gen.addProvider(AllSoundEvents.provider(gen));
}
if (event.includeServer()) {
gen.addProvider(new AllAdvancements(gen));
gen.addProvider(new StandardRecipeGen(gen));
gen.addProvider(new MechanicalCraftingRecipeGen(gen));
gen.addProvider(new SequencedAssemblyRecipeGen(gen));
ProcessingRecipeGen.registerAll(gen);
// AllOreFeatureConfigEntries.gatherData(event);
}
}
public static CreateRegistrate registrate() {

View file

@ -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());
}

View file

@ -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<SmartFluidTankBehaviour> getTanks() {

View file

@ -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> soundEvent;
private final float toughness;
private final float knockbackResistance;
private final Supplier<Ingredient> repairMaterial;
private AllArmorMaterials(String name, int maxDamageFactor, int[] damageReductionAmountArray, int enchantability,
SoundEvent soundEvent, float toughness, float knockbackResistance, Supplier<Ingredient> repairMaterial) {
Supplier<SoundEvent> soundEvent, float toughness, float knockbackResistance, Supplier<Ingredient> 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

View file

@ -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<SchematicProcessor> CODEC = Codec.unit(() -> {
return INSTANCE;
});
public static StructureProcessorType<SchematicProcessor> 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();
}
}

View file

@ -20,7 +20,7 @@ import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.foundation.utility.WorldAttached;
import com.simibubi.create.foundation.utility.recipe.RecipeFinder;
import com.simibubi.create.foundation.worldgen.AllWorldFeatures;
import com.simibubi.create.foundation.worldgen.AllOreFeatureConfigEntries;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
@ -213,7 +213,7 @@ public class CommonEvents {
@SubscribeEvent(priority = EventPriority.HIGH)
public static void onBiomeLoad(BiomeLoadingEvent event) {
AllWorldFeatures.reload(event);
AllOreFeatureConfigEntries.modifyBiomes(event);
}
public static void leftClickEmpty(ServerPlayer player) {

View file

@ -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 {

View file

@ -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 <T extends Enum<T>> ConfigEnum<T> e(T defaultValue, String name, String... comment) {
return new ConfigEnum<>(name, defaultValue, comment);
}

View file

@ -0,0 +1,93 @@
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.Gson;
import com.google.gson.GsonBuilder;
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.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.data.HashCache;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
public class DynamicDataProvider<T> implements DataProvider {
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private final DataGenerator generator;
private final String name;
private final RegistryAccess registryAccess;
private final RegistryAccess.RegistryData<T> registryData;
private final Map<ResourceLocation, T> values;
public DynamicDataProvider(DataGenerator generator, String name, RegistryAccess registryAccess, RegistryAccess.RegistryData<T> registryData, Map<ResourceLocation, T> values) {
this.generator = generator;
this.name = name;
this.registryAccess = registryAccess;
this.registryData = registryData;
this.values = values;
}
@Nullable
public static <T> DynamicDataProvider<T> create(DataGenerator generator, String name, RegistryAccess registryAccess, ResourceKey<? extends Registry<T>> registryKey, Map<ResourceLocation, T> values) {
@SuppressWarnings("unchecked")
RegistryAccess.RegistryData<T> registryData = (RegistryData<T>) RegistryAccess.REGISTRIES.get(registryKey);
if (registryData == null) {
return null;
}
return new DynamicDataProvider<>(generator, name, registryAccess, registryData, values);
}
@Override
public void run(HashCache cache) throws IOException {
Path path = generator.getOutputFolder();
DynamicOps<JsonElement> ops = RegistryOps.create(JsonOps.INSTANCE, registryAccess);
dumpValues(path, cache, ops, registryData.key(), values, registryData.codec());
}
private void dumpValues(Path rootPath, HashCache cache, DynamicOps<JsonElement> ops, ResourceKey<? extends Registry<T>> registryKey, Map<ResourceLocation, T> values, Encoder<T> encoder) {
for (Entry<ResourceLocation, T> entry : values.entrySet()) {
Path path = createPath(rootPath, registryKey.location(), entry.getKey());
dumpValue(path, cache, ops, encoder, entry.getValue());
}
}
// From WorldgenRegistryDumpReport
private void dumpValue(Path path, HashCache cache, DynamicOps<JsonElement> ops, Encoder<T> encoder, T value) {
try {
Optional<JsonElement> optional = encoder.encodeStart(ops, value).resultOrPartial((message) -> {
Create.LOGGER.error("Couldn't serialize element {}: {}", path, message);
});
if (optional.isPresent()) {
DataProvider.save(GSON, cache, optional.get(), path);
}
} catch (IOException e) {
Create.LOGGER.error("Couldn't save element {}", path, e);
}
}
private Path createPath(Path path, ResourceLocation registry, ResourceLocation value) {
return path.resolve("data").resolve(value.getNamespace()).resolve(registry.getPath()).resolve(value.getPath() + ".json");
}
@Override
public String getName() {
return name;
}
}

View file

@ -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<Feature<?>> REGISTER = DeferredRegister.create(ForgeRegistries.FEATURES, Create.ID);
public static final RegistryObject<StandardOreFeature> STANDARD_ORE = REGISTER.register("standard_ore", () -> new StandardOreFeature());
public static final RegistryObject<LayeredOreFeature> LAYERED_ORE = REGISTER.register("layered_ore", () -> new LayeredOreFeature());
public static void register(IEventBus modEventBus) {
REGISTER.register(modEventBus);
}
}

View file

@ -7,7 +7,7 @@ import net.minecraft.world.level.block.Blocks;
public class AllLayerPatterns {
public static NonNullSupplier<LayerPattern>
public static final NonNullSupplier<LayerPattern>
CINNABAR = () -> LayerPattern.builder()
.layer(l -> l.weight(1)
@ -25,7 +25,7 @@ public class AllLayerPatterns {
.block(AllPaletteStoneTypes.LIMESTONE.getBaseBlock()))
.build();
public static NonNullSupplier<LayerPattern> MAGNETITE = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> OCHRESTONE = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> MALACHITE = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> SCORIA = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> LIMESTONE = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> SCORIA_NETHER = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> 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<LayerPattern> SCORCHIA_NETHER = () -> LayerPattern.builder()
public static final NonNullSupplier<LayerPattern> SCORCHIA_NETHER = () -> LayerPattern.builder()
.inNether()
.layer(l -> l.weight(2)
.passiveBlock())

View file

@ -0,0 +1,134 @@
package com.simibubi.create.foundation.worldgen;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
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.BuiltinRegistries;
import net.minecraft.data.DataGenerator;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.event.world.BiomeLoadingEvent;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
public class AllOreFeatureConfigEntries {
private static final Predicate<BiomeLoadingEvent> OVERWORLD_BIOMES = event -> {
Biome.BiomeCategory category = event.getCategory();
return category != BiomeCategory.NETHER && category != BiomeCategory.THEEND && category != BiomeCategory.NONE;
};
private static final Predicate<BiomeLoadingEvent> NETHER_BIOMES = event -> {
Biome.BiomeCategory category = event.getCategory();
return category == BiomeCategory.NETHER;
};
//
public static final OreFeatureConfigEntry ZINC_ORE =
create("zinc_ore", 12, 8, -63, 70)
.biomeExt()
.predicate(OVERWORLD_BIOMES)
.parent()
.standardDatagenExt()
.withBlocks(Couple.create(AllBlocks.ZINC_ORE, AllBlocks.DEEPSLATE_ZINC_ORE))
.parent();
public static final OreFeatureConfigEntry STRIATED_ORES_OVERWORLD =
create("striated_ores_overworld", 32, 1 / 12f, -30, 70)
.biomeExt()
.predicate(OVERWORLD_BIOMES)
.parent()
.layeredDatagenExt()
.withLayerPattern(AllLayerPatterns.SCORIA)
.withLayerPattern(AllLayerPatterns.CINNABAR)
.withLayerPattern(AllLayerPatterns.MAGNETITE)
.withLayerPattern(AllLayerPatterns.MALACHITE)
.withLayerPattern(AllLayerPatterns.LIMESTONE)
.withLayerPattern(AllLayerPatterns.OCHRESTONE)
.parent();
public static final OreFeatureConfigEntry STRIATED_ORES_NETHER =
create("striated_ores_nether", 32, 1 / 12f, 40, 90)
.biomeExt()
.predicate(NETHER_BIOMES)
.parent()
.layeredDatagenExt()
.withLayerPattern(AllLayerPatterns.SCORIA_NETHER)
.withLayerPattern(AllLayerPatterns.SCORCHIA_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 modifyBiomes(BiomeLoadingEvent event) {
for (OreFeatureConfigEntry entry : OreFeatureConfigEntry.ALL.values()) {
entry.biomeExt().modifyBiomes(event, BuiltinRegistries.PLACED_FEATURE);
}
}
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
RegistryAccess registryAccess = RegistryAccess.BUILTIN.get();
//
Map<ResourceLocation, ConfiguredFeature<?, ?>> configuredFeatures = new HashMap<>();
for (Map.Entry<ResourceLocation, OreFeatureConfigEntry> entry : OreFeatureConfigEntry.ALL.entrySet()) {
DatagenExtension datagenExt = entry.getValue().datagenExt();
if (datagenExt != null) {
configuredFeatures.put(entry.getKey(), datagenExt.getConfiguredFeature());
}
}
DynamicDataProvider<ConfiguredFeature<?, ?>> configuredFeatureProvider = DynamicDataProvider.create(generator, "Create's Configured Features", registryAccess, Registry.CONFIGURED_FEATURE_REGISTRY, configuredFeatures);
if (configuredFeatureProvider != null) {
generator.addProvider(configuredFeatureProvider);
}
//
Map<ResourceLocation, PlacedFeature> placedFeatures = new HashMap<>();
for (Map.Entry<ResourceLocation, OreFeatureConfigEntry> entry : OreFeatureConfigEntry.ALL.entrySet()) {
DatagenExtension datagenExt = entry.getValue().datagenExt();
if (datagenExt != null) {
placedFeatures.put(entry.getKey(), datagenExt.getPlacedFeature());
}
}
DynamicDataProvider<PlacedFeature> placedFeatureProvider = DynamicDataProvider.create(generator, "Create's Placed Features", registryAccess, Registry.PLACED_FEATURE_REGISTRY, placedFeatures);
if (placedFeatureProvider != null) {
generator.addProvider(placedFeatureProvider);
}
}
}

View file

@ -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<PlacementModifierType<?>> REGISTER = DeferredRegister.create(Registry.PLACEMENT_MODIFIER_REGISTRY, Create.ID);
public static final RegistryObject<PlacementModifierType<ConfigDrivenPlacement>> CONFIG_DRIVEN = REGISTER.register("config_driven", () -> () -> ConfigDrivenPlacement.CODEC);
public static void register(IEventBus modEventBus) {
REGISTER.register(modEventBus);
}
}

View file

@ -1,116 +0,0 @@
package com.simibubi.create.foundation.worldgen;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ImmutableList;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.core.Registry;
import net.minecraft.data.BuiltinRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.GenerationStep.Decoration;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.world.BiomeLoadingEvent;
public class AllWorldFeatures {
public static final Map<ResourceLocation, ConfigDrivenFeatureEntry> ENTRIES = new HashMap<>();
private static final BiomeFilter OVERWORLD_BIOMES =
(r, b) -> b != BiomeCategory.NETHER && b != BiomeCategory.THEEND && b != BiomeCategory.NONE;
private static final BiomeFilter NETHER_BIOMES = (r, b) -> b == BiomeCategory.NETHER;
//
public static final ConfigDrivenFeatureEntry ZINC_ORE =
register("zinc_ore", 12, 8, OVERWORLD_BIOMES).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, OVERWORLD_BIOMES).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, NETHER_BIOMES).between(40, 90)
.withLayerPattern(AllLayerPatterns.SCORIA_NETHER)
.withLayerPattern(AllLayerPatterns.SCORCHIA_NETHER);
//
private static ConfigDrivenFeatureEntry register(String id, int clusterSize, float frequency,
BiomeFilter biomeFilter) {
ConfigDrivenFeatureEntry configDrivenFeatureEntry = new ConfigDrivenFeatureEntry(id, clusterSize, frequency);
configDrivenFeatureEntry.biomeFilter = biomeFilter;
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 reload(BiomeLoadingEvent event) {
BiomeGenerationSettingsBuilder generation = event.getGeneration();
Decoration decoStep = GenerationStep.Decoration.UNDERGROUND_ORES;
ENTRIES.values()
.forEach(entry -> {
ConfigDrivenFeatureEntry value = entry;
if (value.biomeFilter.test(event.getName(), event.getCategory()))
generation.addFeature(decoStep, value.placedFeature);
});
}
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(RegistryEvent.Register<Feature<?>> event) {
event.getRegistry()
.registerAll(VanillaStyleOreFeature.INSTANCE, LayeredOreFeature.INSTANCE);
}
public static void registerPlacementTypes() {
ConfigDrivenDecorator.TYPE =
Registry.register(Registry.PLACEMENT_MODIFIERS, "create_config_driven", () -> ConfigDrivenDecorator.CODEC);
}
}

View file

@ -3,23 +3,24 @@ package com.simibubi.create.foundation.worldgen;
import java.util.Random;
import java.util.function.Function;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
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<ConfigDrivenOreConfiguration> {
public OreFeatureBase() {
super(ConfigDrivenOreConfiguration.CODEC);
public abstract class BaseConfigDrivenOreFeature<FC extends BaseConfigDrivenOreFeatureConfiguration> extends Feature<FC> {
public BaseConfigDrivenOreFeature(Codec<FC> configCodec) {
super(configCodec);
}
public boolean canPlaceOre(BlockState pState, Function<BlockPos, BlockState> pAdjacentStateAccessor,
Random pRandom, ConfigDrivenOreConfiguration pConfig, OreConfiguration.TargetBlockState pTargetState,
Random 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);

View file

@ -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;
}
}

View file

@ -1,10 +0,0 @@
package com.simibubi.create.foundation.worldgen;
import java.util.function.BiPredicate;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome.BiomeCategory;
public interface BiomeFilter extends BiPredicate<ResourceLocation, BiomeCategory> {
}

View file

@ -0,0 +1,36 @@
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.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
public class BuiltinRegistration {
private static final DeferredRegister<ConfiguredFeature<?, ?>> CONFIGURED_FEATURE_REGISTER = DeferredRegister.create(Registry.CONFIGURED_FEATURE_REGISTRY, Create.ID);
private static final DeferredRegister<PlacedFeature> PLACED_FEATURE_REGISTER = DeferredRegister.create(Registry.PLACED_FEATURE_REGISTRY, Create.ID);
static {
for (Map.Entry<ResourceLocation, OreFeatureConfigEntry> 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());
}
}
}
}
public static void register(IEventBus modEventBus) {
CONFIGURED_FEATURE_REGISTER.register(modEventBus);
PLACED_FEATURE_REGISTER.register(modEventBus);
}
}

View file

@ -1,67 +0,0 @@
package com.simibubi.create.foundation.worldgen;
import java.util.Random;
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.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<ConfigDrivenDecorator> TYPE;
public static final Codec<ConfigDrivenDecorator> 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<BlockPos> getPositions(PlacementContext context, Random 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);
}
}

View file

@ -1,118 +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.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 BiomeFilter biomeFilter;
private NonNullSupplier<? extends Block> block;
private NonNullSupplier<? extends Block> deepblock;
private NonNullSupplier<? extends Block> netherblock;
private List<NonNullSupplier<LayerPattern>> layers = new ArrayList<>();
protected ConfigInt clusterSize;
protected ConfigInt minHeight;
protected ConfigInt maxHeight;
protected ConfigFloat frequency;
Function<ConfigDrivenFeatureEntry, ? extends ConfiguredFeature<?, ?>> factory;
Holder<ConfiguredFeature<?, ?>> configuredFeature;
Holder<PlacedFeature> 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<LayerPattern> pattern) {
this.layers.add(pattern);
this.factory = this::layersFactory;
return this;
}
public ConfigDrivenFeatureEntry withBlock(NonNullSupplier<? extends Block> block) {
this.block = this.deepblock = block;
return this;
}
public ConfigDrivenFeatureEntry withNetherBlock(NonNullSupplier<? extends Block> block) {
this.netherblock = block;
return this;
}
public ConfigDrivenFeatureEntry withBlocks(Couple<NonNullSupplier<? extends Block>> 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<TargetBlockState> createTarget() {
List<TargetBlockState> 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;
}
}

View file

@ -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<ConfigDrivenLayeredOreFeatureConfiguration> 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<LayerPattern> layerPatterns;
public ConfigDrivenLayeredOreFeatureConfiguration(OreFeatureConfigEntry entry, float discardChance, List<LayerPattern> layerPatterns) {
super(entry, discardChance);
this.layerPatterns = layerPatterns;
}
public List<LayerPattern> getLayerPatterns() {
return layerPatterns;
}
}

View file

@ -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<ConfigDrivenOreConfiguration> 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<TargetBlockState> targetStates;
public final float discardChanceOnAirExposure;
public final ResourceLocation key;
public ConfigDrivenOreConfiguration(List<TargetBlockState> 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<LayerPattern> 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);
}
}

View file

@ -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<ConfigDrivenOreFeatureConfiguration> 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<TargetBlockState> targetStates;
public ConfigDrivenOreFeatureConfiguration(OreFeatureConfigEntry entry, float discardChance, List<TargetBlockState> targetStates) {
super(entry, discardChance);
this.targetStates = targetStates;
}
public List<TargetBlockState> getTargetStates() {
return targetStates;
}
}

View file

@ -0,0 +1,79 @@
package com.simibubi.create.foundation.worldgen;
import java.util.Random;
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.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<ConfigDrivenPlacement> 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<BlockPos> getPositions(PlacementContext context, Random 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, Random 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();
}
}

View file

@ -7,8 +7,9 @@ import java.util.Random;
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<LayerPattern> CODEC = Codec.list(Layer.CODEC)
.xmap(LayerPattern::new, pattern -> pattern.layers);
List<Layer> layers;
public final List<Layer> layers;
public LayerPattern() {
layers = new ArrayList<>();
}
public static Builder builder() {
LayerPattern ore = new LayerPattern();
return ore.new Builder();
public LayerPattern(List<Layer> layers) {
this.layers = layers;
}
public Layer rollNext(@Nullable Layer previous, Random 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<Layer> layers = new ArrayList<>();
private boolean netherMode;
public LayerPattern build() {
return LayerPattern.this;
}
public Builder inNether() {
netherMode = true;
return this;
}
public Builder layer(NonNullConsumer<LayerBuilder> builder) {
Layer layer = new Layer();
LayerBuilder layerBuilder = layer.new LayerBuilder();
public Builder layer(NonNullConsumer<Layer.Builder> 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<Layer> 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<List<TargetBlockState>> targets;
public int minSize;
public int maxSize;
public int weight;
public final List<List<TargetBlockState>> 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<List<TargetBlockState>> targets, int minSize, int maxSize, int weight) {
this.targets = targets;
this.minSize = minSize;
this.maxSize = maxSize;
this.weight = weight;
}
public List<TargetBlockState> rollBlock(Random random) {
@ -93,36 +109,35 @@ public class LayerPattern {
return targets.get(random.nextInt(targets.size()));
}
class LayerBuilder {
public static class Builder {
private final List<List<TargetBlockState>> 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<? extends Block> block) {
public Builder block(NonNullSupplier<? extends Block> 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<NonNullSupplier<? extends Block>> blocksByDepth) {
public Builder blocks(Couple<NonNullSupplier<? extends Block>> 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);
}
}
}
}

View file

@ -1,9 +1,7 @@
package com.simibubi.create.foundation.worldgen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.simibubi.create.foundation.worldgen.LayerPattern.Layer;
@ -11,7 +9,6 @@ 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.world.level.WorldGenLevel;
import net.minecraft.world.level.block.state.BlockState;
@ -22,23 +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<ResourceLocation, List<LayerPattern>> LAYER_PATTERNS = new HashMap<>();
public static final LayeredOreFeature INSTANCE = new LayeredOreFeature();
public class LayeredOreFeature extends BaseConfigDrivenOreFeature<ConfigDrivenLayeredOreFeatureConfiguration> {
public LayeredOreFeature() {
setRegistryName("config_driven_layered_ore");
super(ConfigDrivenLayeredOreFeatureConfiguration.CODEC);
}
public boolean place(FeaturePlaceContext<ConfigDrivenOreConfiguration> pContext) {
@Override
public boolean place(FeaturePlaceContext<ConfigDrivenLayeredOreFeatureConfiguration> pContext) {
Random random = pContext.random();
BlockPos blockpos = pContext.origin();
WorldGenLevel worldgenlevel = pContext.level();
ConfigDrivenOreConfiguration config = pContext.config();
List<LayerPattern> patternPool = config.getLayers();
ConfigDrivenLayeredOreFeatureConfiguration config = pContext.config();
List<LayerPattern> patternPool = config.getLayerPatterns();
if (patternPool.isEmpty())
return false;
@ -46,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;
@ -150,5 +142,4 @@ public class LayeredOreFeature extends OreFeatureBase {
bulksectionaccess.close();
return placedAmount > 0;
}
}

View file

@ -0,0 +1,233 @@
package com.simibubi.create.foundation.worldgen;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
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.Registry;
import net.minecraft.data.worldgen.features.OreFeatures;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.GenerationStep;
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.event.world.BiomeLoadingEvent;
public class OreFeatureConfigEntry extends ConfigBase {
public static final Map<ResourceLocation, OreFeatureConfigEntry> ALL = new HashMap<>();
public static final Codec<OreFeatureConfigEntry> 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 BiomeExtension biomeExt;
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);
}
public BiomeExtension biomeExt() {
if (biomeExt == null) {
biomeExt = new BiomeExtension();
}
return biomeExt;
}
@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<OreFeatureConfigEntry> 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 class BiomeExtension {
public ResourceLocation placedFeatureLocation = id;
public Predicate<BiomeLoadingEvent> biomePredicate = e -> false;
public BiomeExtension feature(ResourceLocation placedFeature) {
this.placedFeatureLocation = placedFeature;
return this;
}
public BiomeExtension predicate(Predicate<BiomeLoadingEvent> predicate) {
this.biomePredicate = predicate;
return this;
}
public void modifyBiomes(BiomeLoadingEvent event, Registry<PlacedFeature> registry) {
if (biomePredicate.test(event)) {
Optional<Holder<PlacedFeature>> optionalFeature = registry.getHolder(ResourceKey.create(Registry.PLACED_FEATURE_REGISTRY, placedFeatureLocation));
if (optionalFeature.isPresent()) {
event.getGeneration().addFeature(GenerationStep.Decoration.UNDERGROUND_ORES, optionalFeature.get());
}
}
}
public OreFeatureConfigEntry parent() {
return OreFeatureConfigEntry.this;
}
}
public abstract class DatagenExtension {
protected ConfiguredFeature<?, ?> configuredFeature;
protected PlacedFeature placedFeature;
public abstract ConfiguredFeature<?, ?> getConfiguredFeature();
public PlacedFeature getPlacedFeature() {
if (placedFeature != null) {
return placedFeature;
}
placedFeature = new PlacedFeature(Holder.direct(getConfiguredFeature()), List.of(new ConfigDrivenPlacement(OreFeatureConfigEntry.this)));
return placedFeature;
}
public OreFeatureConfigEntry parent() {
return OreFeatureConfigEntry.this;
}
}
public class StandardDatagenExtension extends DatagenExtension {
public NonNullSupplier<? extends Block> block;
public NonNullSupplier<? extends Block> deepBlock;
public NonNullSupplier<? extends Block> netherBlock;
public StandardDatagenExtension withBlock(NonNullSupplier<? extends Block> block) {
this.block = block;
this.deepBlock = block;
return this;
}
public StandardDatagenExtension withBlocks(Couple<NonNullSupplier<? extends Block>> blocks) {
this.block = blocks.getFirst();
this.deepBlock = blocks.getSecond();
return this;
}
public StandardDatagenExtension withNetherBlock(NonNullSupplier<? extends Block> block) {
this.netherBlock = block;
return this;
}
@Override
public ConfiguredFeature<?, ?> getConfiguredFeature() {
if (configuredFeature != null) {
return configuredFeature;
}
List<TargetBlockState> 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<NonNullSupplier<LayerPattern>> layerPatterns = new ArrayList<>();
public LayeredDatagenExtension withLayerPattern(NonNullSupplier<LayerPattern> pattern) {
this.layerPatterns.add(pattern);
return this;
}
@Override
public ConfiguredFeature<?, ?> getConfiguredFeature() {
if (configuredFeature != null) {
return configuredFeature;
}
List<LayerPattern> 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;
}
}
}

View file

@ -0,0 +1,168 @@
package com.simibubi.create.foundation.worldgen;
import java.util.BitSet;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
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<ConfigDrivenOreFeatureConfiguration> {
public StandardOreFeature() {
super(ConfigDrivenOreFeatureConfiguration.CODEC);
}
// From OreFeature, slight adjustments
@Override
public boolean place(FeaturePlaceContext<ConfigDrivenOreFeatureConfiguration> pContext) {
Random 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, Random 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;
}
}

View file

@ -1,176 +0,0 @@
package com.simibubi.create.foundation.worldgen;
import java.util.BitSet;
import java.util.Random;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
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();
public VanillaStyleOreFeature() {
setRegistryName("config_driven_ore");
}
// From OreFeature, slight adjustments
public boolean place(FeaturePlaceContext<ConfigDrivenOreConfiguration> pContext) {
Random 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, Random 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;
}
}