Implement feature for mods to define new world types (#7448)

* Mods can now register world types via a new forge registry, and optionally register a settings screen to tweak them.
  * The default world type for dedicated servers and singleplayer world creation is configurable via forge's common config.
This commit is contained in:
David Quintana 2020-11-28 00:57:15 +01:00 committed by GitHub
parent cd393bbfdc
commit 93c00b67d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 519 additions and 4 deletions

View file

@ -0,0 +1,21 @@
--- a/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
+++ b/net/minecraft/client/gui/screen/BiomeGeneratorTypeScreens.java
@@ -113,6 +113,9 @@
private BiomeGeneratorTypeScreens(String p_i232324_1_) {
this.field_239076_k_ = new TranslationTextComponent("generator." + p_i232324_1_);
}
+ public BiomeGeneratorTypeScreens(ITextComponent displayName) {
+ this.field_239076_k_ = displayName;
+ }
private static DimensionGeneratorSettings func_243452_a(DynamicRegistries p_243452_0_, DimensionGeneratorSettings p_243452_1_, BiomeGeneratorTypeScreens p_243452_2_, Biome p_243452_3_) {
BiomeProvider biomeprovider = new SingleBiomeProvider(p_243452_3_);
@@ -166,4 +169,8 @@
public interface IFactory {
Screen createEditScreen(CreateWorldScreen p_createEditScreen_1_, DimensionGeneratorSettings p_createEditScreen_2_);
}
+
+ // Forge start
+ // For internal use only, automatically called for all ForgeWorldTypes. Register your ForgeWorldType in the forge registry!
+ public static void registerGenerator(BiomeGeneratorTypeScreens gen) { field_239068_c_.add(gen); }
}

View file

@ -1,5 +1,14 @@
--- a/net/minecraft/client/gui/screen/CreateWorldScreen.java
+++ b/net/minecraft/client/gui/screen/CreateWorldScreen.java
@@ -110,7 +110,7 @@
public static CreateWorldScreen func_243425_a(@Nullable Screen p_243425_0_) {
DynamicRegistries.Impl dynamicregistries$impl = DynamicRegistries.func_239770_b_();
- return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar)), Optional.of(BiomeGeneratorTypeScreens.field_239066_a_), OptionalLong.empty()));
+ return new CreateWorldScreen(p_243425_0_, DatapackCodec.field_234880_a_, new WorldOptionsScreen(dynamicregistries$impl, DimensionGeneratorSettings.func_242751_a(dynamicregistries$impl.func_243612_b(Registry.field_239698_ad_), dynamicregistries$impl.func_243612_b(Registry.field_239720_u_), dynamicregistries$impl.func_243612_b(Registry.field_243549_ar)), net.minecraftforge.client.ForgeHooksClient.getDefaultWorldType(), OptionalLong.empty()));
}
private CreateWorldScreen(@Nullable Screen p_i242063_1_, DatapackCodec p_i242063_2_, WorldOptionsScreen p_i242063_3_) {
@@ -542,6 +542,7 @@
File file1 = path.toFile();
if (this.field_243416_G == null) {

View file

@ -0,0 +1,19 @@
--- a/net/minecraft/client/gui/screen/WorldOptionsScreen.java
+++ b/net/minecraft/client/gui/screen/WorldOptionsScreen.java
@@ -134,6 +134,7 @@
this.field_239035_i_.field_230693_o_ = this.field_239040_n_.isPresent();
this.field_239036_j_ = p_239048_1_.func_230480_a_(new Button(j, 120, 150, 20, new TranslationTextComponent("selectWorld.customizeType"), (p_239044_3_) -> {
BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory = BiomeGeneratorTypeScreens.field_239069_d_.get(this.field_239040_n_);
+ biomegeneratortypescreens$ifactory = net.minecraftforge.client.ForgeHooksClient.getBiomeGeneratorTypeScreenFactory(this.field_239040_n_, biomegeneratortypescreens$ifactory);
if (biomegeneratortypescreens$ifactory != null) {
p_239048_2_.func_147108_a(biomegeneratortypescreens$ifactory.createEditScreen(p_239048_1_, this.field_239039_m_));
}
@@ -292,7 +293,7 @@
} else {
this.field_239034_h_.field_230694_p_ = p_239059_1_;
this.field_239027_a_.field_230694_p_ = p_239059_1_;
- this.field_239036_j_.field_230694_p_ = p_239059_1_ && BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_);
+ this.field_239036_j_.field_230694_p_ = p_239059_1_ && (BiomeGeneratorTypeScreens.field_239069_d_.containsKey(this.field_239040_n_) || net.minecraftforge.client.ForgeHooksClient.hasBiomeGeneratorSettingsOptionsScreen(this.field_239040_n_));
this.field_239037_k_.field_230694_p_ = p_239059_1_;
}

View file

@ -0,0 +1,20 @@
--- a/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
+++ b/net/minecraft/world/gen/settings/DimensionGeneratorSettings.java
@@ -192,7 +192,7 @@
String s3 = (String)p_242753_1_.get("level-type");
String s4 = Optional.ofNullable(s3).map((p_236217_0_) -> {
return p_236217_0_.toLowerCase(Locale.ROOT);
- }).orElse("default");
+ }).orElseGet(net.minecraftforge.common.ForgeHooks::getDefaultWorldType);
p_242753_1_.put("level-type", s4);
long i = (new Random()).nextLong();
if (!s1.isEmpty()) {
@@ -210,6 +210,8 @@
Registry<Biome> registry = p_242753_0_.func_243612_b(Registry.field_239720_u_);
Registry<DimensionSettings> registry1 = p_242753_0_.func_243612_b(Registry.field_243549_ar);
SimpleRegistry<Dimension> simpleregistry = DimensionType.func_242718_a(registry2, registry, registry1, i);
+ net.minecraftforge.common.world.ForgeWorldType type = net.minecraftforge.registries.ForgeRegistries.WORLD_TYPES.getValue(new net.minecraft.util.ResourceLocation(s4));
+ if (type != null) return type.createSettings(p_242753_0_, i, flag, false, s);
switch(s4) {
case "flat":
JsonObject jsonobject = !s.isEmpty() ? JSONUtils.func_212745_a(s) : new JsonObject();

View file

@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.fml.loading;
import net.minecraftforge.forgespi.language.MavenVersionAdapter;

View file

@ -31,6 +31,7 @@ import net.minecraft.client.audio.SoundEngine;
import net.minecraft.client.gui.AbstractGui;
import net.minecraft.client.gui.ClientBossInfo;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.client.gui.screen.MainMenuScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.play.NetworkPlayerInfo;
@ -78,6 +79,7 @@ import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.GameType;
import net.minecraft.world.IBlockDisplayReader;
import net.minecraft.world.World;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.client.event.*;
import net.minecraftforge.client.event.sound.PlaySoundEvent;
import net.minecraftforge.client.model.ModelLoader;
@ -102,12 +104,14 @@ import org.apache.logging.log4j.core.impl.ReusableLogEventFactory;
import org.lwjgl.opengl.GL13;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Stream;
@ -785,4 +789,29 @@ public class ForgeHooksClient
});
setRenderLayer(null);
}
public static void registerForgeWorldTypeScreens()
{
ForgeWorldTypeScreens.registerTypes();
}
public static BiomeGeneratorTypeScreens.IFactory getBiomeGeneratorTypeScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return ForgeWorldTypeScreens.getGeneratorScreenFactory(generator, biomegeneratortypescreens$ifactory);
}
public static boolean hasBiomeGeneratorSettingsOptionsScreen(Optional<BiomeGeneratorTypeScreens> generator)
{
return getBiomeGeneratorTypeScreenFactory(generator, null) != null;
}
public static Optional<BiomeGeneratorTypeScreens> getWorldTypeFromGenerator(DimensionGeneratorSettings dimensionGeneratorSettings)
{
return BiomeGeneratorTypeScreens.func_239079_a_(dimensionGeneratorSettings);
}
public static Optional<BiomeGeneratorTypeScreens> getDefaultWorldType()
{
return Optional.of(ForgeWorldTypeScreens.getDefaultGenerator());
}
}

