diff --git a/src/main/java/org/betterx/bclib/BCLib.java b/src/main/java/org/betterx/bclib/BCLib.java index 0be4ae84..be232144 100644 --- a/src/main/java/org/betterx/bclib/BCLib.java +++ b/src/main/java/org/betterx/bclib/BCLib.java @@ -38,7 +38,7 @@ public class BCLib implements ModInitializer { CraftingRecipes.init(); WorldDataAPI.registerModCache(MOD_ID); DataExchangeAPI.registerMod(MOD_ID); - WorldPresets.register(); + WorldPresets.registerPresets(); AnvilRecipe.register(); DataExchangeAPI.registerDescriptors(List.of( @@ -47,7 +47,7 @@ public class BCLib implements ModInitializer { RequestFiles.DESCRIPTOR, SendFiles.DESCRIPTOR, Chunker.DESCRIPTOR - )); + )); BCLibPatch.register(); Configs.save(); diff --git a/src/main/java/org/betterx/bclib/client/BCLibClient.java b/src/main/java/org/betterx/bclib/client/BCLibClient.java index 2c8d7953..3cbdb6c3 100644 --- a/src/main/java/org/betterx/bclib/client/BCLibClient.java +++ b/src/main/java/org/betterx/bclib/client/BCLibClient.java @@ -11,6 +11,7 @@ import org.betterx.bclib.api.ModIntegrationAPI; import org.betterx.bclib.api.PostInitAPI; import org.betterx.bclib.api.dataexchange.DataExchangeAPI; import org.betterx.bclib.client.models.CustomModelBakery; +import org.betterx.bclib.client.presets.WorldPresetsUI; import org.betterx.bclib.registry.BaseBlockEntityRenders; import org.jetbrains.annotations.Nullable; @@ -27,6 +28,8 @@ public class BCLibClient implements ClientModInitializer, ModelResourceProvider, modelBakery = new CustomModelBakery(); ModelLoadingRegistry.INSTANCE.registerResourceProvider(rm -> this); ModelLoadingRegistry.INSTANCE.registerVariantProvider(rm -> this); + + WorldPresetsUI.setupClientside(); } @Override diff --git a/src/main/java/org/betterx/bclib/client/presets/WorldPresetsUI.java b/src/main/java/org/betterx/bclib/client/presets/WorldPresetsUI.java new file mode 100644 index 00000000..910431f3 --- /dev/null +++ b/src/main/java/org/betterx/bclib/client/presets/WorldPresetsUI.java @@ -0,0 +1,28 @@ +package org.betterx.bclib.client.presets; + +import net.minecraft.client.gui.screens.worldselection.PresetEditor; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.level.levelgen.presets.WorldPreset; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +import org.betterx.bclib.gui.worldgen.WorldSetupScreen; +import org.betterx.bclib.presets.WorldPresets; + +import java.util.Optional; + +@Environment(EnvType.CLIENT) +public class WorldPresetsUI { + public static void registerCustomizeUI(ResourceKey key, PresetEditor setupScreen) { + if (setupScreen != null) { + PresetEditor.EDITORS.put(Optional.of(key), setupScreen); + } + } + + public static void setupClientside() { + registerCustomizeUI(WorldPresets.BCL_WORLD, (createWorldScreen, worldCreationContext) -> { + return new WorldSetupScreen(createWorldScreen); + }); + } +} diff --git a/src/main/java/org/betterx/bclib/gui/worldgen/WorldSetupScreen.java b/src/main/java/org/betterx/bclib/gui/worldgen/WorldSetupScreen.java new file mode 100644 index 00000000..2d0c2f5a --- /dev/null +++ b/src/main/java/org/betterx/bclib/gui/worldgen/WorldSetupScreen.java @@ -0,0 +1,34 @@ +package org.betterx.bclib.gui.worldgen; + +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.worldselection.WorldCreationContext; +import net.minecraft.core.Registry; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.levelgen.FlatLevelSource; +import net.minecraft.world.level.levelgen.WorldGenSettings; +import net.minecraft.world.level.levelgen.flat.FlatLevelGeneratorSettings; +import net.minecraft.world.level.levelgen.structure.StructureSet; + +import org.betterx.bclib.gui.gridlayout.GridScreen; + +import org.jetbrains.annotations.Nullable; + +public class WorldSetupScreen extends GridScreen { + public WorldSetupScreen(@Nullable Screen parent) { + super(parent, Component.translatable("title.screen.bclib.worldgen.main"), 10, false); + } + + @Override + protected void initLayout() { + + } + + private static WorldCreationContext.Updater worldConfiguration(FlatLevelGeneratorSettings flatLevelGeneratorSettings) { + return (frozen, worldGenSettings) -> { + Registry registry = frozen.registryOrThrow(Registry.STRUCTURE_SET_REGISTRY); + ChunkGenerator chunkGenerator = new FlatLevelSource(registry, flatLevelGeneratorSettings); + return WorldGenSettings.replaceOverworldGenerator(frozen, worldGenSettings, chunkGenerator); + }; + } +} diff --git a/src/main/java/org/betterx/bclib/mixin/client/CreateWorldScreenMixin.java b/src/main/java/org/betterx/bclib/mixin/client/CreateWorldScreenMixin.java index 7db2dfd7..ba5dd512 100644 --- a/src/main/java/org/betterx/bclib/mixin/client/CreateWorldScreenMixin.java +++ b/src/main/java/org/betterx/bclib/mixin/client/CreateWorldScreenMixin.java @@ -4,10 +4,14 @@ import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.CreateWorldScreen; import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.WorldLoader; import net.minecraft.world.level.DataPackConfig; +import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.presets.WorldPreset; +import com.mojang.datafixers.util.Pair; import org.betterx.bclib.api.biomes.BiomeAPI; import org.betterx.bclib.presets.WorldPresets; import org.spongepowered.asm.mixin.Mixin; @@ -28,8 +32,18 @@ public class CreateWorldScreenMixin { BiomeAPI.initRegistry(worldGenSettingsComponent.registryHolder().registryOrThrow(Registry.BIOME_REGISTRY)); } + //Change the WorldPreset that is selected by default on the Create World Screen @ModifyArg(method = "openFresh", index = 1, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/worldselection/WorldGenSettingsComponent;(Lnet/minecraft/client/gui/screens/worldselection/WorldCreationContext;Ljava/util/Optional;Ljava/util/OptionalLong;)V")) private static Optional> bcl_NewDefault(Optional> preset) { - return Optional.of(WorldPresets.BCL_WORLD); + return WorldPresets.DEFAULT; + } + + //Make sure the WorldGenSettings match the default WorldPreset + @ModifyArg(method = "openFresh", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/WorldLoader;load(Lnet/minecraft/server/WorldLoader$InitConfig;Lnet/minecraft/server/WorldLoader$WorldDataSupplier;Lnet/minecraft/server/WorldLoader$ResultFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private static WorldLoader.WorldDataSupplier bcl_NewDefaultSettings(WorldLoader.WorldDataSupplier worldDataSupplier) { + return (resourceManager, dataPackConfig) -> { + Pair res = worldDataSupplier.get(resourceManager, dataPackConfig); + return WorldPresets.defaultWorldDataSupplier(res.getSecond()); + }; } } diff --git a/src/main/java/org/betterx/bclib/mixin/common/DedicatedServerPropertiesMixin.java b/src/main/java/org/betterx/bclib/mixin/common/DedicatedServerPropertiesMixin.java new file mode 100644 index 00000000..ac658a50 --- /dev/null +++ b/src/main/java/org/betterx/bclib/mixin/common/DedicatedServerPropertiesMixin.java @@ -0,0 +1,17 @@ +package org.betterx.bclib.mixin.common; + +import net.minecraft.server.dedicated.DedicatedServerProperties; + +import org.betterx.bclib.presets.WorldPresets; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(DedicatedServerProperties.class) +public class DedicatedServerPropertiesMixin { + //Make sure the default server properties use our Default World Preset + @ModifyArg(method = "", index = 3, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/dedicated/DedicatedServerProperties$WorldGenProperties;(Ljava/lang/String;Lcom/google/gson/JsonObject;ZLjava/lang/String;)V")) + private String bcl_foo(String levelType) { + return WorldPresets.DEFAULT.orElseThrow().location().toString(); + } +} diff --git a/src/main/java/org/betterx/bclib/mixin/common/MainMixin.java b/src/main/java/org/betterx/bclib/mixin/common/MainMixin.java index e7365400..36b9b55c 100644 --- a/src/main/java/org/betterx/bclib/mixin/common/MainMixin.java +++ b/src/main/java/org/betterx/bclib/mixin/common/MainMixin.java @@ -11,7 +11,7 @@ import org.betterx.bclib.api.LifeCycleAPI; import org.betterx.bclib.api.datafixer.DataFixerAPI; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.io.File; @@ -21,7 +21,16 @@ import java.util.Optional; @Mixin(Main.class) abstract public class MainMixin { - @Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource;createDefault(Ljava/nio/file/Path;)Lnet/minecraft/world/level/storage/LevelStorageSource;")) + @ModifyVariable(method = "main", ordinal = 0, at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;getSummary()Lnet/minecraft/world/level/storage/LevelSummary;")) + private static LevelStorageSource.LevelStorageAccess bc_createAccess(LevelStorageSource.LevelStorageAccess levelStorageAccess) { + DataFixerAPI.fixData(levelStorageAccess, false, (didFix) -> {/* not called when showUI==false */}); + + LifeCycleAPI._runBeforeLevelLoad(); + return levelStorageAccess; + } + + + //@Inject(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorageSource;createDefault(Ljava/nio/file/Path;)Lnet/minecraft/world/level/storage/LevelStorageSource;")) private static void bclib_callServerFix(String[] args, CallbackInfo ci) { OptionParser parser = new OptionParser(); ArgumentAcceptingOptionSpec optionUniverse = parser.accepts("universe") diff --git a/src/main/java/org/betterx/bclib/mixin/common/WorldGenPropertiesMixin.java b/src/main/java/org/betterx/bclib/mixin/common/WorldGenPropertiesMixin.java index 448bfbc8..a2955e8a 100644 --- a/src/main/java/org/betterx/bclib/mixin/common/WorldGenPropertiesMixin.java +++ b/src/main/java/org/betterx/bclib/mixin/common/WorldGenPropertiesMixin.java @@ -1,7 +1,10 @@ package org.betterx.bclib.mixin.common; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.dedicated.DedicatedServerProperties; +import net.minecraft.world.level.levelgen.presets.WorldPreset; +import org.betterx.bclib.presets.WorldPresets; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; @@ -12,4 +15,10 @@ public class WorldGenPropertiesMixin { public long bcl_create(long seed) { return seed; } + + //Make sure Servers use our Default World Preset + @ModifyArg(method = "create", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/core/Registry;getHolder(Lnet/minecraft/resources/ResourceKey;)Ljava/util/Optional;")) + private ResourceKey bcl_foo(ResourceKey resourceKey) { + return WorldPresets.DEFAULT.orElseThrow(); + } } \ No newline at end of file diff --git a/src/main/java/org/betterx/bclib/mixin/common/WorldPresetsBootstrapMixin.java b/src/main/java/org/betterx/bclib/mixin/common/WorldPresetsBootstrapMixin.java index 247001c2..7f65ab86 100644 --- a/src/main/java/org/betterx/bclib/mixin/common/WorldPresetsBootstrapMixin.java +++ b/src/main/java/org/betterx/bclib/mixin/common/WorldPresetsBootstrapMixin.java @@ -6,15 +6,12 @@ import net.minecraft.data.BuiltinRegistries; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; -import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; import net.minecraft.world.level.levelgen.presets.WorldPreset; import net.minecraft.world.level.levelgen.presets.WorldPresets; import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.synth.NormalNoise; -import org.betterx.bclib.world.generator.BCLibEndBiomeSource; -import org.betterx.bclib.world.generator.BCLibNetherBiomeSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -54,35 +51,27 @@ public abstract class WorldPresetsBootstrapMixin { @ModifyArg(method = "run", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/level/levelgen/presets/WorldPresets$Bootstrap;registerCustomOverworldPreset(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/LevelStem;)Lnet/minecraft/core/Holder;")) private LevelStem bcl_getOverworldStem(LevelStem overworldStem) { - BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(this.biomes); - BCLibEndBiomeSource endSource = new BCLibEndBiomeSource(this.biomes); - - LevelStem bclNether = new LevelStem( - this.netherDimensionType, - new NoiseBasedChunkGenerator( - this.structureSets, - this.noises, - netherSource, - this.netherNoiseSettings) + WorldPreset preset = new org.betterx.bclib.presets.WorldPresets.SortableWorldPreset( + Map.of(LevelStem.OVERWORLD, + overworldStem, + LevelStem.NETHER, + org.betterx.bclib.presets.WorldPresets.getBCLNetherLevelStem(this.biomes, + this.netherDimensionType, + this.structureSets, + this.noises, + this.netherNoiseSettings), + LevelStem.END, + org.betterx.bclib.presets.WorldPresets.getBCLEndLevelStem(this.biomes, + this.endDimensionType, + this.structureSets, + this.noises, + this.endNoiseSettings) + ), 0 ); - LevelStem bclEnd = new LevelStem( - this.endDimensionType, - new NoiseBasedChunkGenerator( - this.structureSets, - this.noises, - endSource, - this.endNoiseSettings) - ); - WorldPreset preset = new org.betterx.bclib.presets.WorldPresets.SortableWorldPreset(Map.of(LevelStem.OVERWORLD, - overworldStem, - LevelStem.NETHER, - bclNether, - LevelStem.END, - bclEnd), 0); - BuiltinRegistries.register(this.presets, org.betterx.bclib.presets.WorldPresets.BCL_WORLD, preset); return overworldStem; } + } \ No newline at end of file diff --git a/src/main/java/org/betterx/bclib/presets/WorldPresets.java b/src/main/java/org/betterx/bclib/presets/WorldPresets.java index 707e90b9..760746d8 100644 --- a/src/main/java/org/betterx/bclib/presets/WorldPresets.java +++ b/src/main/java/org/betterx/bclib/presets/WorldPresets.java @@ -1,23 +1,71 @@ package org.betterx.bclib.presets; -import net.minecraft.client.gui.screens.worldselection.PresetEditor; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; import net.minecraft.data.BuiltinRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.WorldPresetTags; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.LevelStem; +import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; +import net.minecraft.world.level.levelgen.NoiseGeneratorSettings; +import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.presets.WorldPreset; +import net.minecraft.world.level.levelgen.structure.StructureSet; +import net.minecraft.world.level.levelgen.synth.NormalNoise; +import com.mojang.datafixers.util.Pair; import org.betterx.bclib.BCLib; import org.betterx.bclib.api.tag.TagAPI; import org.betterx.bclib.api.tag.TagType; -import org.betterx.bclib.gui.modmenu.MainScreen; +import org.betterx.bclib.world.generator.BCLibEndBiomeSource; +import org.betterx.bclib.world.generator.BCLibNetherBiomeSource; import java.util.Map; import java.util.Optional; +import org.jetbrains.annotations.NotNull; public class WorldPresets { + @NotNull + public static LevelStem getBCLNetherLevelStem(Registry biomes, + Holder dimension, + Registry structureSets, + Registry noiseParameters, + Holder generatorSettings) { + BCLibNetherBiomeSource netherSource = new BCLibNetherBiomeSource(biomes); + LevelStem bclNether = new LevelStem( + dimension, + new NoiseBasedChunkGenerator( + structureSets, + noiseParameters, + netherSource, + generatorSettings) + ); + return bclNether; + } + + @NotNull + public static LevelStem getBCLEndLevelStem(Registry biomes, + Holder dimension, + Registry structureSets, + Registry noiseParameters, + Holder generatorSettings) { + BCLibEndBiomeSource netherSource = new BCLibEndBiomeSource(biomes); + LevelStem bclEnd = new LevelStem( + dimension, + new NoiseBasedChunkGenerator( + structureSets, + noiseParameters, + netherSource, + generatorSettings) + ); + return bclEnd; + } + public static class SortableWorldPreset extends WorldPreset { public final int sortOrder; @@ -27,22 +75,53 @@ public class WorldPresets { } } - public static TagType.Simple WORLD_PRESETS = + public static final TagType.Simple WORLD_PRESETS = TagAPI.registerType(BuiltinRegistries.WORLD_PRESET, "tags/worldgen/world_preset"); - public static ResourceKey BCL_WORLD = register(BCLib.makeID("normal")); + public static final ResourceKey BCL_WORLD = register(BCLib.makeID("normal")); + public static Optional> DEFAULT = Optional.of(BCL_WORLD); + + public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, + long seed, + boolean generateStructures, + boolean generateBonusChest) { + return registryAccess + .registryOrThrow(Registry.WORLD_PRESET_REGISTRY) + .getHolderOrThrow(DEFAULT.orElseThrow()) + .value() + .createWorldGenSettings(seed, generateStructures, generateBonusChest); + } + + public static Pair defaultWorldDataSupplier(RegistryAccess.Frozen frozen) { + WorldGenSettings worldGenSettings = createDefaultWorldFromPreset(frozen); + return Pair.of(worldGenSettings, frozen); + } + + public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess, long seed) { + return createDefaultWorldFromPreset(registryAccess, seed, true, false); + } + + public static WorldGenSettings createDefaultWorldFromPreset(RegistryAccess registryAccess) { + return createDefaultWorldFromPreset(registryAccess, RandomSource.create().nextLong()); + } + + /** + * Registers a custom WorldPreset (with custom rules and behaviour) + *

