Jump to content
Search In
  • More options...
Find results that contain...
Find results in...


  • Posts

  • Joined

  • Last visited

  • Days Won


JimiIT92 last won the day on November 7 2017

JimiIT92 had the most liked content!


  • Gender
  • URL
  • Location
  • Personal Text
    Creator of MineWorld mod!

Recent Profile Visitors

3513 profile views

JimiIT92's Achievements

Dragon Slayer

Dragon Slayer (6/8)



  1. I'm facing a strange issue with custom biomes in Forge 1.18. Essentially they do not seem to be generated or be registered at all... This is how I'm registering a biome @Mod.EventBusSubscriber(modid = "test", bus = Mod.EventBusSubscriber.Bus.MOD) public class CommonModEvents { @SubscribeEvent public static void registerOres(FMLCommonSetupEvent event) { event.enqueueWork(BiomeGeneration::registerBiomes); } } public class BiomeGeneration { public static final ResourceKey<Biome> TEST_BIOME = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("test", "test_biome")); public static void registerBiomes() { BiomeDictionary.addTypes(TEST_BIOME, BiomeDictionary.Type.FOREST); BiomeManager.addAdditionalOverworldBiomes(TEST_BIOME); } } And this is the Biome json file. Nothing crazy here, just a Birch Forest json file without Birch trees (just to see if it actually spawns) { "effects": { "mood_sound": { "sound": "minecraft:ambient.cave", "tick_delay": 6000, "block_search_extent": 8, "offset": 2.0 }, "sky_color": 8037887, "fog_color": 12638463, "water_color": 4159204, "water_fog_color": 329011 }, "carvers": { "air": [ "minecraft:cave", "minecraft:cave_extra_underground", "minecraft:canyon" ] }, "features": [ [], [ "minecraft:lake_lava_underground", "minecraft:lake_lava_surface" ], [ "minecraft:amethyst_geode" ], [ "minecraft:monster_room", "minecraft:monster_room_deep" ], [], [], [ "minecraft:ore_dirt", "minecraft:ore_gravel", "minecraft:ore_granite_upper", "minecraft:ore_granite_lower", "minecraft:ore_diorite_upper", "minecraft:ore_diorite_lower", "minecraft:ore_andesite_upper", "minecraft:ore_andesite_lower", "minecraft:ore_tuff", "minecraft:ore_coal_upper", "minecraft:ore_coal_lower", "minecraft:ore_iron_upper", "minecraft:ore_iron_middle", "minecraft:ore_iron_small", "minecraft:ore_gold", "minecraft:ore_gold_lower", "minecraft:ore_redstone", "minecraft:ore_redstone_lower", "minecraft:ore_diamond", "minecraft:ore_diamond_large", "minecraft:ore_diamond_buried", "minecraft:ore_lapis", "minecraft:ore_lapis_buried", "minecraft:ore_copper", "minecraft:underwater_magma", "minecraft:disk_sand", "minecraft:disk_clay", "minecraft:disk_gravel" ], [], [ "minecraft:spring_water", "minecraft:spring_lava" ], [ "minecraft:glow_lichen", "minecraft:forest_flowers", "minecraft:flower_default", "minecraft:patch_grass_forest", "minecraft:brown_mushroom_normal", "minecraft:red_mushroom_normal", "minecraft:patch_sugar_cane", "minecraft:patch_pumpkin" ], [ "minecraft:freeze_top_layer" ] ], "spawners": { "monster": [ { "type": "minecraft:spider", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:zombie", "weight": 95, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:zombie_villager", "weight": 5, "minCount": 1, "maxCount": 1 }, { "type": "minecraft:skeleton", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:creeper", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:slime", "weight": 100, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:enderman", "weight": 10, "minCount": 1, "maxCount": 4 }, { "type": "minecraft:witch", "weight": 5, "minCount": 1, "maxCount": 1 } ], "creature": [ { "type": "minecraft:sheep", "weight": 12, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:pig", "weight": 10, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:chicken", "weight": 10, "minCount": 4, "maxCount": 4 }, { "type": "minecraft:cow", "weight": 8, "minCount": 4, "maxCount": 4 } ], "ambient": [ { "type": "minecraft:bat", "weight": 10, "minCount": 8, "maxCount": 8 } ], "axolotls": [], "underground_water_creature": [ { "type": "minecraft:glow_squid", "weight": 10, "minCount": 4, "maxCount": 6 } ], "water_creature": [], "water_ambient": [], "misc": [] }, "spawn_costs": {}, "precipitation": "rain", "temperature": 0.6, "downfall": 0.6, "category": "forest" } If I try to locate the biome using the /locatebiome test:test_biome it says that it can't find the Biome. Also, if I try to generate a single biome world, the custom biome doesn't even show in the biomes list. What I noticed, in comparison to 1.17, is that the BiomeEntry class essentially is ignoring the weight parameter. This is the 1.17 BiomeEntry class public static class BiomeEntry extends WeighedRandom.WeighedRandomItem { private final ResourceKey<Biome> key; public BiomeEntry(ResourceKey<Biome> key, int weight) { super(weight); this.key = key; } public ResourceKey<Biome> getKey() { return this.key; } } And this is the 1.18 one public static class BiomeEntry { private final ResourceKey<Biome> key; public BiomeEntry(ResourceKey<Biome> key, int weight) { this.key = key; } public ResourceKey<Biome> getKey() { return this.key; } } Also, looking at the BiomeManager class, specifically the getAdditionalOverworldBiomes method, which should be used to attach the mod biomes to the vanilla ones, if you try to look for method usages, in 1.18 it appears that this method is unused. This is what IntelliJ shows if I run the "Find usages" command on this method https://imgur.com/a/r0Fvkjp Where in 1.17 this method is called by the OverworldBiomeSource constructor to attach the mod biomes to the already registered ones public OverworldBiomeSource(long p_48590_, boolean p_48591_, boolean p_48592_, Registry<Biome> p_48593_) { super(java.util.stream.Stream.concat(POSSIBLE_BIOMES.stream(), net.minecraftforge.common.BiomeManager.getAdditionalOverworldBiomes().stream()).map((p_48603_) -> { return () -> { return p_48593_.getOrThrow(p_48603_); }; })); //... } So, am I missing something during the creation of a Biome in 1.18 or there's still something missing on this?
  2. Aaah, I see! I saw that I also need to register the Layer inside the EntityRenderersEvent.RegisterLayers event. Now that I registered the layer and moved the listener to the Mod bus is finally showing 😁 Thank for your tips
  3. Allright, so I got the correct event now, and I'm adding the layer like this @Mod.EventBusSubscriber(modid = MOD_ID, value = Dist.CLIENT) public final class LayerRenderSubscriber { @SubscribeEvent(priority = EventPriority.LOW) public static void renderPlayer(final EntityRenderersEvent.AddLayers event) { LivingEntityRenderer<Player, PlayerModel<Player>> renderer = event.getRenderer(EntityType.PLAYER); BlackElytraLayer<Player, PlayerModel<Player>> layer = new BlackElytraLayer<>(renderer, event.getEntityModels()); renderer.addLayer(layer); } } But the Layer doesn't render at all. Even worse, if I start the game in debug mode, a breakpoint into the event doesn't hit, so it seems like the event isn't even fired. Do I need to register something or do something else that I'm missing?
  4. Oh, I see. So I was listening to the wrong event. But now the problem is getting the first parameter correctly, the RenderLayerParent parameter, which I don't see being referenced by the event (sorry but I've never used this event so I don't know exactly where to look)
  5. I'm trying to add a custom layer to the vanilla player rendering. Specifically, I'm trying to create some custom Elytras. I've already extended the vanilla Elytra Layer, and tried to attach it inside the RenderPlayerEvent.Pre event (which I'm not sure if is the right place, I'm using a 1.16.x code base as reference) @SubscribeEvent public static void renderPlayer(final RenderPlayerEvent.Pre event) { Player player = event.getPlayer(); PlayerRenderer renderer = event.getRenderer(); renderer.addLayer(new BlackElytraLayer<>(renderer, ?)); //? is for the missing EntityModelSet parameter } However, the ElytraLayer requires an EntityModelSet as parameter, to bake the Elytra Model public ElytraLayer(RenderLayerParent<T, M> parent, EntityModelSet modelSet) { super(parent); this.elytraModel = new ElytraModel<>(modelSet.bakeLayer(ModelLayers.ELYTRA)); } But inside the event I see nothing that can get me an instance of this varaiable, leading me to bake the Elytra Model as well. So is there any way to get this or do I just have to recreate the entire Elytra model and use that in the custom layer?
  6. As the tile says, is there any way to add or edit requirements for Vanilla Advancements? For instance, let's say I add a new food to the game. I want that food to be counted into the "A balanced diet" advancement, but of course I want to avoid edit the vanilla json file. So is there any way to add this requirement to the advancement without editing it (similar to how you can add or modify Loot to LootTables using GlobalLootModifiers)?
  7. So essentially I need the RegistryObject just for overworld biomes? For instance, if I have a custom dimension or want to add new Biomes to Nether/End I can just register the key and then handle everything via the Json? I assume this excludes features, so if I want my custom feature to be generated inside the Biome I still need to code it like I'm doing now, right? Just I won't need to add it through code in the BiomeLoadingEvent?
  8. Ok, so adding custom features during the BiomeLoadingEvent (essentialy what I already do for flowers/tree generation) solves the issue. However I'm curious to know more about the json Biomes. Where can I find some details about this system? Will this allow me to add biomes to the game without even writing code (so just the Json file)? I looked on the documentation but found nothing about it
  9. The point is that even without adding the CF to a custom Biome the game crashes However, here is how I create the Biome public static Biome volcanicWasteland() { MobSpawnSettings mobSpawnSettings = new MobSpawnSettings.Builder() .addSpawn(MobCategory.MONSTER, new MobSpawnSettings.SpawnerData(EntityType.MAGMA_CUBE, 100, 2, 5)) .build(); BiomeGenerationSettings.Builder biomeBuilder = new BiomeGenerationSettings.Builder(); addDefaultOverworldUnderground(biomeBuilder); biomeBuilder.surfaceBuilder(MwConfiguredSurfaceBuilders.VOLCANIC_WASTELAND) .addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, Features.DELTA) .addFeature(GenerationStep.Decoration.VEGETAL_DECORATION, Features.SPRING_LAVA_DOUBLE) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_DELTA) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.ORE_MAGMA) .addFeature(GenerationStep.Decoration.UNDERGROUND_DECORATION, Features.SPRING_CLOSED_DOUBLE); //Add custom CF biomeBuilder.addFeature(GenerationStep.Decoration.SURFACE_STRUCTURES, ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS); var temperature = 10.0F; var ashColor = 0x333333; return new Biome.BiomeBuilder() .precipitation(Biome.Precipitation.NONE) .biomeCategory(Biome.BiomeCategory.DESERT) .depth(0.25F) .scale(0.1F) .temperature(temperature) .downfall(0.0F) .specialEffects( new BiomeSpecialEffects.Builder() .waterColor(ashColor) .waterFogColor(ashColor) .fogColor(ashColor) .foliageColorOverride(ashColor) .grassColorOverride(ashColor) .skyColor(calculateSkyColor(temperature)) .ambientParticle(new AmbientParticleSettings(ParticleTypes.WHITE_ASH, 0.118093334F)) .ambientMoodSound(AmbientMoodSettings.LEGACY_CAVE_SETTINGS) .build()) .mobSpawnSettings(mobSpawnSettings) .generationSettings(biomeBuilder.build()) .build(); } which I register on the Biome Registry from the main mod constructor var eventBus = FMLJavaModLoadingContext.get().getModEventBus(); MOD_FEATURES.register(eventBus); MOD_BIOMES.register(eventBus); and here is were I store the Biomes //Registry public static final DeferredRegister<Biome> MOD_BIOMES = DeferredRegister.create(ForgeRegistries.BIOMES, MOD_ID); //Biomes public static final RegistryObject<Biome> VOLCANIC_WASTELAND = register("volcanic_wasteland", BiomeUtils::volcanicWasteland); //Register Biome public static RegistryObject<Biome> register(String name, Supplier<Biome> biomeSupplier) { return REGISTRY.register(name, biomeSupplier); } Finally, during FMLCommonSetupEvent I add the Biome to the BiomeDictionary @SubscribeEvent public static void onCommonSetup(final FMLCommonSetupEvent event) { ... event.enqueueWork(CommonSetupSubscriber::addVolcanicWastelandBiome); } private static void addVolcanicWastelandBiome() { var key = ResourceKey.create(ForgeRegistries.Keys.BIOMES, Objects.requireNonNull(ForgeRegistries.BIOMES).getKey(ModBiomes.VOLCANIC_WASTELAND.get())); BiomeDictionary.addTypes(key, BiomeDictionary.Type.HOT, BiomeDictionary.Type.DRY, BiomeDictionary.Type.WASTELAND, BiomeDictionary.Type.DEAD); BiomeManager.addBiome(BiomeManager.BiomeType.DESERT, new BiomeManager.BiomeEntry(key, 70)); } This is the full debug log I have. I noticed that error is actually thrown by another method (the appleForest method is used to create another mod biome). I guess is called when the Mod feature hasn't been registered yet, so it crashes?
  10. I'm having some troubles creating/attaching a ConfiguredFeature built on top of a modded feature in a modded biome. I had no issues using CF with vanilla features (like Flower placing or Tree placement with mod blocks, for example), however if I want to use my own Feature as well, I get some troubles. What I've done is this: I create the Feature like this // Deferred Register public static final DeferredRegister<Feature<?>> MOD_FEATURES = DeferredRegister.create(ForgeRegistries.FEATURES, MOD_ID); // Feature public static final RegistryObject<Feature<ColumnFeatureConfiguration>> LAVA_ROCK_COLUMNS = register("lava_rock_columns", () -> new LavaRockColumnsFeature(ColumnFeatureConfiguration.CODEC)); //LavaRockColumnsFeature is just a class that extends Feature<ColumnFeatureConfiguration> //to generate basalt columns but with a mod block instead // Register the Feature public static <T extends FeatureConfiguration> RegistryObject<Feature<T>> register(String name, Supplier<Feature<T>> featureSupplier) { return MOD_FEATURES.register(name, featureSupplier); } Then, from the main mod class constructor, I call the register method for the Feature registry var eventBus = FMLJavaModLoadingContext.get().getModEventBus(); MOD_FEATURES.register(eventBus); Next I create my ConfiguredFeatures like this //Generate "Anemone" flowers inside the World public static final ConfiguredFeature<?, ?> ANEMONE = Feature.FLOWER.configured( (new RandomPatchConfiguration.GrassConfigurationBuilder( new SimpleStateProvider(ModBlocks.ANEMONE.get().defaultBlockState()), SimpleBlockPlacer.INSTANCE) ).tries(2).build()) .decorated(Features.Decorators.HEIGHTMAP_SQUARE).count(1); //Generate "Small Lava Rock Columns" in a custom Biome public static final ConfiguredFeature<?, ?> SMALL_LAVA_ROCK_COLUMNS = ModFeatures.LAVA_ROCK_COLUMNS.get() .configured(new ColumnFeatureConfiguration(ConstantInt.of(1), UniformInt.of(1, 4))) .decorated(FeatureDecorator.COUNT_MULTILAYER.configured(new CountConfiguration(4))); Then I register this feature during the FMLCommonSetupEvent by doing this @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) public final class CommonSetupSubscriber { @SubscribeEvent public static void onCommonSetup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { registerConfiguredFeatures(); }); } } private static void registerConfiguredFeatures() { Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "anemone"), ModConfiguredFeatures.ANEMONE); Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(MOD_ID, "small_lava_rock_columns"), ModConfiguredFeatures.SMALL_LAVA_ROCK_COLUMNS); } Even without adding the "Small lava rock" configured feature to the custom Biome, if I run the game, I get this error java.lang.NullPointerException: Registry Object not present: mod_id:lava_rock_columns So I guess the issue is that the ConfiguredFeature is trying to get the Feature from the Registry, but can't find it? So what should be the correct way to register the Feature and/or the Configured Feature?
  11. I've noticed something strange when using commands like /give or /setblock. Essentially the mod blocks and items are kinda ignored by these commands (these two are just an example, but this behaviour happens to all commands in the game). Let me explain: Let's say you have a block in your mod registered as mymod:my_cobblestone_block If you type /give Dev bble, the vanilla Cobblestone block shows in the suggestions list but not the mod blocks. This is because the suggestions look for blocks and items that contains the word you typed in (in this case minecraft:cobblestone contains the word bble) This system only works for mod blocks and items if you type the mod_id first. For example, typing /give Dev mymod:bble will make the my_cobblestone_block appear in the suggestions list. Is there any way to prevent this and make the mod blocks and items appear in the suggestions list even without typing the mod id first?
  12. Alright, so after a whole morning of tries, I finally got it working! Let's say I have this object inside my GLM json { "item": "minecraft:emerald", "chance": 0.0265, "functions": [ { "function": "minecraft:set_count", "count": { "type": "minecraft:uniform", "min": 2.0, "max": 7.0 }, "add": false } ] } where I am saying that the emerald has a 2.65% chacne of being inside the chest loot. But, I want that the stack, if any, must be between 2 and 7 items. Sure I can add my "min" and "max" parameters, but since we already have a function that does this, why not using it? So I added the vanilla set_count function, using the exact same syntax as any vanilla loot table. In the deserializer (the class that extends GlobalLootModifierSerializer) I can read the functions array by doing so var functionsArray = jsonObject.getAsJsonArray("functions"); if(functionsArray != null) { var functions = Deserializers.createFunctionSerializer().create().fromJson(functionsArray, LootItemFunction[].class); } This will return a LootItemFunction array that is the actual list of functions that are specified inside the JSON, correctly deserialized. So we can store these functions and use them when adding the ItemStack to the generated loot, by doing a simple for loop var stack = new ItemStack(item); if(functions != null && !functions.isEmpty()) { functions.forEach(function -> function.apply(stack, context)); } By doing that the function will be applied to the item of the GLM! Of course we are not limited by the set_count, but we can use any vanilla function as we want (I think even custom functions, but I'm not sure about this since I haven't any of these). To correctly serialize said functions, inside the write method, we can use this function Deserializers.createFunctionSerializer().create().toJsonTree(functions) assuming that functions is a variable containing all of the functions previously deserialized
  13. Hi everyone! As the title says, I am wondering if there is a way to use vanilla loot table functions inside a Global Loot Modifier. For instance: I want to add a Sword to the Mineshaft chests and I want this Sword to be randomly enchanted, kinda like vanilla does it to Desert Pyarmid chests or for End Cities. In the first case, this function is called minecraft:enchant_randomly while for End Cities is this one { "function": "minecraft:enchant_with_levels", "levels": { "type": "minecraft:uniform", "min": 20.0, "max": 39.0 }, "treasure": true } Either way, using these functions the Item can sometime be enchanted. How can I make so in a Loot Modifier I can use these functions as well, if is ever possible? I read the doc about Global Item Modifier and of course have seen the GitHub examples. This helped me setting up some Loot Modifiers, which has no issues adding custom items to Vanilla Loot Tables, however I can't seem to find any example or indication about the possibility to use functions inside Loot Modifiers (aside from inserting some custom keywords in the json that if parsed will manually trigger the said function)
  14. Can confirm, I update to the latest version (1.16.3-34.1.16) and it fires
  15. I was saying use the ClientChatReceivedEvent event, but I have a doubt: if a Player send the same exact message what would happen? How can you tell if the message has been sent from a player or not?
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.