View file

@ -0,0 +1,118 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.client;
import com.google.common.collect.Maps;
import net.minecraft.client.gui.screen.BiomeGeneratorTypeScreens;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Optional;
public class ForgeWorldTypeScreens
{
private static final Logger LOGGER = LogManager.getLogger();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens> GENERATORS = Maps.newHashMap();
private static final Map<ForgeWorldType, BiomeGeneratorTypeScreens.IFactory> GENERATOR_SCREEN_FACTORIES = Maps.newHashMap();
public static synchronized void registerFactory(ForgeWorldType type, BiomeGeneratorTypeScreens.IFactory factory)
{
if (GENERATOR_SCREEN_FACTORIES.containsKey(type))
throw new IllegalStateException("Factory has already been registered for: " + type);
GENERATOR_SCREEN_FACTORIES.put(type, factory);
}
static BiomeGeneratorTypeScreens getDefaultGenerator()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def == null)
{
return BiomeGeneratorTypeScreens.field_239066_a_;
}
BiomeGeneratorTypeScreens gen = GENERATORS.get(def);
if (gen == null)
{
LOGGER.error("The default world type '{}' has not been added to the GUI. Was it registered too late?", def.getRegistryName());
return BiomeGeneratorTypeScreens.field_239066_a_;
}
return gen;
}
static BiomeGeneratorTypeScreens.IFactory getGeneratorScreenFactory(Optional<BiomeGeneratorTypeScreens> generator, @Nullable BiomeGeneratorTypeScreens.IFactory biomegeneratortypescreens$ifactory)
{
return generator.filter(gen -> gen instanceof GeneratorType)
.map(type -> GENERATOR_SCREEN_FACTORIES.get(((GeneratorType)type).getWorldType()))
.orElse(biomegeneratortypescreens$ifactory);
}
static void registerTypes()
{
ForgeRegistries.WORLD_TYPES.forEach(wt -> {
GeneratorType gen = new GeneratorType(wt);
GENERATORS.put(wt, gen);
BiomeGeneratorTypeScreens.registerGenerator(gen);
});
}
private static class GeneratorType extends BiomeGeneratorTypeScreens
{
private final ForgeWorldType worldType;
public GeneratorType(ForgeWorldType wt)
{
super(wt.getDisplayName());
worldType = wt;
}
public ForgeWorldType getWorldType()
{
return worldType;
}
@Nonnull
@Override
public DimensionGeneratorSettings func_241220_a_(@Nonnull DynamicRegistries.Impl dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest)
{
return worldType.createSettings(dynamicRegistries, seed, generateStructures, bonusChest, "");
}
@Nonnull
@Override
protected ChunkGenerator func_241869_a(@Nonnull Registry<Biome> p_241869_1_, @Nonnull Registry<DimensionSettings> p_241869_2_, long p_241869_3_)
{
return worldType.createChunkGenerator(p_241869_1_, p_241869_2_, p_241869_3_, "");
}
}
}