+ * See also {@link org.betterx.bclib.client.presets.WorldPresetsUI} if you need to add a Customize Button/Screen + * for your preset + * + * @param loc The ID of your Preset + * @return The key you may use to reference your new Preset + */ public static ResourceKey register(ResourceLocation loc) { - ResourceKey key = ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, - loc); + ResourceKey key = ResourceKey.create(Registry.WORLD_PRESET_REGISTRY, loc); WORLD_PRESETS.addUntyped(WorldPresetTags.NORMAL, key.location()); - PresetEditor.EDITORS.put(Optional.of(key), - (createWorldScreen, worldCreationContext) -> new MainScreen(createWorldScreen)); - return key; } - public static void register() { + public static void registerPresets() { } } diff --git a/src/main/resources/bclib.accesswidener b/src/main/resources/bclib.accesswidener index 2dd0e76c..ba0a8480 100644 --- a/src/main/resources/bclib.accesswidener +++ b/src/main/resources/bclib.accesswidener @@ -2,7 +2,6 @@ accessWidener v1 named # Classes accessible class net/minecraft/server/MinecraftServer$ReloadableResources -accessible class net/minecraft/client/Minecraft$ExperimentalDialogType accessible class net/minecraft/world/level/levelgen/SurfaceRules$Context accessible class net/minecraft/world/level/levelgen/SurfaceRules$Condition accessible class net/minecraft/world/level/levelgen/SurfaceRules$SurfaceRule diff --git a/src/main/resources/bclib.mixins.common.json b/src/main/resources/bclib.mixins.common.json index 0cea37ae..65e1496c 100644 --- a/src/main/resources/bclib.mixins.common.json +++ b/src/main/resources/bclib.mixins.common.json @@ -14,6 +14,7 @@ "ChunkGeneratorMixin", "ComposterBlockAccessor", "CraftingMenuMixin", + "DedicatedServerPropertiesMixin", "DiggerItemAccessor", "EnchantingTableBlockMixin", "ItemStackMixin",