View file

@ -108,10 +108,33 @@ public class ForgeConfig
.comment("Fix advancement loading to use a proper topological sort. This may have visibility side-effects and can thus be turned off if needed for data-pack compatibility.")
.translation("forge.configgui.fixAdvancementLoading")
.define("fixAdvancementLoading", true);
builder.pop();
}
}
/**
* General configuration that doesn't need to be synchronized but needs to be available before server startup
*/
public static class Common {
public final ForgeConfigSpec.ConfigValue<? extends String> defaultWorldType;
Common(ForgeConfigSpec.Builder builder)
{
builder.comment("General configuration settings")
.push("general");
defaultWorldType = builder
.comment("Defines a default world type to use. The vanilla default world type is represented by 'default'.",
"The modded world types are registry names which should include the registry namespace, such as 'examplemod:example_world_type'.")
.translation("forge.configgui.defaultWorldType")
.define("defaultWorldType", "default");
builder.pop();
}
}
/**
* Client specific configuration - only loaded clientside from forge-client.toml
*/
@ -196,6 +219,15 @@ public class ForgeConfig
}
static final ForgeConfigSpec commonSpec;
public static final Common COMMON;
static {
final Pair<Common, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Common::new);
commonSpec = specPair.getRight();
COMMON = specPair.getLeft();
}
static final ForgeConfigSpec serverSpec;
public static final Server SERVER;
static {

View file

@ -120,6 +120,7 @@ import net.minecraftforge.common.loot.IGlobalLootModifier;
import net.minecraftforge.common.loot.LootModifierManager;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.common.world.BiomeGenerationSettingsBuilder;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.common.world.MobSpawnInfoBuilder;
import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.DifficultyChangeEvent;
@ -879,6 +880,14 @@ public class ForgeHooks
throw new RuntimeException("Mod fluids must override createAttributes.");
}
public static String getDefaultWorldType()
{
ForgeWorldType def = ForgeWorldType.getDefaultWorldType();
if (def != null)
return def.getRegistryName().toString();
return "default";
}
@FunctionalInterface
public interface BiomeCallbackFunction
{

View file

@ -27,14 +27,16 @@ import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.util.SoundEvent;
import net.minecraft.world.storage.IServerConfiguration;
import net.minecraft.world.storage.SaveFormat;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.*;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLModIdMappingEvent;
import net.minecraftforge.fml.event.lifecycle.*;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.fml.loading.progress.StartupMessageManager;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.server.command.EnumArgument;
@ -71,7 +73,6 @@ import net.minecraftforge.common.data.ForgeRecipeProvider;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fml.common.Mod;
@ -118,12 +119,14 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(this::preInit);
modEventBus.addListener(this::gatherData);
modEventBus.addListener(this::loadComplete);
modEventBus.register(this);
ATTRIBUTES.register(modEventBus);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
MinecraftForge.EVENT_BUS.addGenericListener(SoundEvent.class, this::missingSoundMapping);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ForgeConfig.commonSpec);
modEventBus.register(ForgeConfig.class);
// Forge does not display problems when the remote is not matching.
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, ()-> Pair.of(()->"ANY", (remote, isServer)-> true));
@ -154,6 +157,12 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
ArgumentTypes.register("forge:modid", ModIdArgument.class, new ArgumentSerializer<>(ModIdArgument::modIdArgument));
}
public void loadComplete(FMLLoadCompleteEvent event)
{
if (FMLEnvironment.dist == Dist.CLIENT)
ForgeHooksClient.registerForgeWorldTypeScreens();
}
public void serverStopping(FMLServerStoppingEvent evt)
{
WorldWorkerManager.clear();

View file

@ -0,0 +1,121 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.common.world;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StringUtils;
import net.minecraft.util.Util;
import net.minecraft.util.registry.DynamicRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.DimensionType;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistryEntry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ForgeWorldType extends ForgeRegistryEntry<ForgeWorldType>
{
private static final Logger LOGGER = LogManager.getLogger();
public static ForgeWorldType getDefaultWorldType()
{
String defaultWorldType = ForgeConfig.COMMON.defaultWorldType.get();
if (StringUtils.isNullOrEmpty(defaultWorldType) || "default".equals(defaultWorldType))
return null; // use vanilla
ForgeWorldType def = ForgeRegistries.WORLD_TYPES.getValue(new ResourceLocation(defaultWorldType));
if (def == null)
{
LOGGER.error("The defaultWorldType '{}' specified in the forge config has not been registered. The vanilla default generator will be used.", defaultWorldType);
}
return def;
}
private final IChunkGeneratorFactory factory;
public ForgeWorldType(IChunkGeneratorFactory factory)
{
this.factory = factory;
}
public ForgeWorldType(IBasicChunkGeneratorFactory factory)
{
this.factory = factory;
}
public String getTranslationKey()
{
return Util.makeTranslationKey("generator", getRegistryName());
}
public ITextComponent getDisplayName()
{
return new TranslationTextComponent(getTranslationKey());
}
/**
* Called from both the dedicated server and the world creation screen in the client.
* to construct the DimensionGEneratorSettings:
* @return The constructed chunk generator.
*/
public ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return this.factory.createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings);
}
public DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean generateLoot, String generatorSettings)
{
return this.factory.createSettings(dynamicRegistries, seed, generateStructures, generateLoot, generatorSettings);
}
public interface IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings);
default DimensionGeneratorSettings createSettings(DynamicRegistries dynamicRegistries, long seed, boolean generateStructures, boolean bonusChest, String generatorSettings) {
Registry<Biome> biomeRegistry = dynamicRegistries.getRegistry(Registry.BIOME_KEY);
Registry<DimensionType> dimensionTypeRegistry = dynamicRegistries.getRegistry(Registry.DIMENSION_TYPE_KEY);
Registry<DimensionSettings> dimensionSettingsRegistry = dynamicRegistries.getRegistry(Registry.NOISE_SETTINGS_KEY);
return new DimensionGeneratorSettings(seed, generateStructures, bonusChest,
DimensionGeneratorSettings.func_242749_a(dimensionTypeRegistry,
DimensionType.getDefaultSimpleRegistry(dimensionTypeRegistry, biomeRegistry, dimensionSettingsRegistry, seed),
createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed, generatorSettings)));
}
}
public interface IBasicChunkGeneratorFactory extends IChunkGeneratorFactory
{
ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed);
default ChunkGenerator createChunkGenerator(Registry<Biome> biomeRegistry, Registry<DimensionSettings> dimensionSettingsRegistry, long seed, String generatorSettings)
{
return createChunkGenerator(biomeRegistry, dimensionSettingsRegistry, seed);
}
}
}

View file

@ -57,6 +57,7 @@ import net.minecraft.world.gen.surfacebuilders.SurfaceBuilder;
import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
import net.minecraftforge.common.Tags;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.fml.common.registry.GameRegistry;
/**
@ -111,6 +112,7 @@ public class ForgeRegistries
// Custom forge registries
public static final IForgeRegistry<DataSerializerEntry> DATA_SERIALIZERS = RegistryManager.ACTIVE.getRegistry(DataSerializerEntry.class);
public static final IForgeRegistry<GlobalLootModifierSerializer<?>> LOOT_MODIFIER_SERIALIZERS = RegistryManager.ACTIVE.getRegistry(GlobalLootModifierSerializer.class);
public static final IForgeRegistry<ForgeWorldType> WORLD_TYPES = RegistryManager.ACTIVE.getRegistry(ForgeWorldType.class);
public static final class Keys {
//Vanilla
@ -152,6 +154,7 @@ public class ForgeRegistries
//Forge
public static final RegistryKey<Registry<DataSerializerEntry>> DATA_SERIALIZERS = key("data_serializers");
public static final RegistryKey<Registry<GlobalLootModifierSerializer<?>>> LOOT_MODIFIER_SERIALIZERS = key("forge:loot_modifier_serializers");
public static final RegistryKey<Registry<ForgeWorldType>> WORLD_TYPES = key("forge:world_types");
private static <T> RegistryKey<Registry<T>> key(String name)
{

View file

@ -74,6 +74,7 @@ import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
import net.minecraftforge.common.ForgeTagHandler;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.loot.GlobalLootModifierSerializer;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.RegistryEvent.MissingMappings;
import net.minecraftforge.fml.ModContainer;
@ -180,6 +181,7 @@ public class GameData
// Custom forge registries
makeRegistry(DATA_SERIALIZERS, DataSerializerEntry.class, 256 /*vanilla space*/, MAX_VARINT).disableSaving().disableOverrides().addCallback(SerializerCallbacks.INSTANCE).create();
makeRegistry(LOOT_MODIFIER_SERIALIZERS, c(GlobalLootModifierSerializer.class)).disableSaving().disableSync().create();
makeRegistry(WORLD_TYPES, ForgeWorldType.class).disableSaving().disableSync().create();
}
@SuppressWarnings("unchecked") //Ugly hack to let us pass in a typed Class object. Remove when we remove type specific references.
private static <T> Class<T> c(Class<?> cls) { return (Class<T>)cls; }

View file

@ -144,6 +144,7 @@ public net.minecraft.client.gui.ScreenManager func_216911_a(Lnet/minecraft/inven
public net.minecraft.client.gui.ScreenManager$IScreenFactory
protected net.minecraft.client.gui.overlay.DebugOverlayGui field_211537_g # rayTraceBlock
protected net.minecraft.client.gui.overlay.DebugOverlayGui field_211538_h # rayTraceFluid
public net.minecraft.client.gui.screen.WorldOptionsScreen func_239043_a_(Lnet/minecraft/world/gen/settings/DimensionGeneratorSettings;)V # func_239043_a_
protected net.minecraft.client.gui.widget.list.AbstractList$AbstractListEntry field_230666_a_ # list
public net.minecraft.client.particle.ParticleManager func_199283_a(Lnet/minecraft/particles/ParticleType;Lnet/minecraft/client/particle/IParticleFactory;)V # registerFactory
public net.minecraft.client.particle.ParticleManager func_215234_a(Lnet/minecraft/particles/ParticleType;Lnet/minecraft/client/particle/ParticleManager$IParticleMetaFactory;)V # registerFactory

View file

@ -1,3 +1,22 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.client.rendering;
import net.minecraft.client.Minecraft;

View file

@ -0,0 +1,82 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2020.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.world;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.DimensionSettings;
import net.minecraft.world.gen.settings.DimensionGeneratorSettings;
import net.minecraftforge.client.ForgeWorldTypeScreens;
import net.minecraftforge.common.world.ForgeWorldType;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ObjectHolder;
@Mod("forge_world_type_test")
public class ForgeWorldTypeTest
{
@ObjectHolder("forge_world_type_test:test_world_type")
public static ForgeWorldType testWorldType;
public ForgeWorldTypeTest()
{
FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(ForgeWorldType.class, this::registerWorldTypes);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::registerWorldTypeScreenFactories);
}
private void registerWorldTypes(RegistryEvent.Register<ForgeWorldType> event)
{
event.getRegistry().registerAll(
new ForgeWorldType(DimensionGeneratorSettings::func_242750_a).setRegistryName("test_world_type")
);
event.getRegistry().registerAll(
new ForgeWorldType(this::createChunkGenerator).setRegistryName("test_world_type2")
);
}
private ChunkGenerator createChunkGenerator(Registry<Biome> biomes, Registry<DimensionSettings> dimensionSettings, long seed, String settings)
{
return DimensionGeneratorSettings.func_242750_a(biomes, dimensionSettings, seed);
}
private void registerWorldTypeScreenFactories(FMLClientSetupEvent event)
{
ForgeWorldTypeScreens.registerFactory(testWorldType, (returnTo, dimensionGeneratorSettings) -> new Screen(testWorldType.getDisplayName())
{
@Override
protected void init()
{
super.init();
addButton(new Button(0, 0, 120, 20, new StringTextComponent("close"), btn -> {
Minecraft.getInstance().displayGuiScreen(returnTo);
}));
}
});
}
}

View file

@ -95,4 +95,6 @@ license="LGPL v2.1"
[[mods]]
modId="forge_codecs_test"
[[mods]]
modId="render_local_player_test"
modId="render_local_player_test"
[[mods]]
modId="forge_world_type_test"