Goosey
-
Posts
18 -
Joined
-
Last visited
Posts posted by Goosey
-
-
21 hours ago, Luis_ST said:
post updated code
Spoilerpublic static final ResourceKey<Biome> MAPLE_BIOME = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation(GooseMod.MODID, "maple_forest")); private void setup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { BiomeManager.addAdditionalOverworldBiomes(MAPLE_BIOME); }); } @SubscribeEvent(priority = EventPriority.HIGH) public static void onBiomeLoad(BiomeLoadingEvent event) { if (event.getName().equals(MAPLE_BIOME.location())) { event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> ORANGE_MAPLE); event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> RED_MAPLE); event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> YELLOW_MAPLE); } }
-
On 11/12/2021 at 4:09 PM, Luis_ST said:
sorry my mistake, did not see that the tutorial is for 1.16 and ResourceKey#get in 1.17 has been removed
i would recommend you to use the ResourceLocations instead,
one location you can get from the Event the other from your ResourceKey via ResourceKey#locationI've implemented this, but I am still getting errors when trying to add my custom biome
-
12 hours ago, Luis_ST said:
yeah that's correct but you should call ResourceKey#get and not ResourceKey#create
I can't find any method named get in ResourceKey
-
39 minutes ago, Luis_ST said:
Why?
It's what it said to do here. Again it was the only resource I had on this.
-
9 hours ago, Luis_ST said:
also is your FMLCommonSetupEvent fierd?
My FMLCommonSetupEvent is being fired, I've debugged the method call but nothing seems out of the ordinary.
-
I've been trying to implement a custom biome and I've run across an error that crashes my game when trying to create a new world and disallows me to enter any existing worlds.
I followed this tutorial for making biomes (with one or two changes to class names and method names).
My code looks like this
Spoilerpublic static final ResourceKey<Biome> MAPLE_BIOME = ResourceKey.create(Registry.BIOME_REGISTRY, new ResourceLocation(GooseMod.MODID, "maple_forest")); private void setup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { ModWorldGeneration.registerConfiguredFeatures(); BiomeManager.addAdditionalOverworldBiomes(MAPLE_BIOME); }); } @SubscribeEvent(priority = EventPriority.HIGH) public static void onBiomeLoad(BiomeLoadingEvent event) { ResourceKey<Biome> eventBiomeKey = ResourceKey.create(Registry.BIOME_REGISTRY, event.getName()); if (eventBiomeKey == MAPLE_BIOME) { event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> ORANGE_MAPLE); event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> RED_MAPLE); event.getGeneration().getFeatures(GenerationStep.Decoration.VEGETAL_DECORATION).add(() -> YELLOW_MAPLE); } } }
and the exception is this
Spoilerjava.lang.IllegalStateException: Missing: ResourceKey[minecraft:worldgen/biome / goosemod:maple_forest]
at net.minecraft.core.Registry.getOrThrow(Registry.java:476) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading}
at net.minecraft.world.level.biome.OverworldBiomeSource.lambda$new$5(OverworldBiomeSource.java:36) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading}
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[?:?] {}
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[?:?] {}
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625) ~[?:?] {}
at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) ~[?:?] {}
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) ~[?:?] {}
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) ~[?:?] {}
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913) ~[?:?] {}
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?] {}
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682) ~[?:?] {}
at net.minecraft.world.level.biome.BiomeSource.<init>(BiomeSource.java:29) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading}
at net.minecraft.world.level.biome.OverworldBiomeSource.<init>(OverworldBiomeSource.java:34) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading}
at net.minecraft.client.gui.screens.worldselection.WorldPreset$1.generator(WorldPreset.java:36) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading}
at net.minecraft.client.gui.screens.worldselection.WorldPreset.create(WorldPreset.java:166) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.screens.worldselection.CreateWorldScreen.lambda$create$0(CreateWorldScreen.java:120) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at java.util.Optional.map(Optional.java:260) ~[?:?] {}
at net.minecraft.client.gui.screens.worldselection.CreateWorldScreen.create(CreateWorldScreen.java:120) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.screens.worldselection.SelectWorldScreen.lambda$init$4(SelectWorldScreen.java:58) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.components.Button.onPress(Button.java:29) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.components.AbstractButton.onClick(AbstractButton.java:17) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.components.AbstractWidget.mouseClicked(AbstractWidget.java:111) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.components.events.ContainerEventHandler.mouseClicked(ContainerEventHandler.java:28) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.MouseHandler.lambda$onPress$0(MouseHandler.java:87) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.gui.screens.Screen.wrapScreenError(Screen.java:530) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
at net.minecraft.client.MouseHandler.onPress(MouseHandler.java:85) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.client.MouseHandler.lambda$setup$4(MouseHandler.java:181) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at net.minecraft.util.thread.BlockableEventLoop.execute(BlockableEventLoop.java:90) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:accesstransformer:B}
at net.minecraft.client.MouseHandler.lambda$setup$5(MouseHandler.java:180) ~[forge-1.17.1-37.0.104_mapped_official_1.17.1-recomp.jar%2375!:?] {re:classloading,pl:runtimedistcleaner:A}
at org.lwjgl.glfw.GLFWMouseButtonCallbackI.callback(GLFWMouseButtonCallbackI.java:36) ~[lwjgl-glfw-3.2.2.jar%2354!:build 10] {}What exactly am I missing? I understand that the tutorial is for 1.16, but I couldn't find anything for 1.17 and so far it hasn't been that difficult to implement it into my project. Did they add a step in 1.17?
-
I figured it out, thanks.
It turns out I had to use event.getGeneration().addStructureStart() instead of event.getGeneration().getStructures().add() among a few other things like updating my version of forge.
-
2 hours ago, Cratthorax said:
WorldGen you ask? I'd have examples for Decorations, BiomeHandlers, and Features as well. You can refer to post 3 in this thread for some input.
The post you linked is for 1.16, I doubt the code would work for 1.17
-
6 hours ago, Luis_ST said:
show the code of your Structure, if possible via a git repo
The code which utilizes BiomeLoadingEvent I have already shown above but here it is again:
Spoiler@SubscribeEvent(priority = EventPriority.HIGH) public static void registerBiomeModification(BiomeLoadingEvent event) { // custom ore event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES).add(() -> MANHUNT); // add the rv to biomes if (event.getCategory() == Biome.BiomeCategory.DESERT || event.getCategory() == Biome.BiomeCategory.MESA) { event.getGeneration().getStructures().add(() -> RV_CONFIGURED); StringBuilder s = new StringBuilder(); for (Supplier<ConfiguredStructureFeature<?, ?>> feature : event.getGeneration().getStructures()) { s.append(feature.get().feature.getRegistryName()).append(", "); } s.delete(s.length() - 2, s.length()); LOGGER.info("structures in {}: [{}]", event.getName(), s.toString()); } }
This code for the feature is this:
Spoilerpublic class RVFeature extends StructureFeature<NoneFeatureConfiguration> { public RVFeature() { super(NoneFeatureConfiguration.CODEC); } public StructureFeature.StructureStartFactory<NoneFeatureConfiguration> getStartFactory() { return RVFeature.FeatureStart::new; } @Override public GenerationStep.Decoration step() { return GenerationStep.Decoration.SURFACE_STRUCTURES; } @Override public String getFeatureName() { return super.getFeatureName(); } public static class FeatureStart extends StructureStart<NoneFeatureConfiguration> { public FeatureStart(StructureFeature<NoneFeatureConfiguration> p_159550_, ChunkPos p_159551_, int p_159552_, long p_159553_) { super(p_159550_, p_159551_, p_159552_, p_159553_); } public void generatePieces(RegistryAccess registry, ChunkGenerator generator, StructureManager manager, ChunkPos chunkPos, Biome biome, NoneFeatureConfiguration codec, LevelHeightAccessor height) { BlockPos blockpos = new BlockPos(chunkPos.getMinBlockX(), 90, chunkPos.getMinBlockZ()); Rotation rotation = Rotation.getRandom(this.random); RVPiece rvpiece = new RVPiece(manager, RVPiece.STRUCTURE_LOCATION, blockpos, rotation); this.addPiece(rvpiece); } } }
And the code for the structure piece is this:
Spoilerpublic class RVPiece extends TemplateStructurePiece { public static final StructurePieceType RV = StructurePieceType.setPieceId(RVPiece::new, "GMBbRv"); static final ResourceLocation STRUCTURE_LOCATION = new ResourceLocation(GooseMod.MODID, "rv/rv"); public RVPiece(StructureManager manager, ResourceLocation nbt, BlockPos pos, Rotation rotation) { super(RV, 0, manager, nbt, nbt.toString(), makeSettings(rotation, nbt), pos); } public RVPiece(ServerLevel p_162441_, CompoundTag p_162442_) { super(RV, p_162442_, p_162441_, (p_162451_) -> makeSettings(Rotation.valueOf(p_162442_.getString("Rot")), p_162451_)); } private static StructurePlaceSettings makeSettings(Rotation p_162447_, ResourceLocation p_162448_) { return (new StructurePlaceSettings()).setRotation(p_162447_).setMirror(Mirror.NONE).setRotationPivot(new BlockPos(0, 0, 0)).addProcessor(BlockIgnoreProcessor.STRUCTURE_BLOCK); } protected void addAdditionalSaveData(ServerLevel p_162444_, CompoundTag p_162445_) { super.addAdditionalSaveData(p_162444_, p_162445_); p_162445_.putString("Rot", this.placeSettings.getRotation().name()); } protected void handleDataMarker(String p_71260_, BlockPos p_71261_, ServerLevelAccessor p_71262_, Random p_71263_, BoundingBox p_71264_) { if ("chest".equals(p_71260_)) { p_71262_.setBlock(p_71261_, Blocks.AIR.defaultBlockState(), 3); BlockEntity blockentity = p_71262_.getBlockEntity(p_71261_.below()); if (blockentity instanceof ChestBlockEntity) { ((ChestBlockEntity)blockentity).setLootTable(BuiltInLootTables.IGLOO_CHEST, p_71263_.nextLong()); } } } public boolean postProcess(WorldGenLevel p_71250_, StructureFeatureManager p_71251_, ChunkGenerator p_71252_, Random p_71253_, BoundingBox p_71254_, ChunkPos p_71255_, BlockPos p_71256_) { ResourceLocation resourcelocation = new ResourceLocation(this.templateName); StructurePlaceSettings structureplacesettings = makeSettings(this.placeSettings.getRotation(), resourcelocation); BlockPos blockpos1 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(structureplacesettings, new BlockPos(3, 0, 0))); int i = p_71250_.getHeight(Heightmap.Types.WORLD_SURFACE_WG, blockpos1.getX(), blockpos1.getZ()); BlockPos blockpos2 = this.templatePosition; this.templatePosition = this.templatePosition.offset(0, i - 90 - 1, 0); boolean flag = super.postProcess(p_71250_, p_71251_, p_71252_, p_71253_, p_71254_, p_71255_, p_71256_); if (resourcelocation.equals(RVPiece.STRUCTURE_LOCATION)) { BlockPos blockpos3 = this.templatePosition.offset(StructureTemplate.calculateRelativePosition(structureplacesettings, new BlockPos(3, 0, 5))); BlockState blockstate = p_71250_.getBlockState(blockpos3.below()); if (!blockstate.isAir()) { p_71250_.setBlock(blockpos3, Blocks.AIR.defaultBlockState(), 3); } } this.templatePosition = blockpos2; return flag; } }
I mainly took advantage of the many examples in vanilla to make the above two classes
-
20 hours ago, Luis_ST said:
which version of forge do you exactly using 1.17.x.x.x because the first version throws an EOFException
My mod is for minecraft 1.17.1, forge 37.0.67. Should I move my project to 37.0.95?
Quoteyou can use BiomeLoadingEvent instead of Reflection
I utilize BiomeLoadingEvent at line 68 in my code, but that alone did not add structures to the game. I also had to use reflection to add my own StructureFeatureConfiguration.
-
A long time ago I tried to make a Minecraft mod (key word is tried). I knew a lot less about Java back then and I mainly relied on the tutorial videos I found. Recently I decided to try and get back into it, and I found it was really fun! I've started doing things that I had no chance of figuring out how to do last time like implementing custom mobs and even bosses. The biggest problem is that there are close to no tutorials or any actual useful documentation for forge 1.17.1, but because of my increased skill level since my last modding attempt, I haven't had to rely on tutorials that much
I recently started trying to add custom entity spawning to the game, but couldn't figure out how to do it in the current forge version. Eventually I just decided to use reflection to add my own data into the vanilla map of "spawners" in net.minecraft.world.level.biome.MobSpawnSettings. This obviously isn't the intended way to add custom entity spawning to the game but because I can't find anything on this subject online, I did it and it works. Entity spawning isn't the main subject of this post, but it gives you the backstory of what I'm about to do (or more specifically, what I did).
After that, I wanted to add my own custom structure. I decided to add an RV that spawns in deserts and mesa biomes so I just looked at how vanilla adds structures.
I created all the proper java classes for the structure itself (The Feature class and the Pieces class) and created a StructureFeature field and a ConfiguredStructureFeature from that Feature. Then in a similar fashion to what I did with the entities, In biomes I wanted my structure to spawn in, I added my ConfiguredStructureFeature to "structureStarts" in net.minecraft.world.level.biome.BiomeGenerationSettings using reflection.
On top of that I also added my own StructureFeatureConfiguration to "BUILTIN_OVERWORLD" from net.minecraft.world.level.levelgen.NoiseGeneratorSettings.
If you're wondering, it works... kind of
When I create a new world, It will spawn the structures but after I exit that world it will take a long time to load the world and there are many EOFExceptions in the console. I did the best job I could do with debugging and found that the error was happening while loading the NBT data for structures in every chunk. It is having a lot of trouble when trying to do something having to do with structure references. I have done my best to try and see exactly what is going wrong in the code and how I can fix it, but frankly, I'm stumped and I have no idea of how to fix it. Honestly the way to fix it is probably to stop using reflection and to just properly register my structures, but I don't know how to do that. After I've exhausted every single solution I can think of, I finally decided to come here and ask for help.
My code for world generation:
Spoilerpublic class ModWorldGeneration { public static ImmutableList<OreConfiguration.TargetBlockState> MANHUNT_TARGET_LIST; public static ConfiguredFeature<?, ?> MANHUNT; public static StructureFeature<NoneFeatureConfiguration> RV_FEATURE = (StructureFeature<NoneFeatureConfiguration>) new RVFeature().setRegistryName("rv"); public static ConfiguredStructureFeature<NoneFeatureConfiguration, ? extends StructureFeature<NoneFeatureConfiguration>> RV_CONFIGURED; @Mod.EventBusSubscriber(modid = GooseMod.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE) public static class ForgeBus { private static final Logger LOGGER = LogManager.getLogger(); public static void registerConfiguredFeatures() { // IGNORE NAMES MANHUNT_TARGET_LIST = ImmutableList.of(OreConfiguration.target(OreConfiguration.Predicates.NATURAL_STONE, ModBlocks.MANHUNT.defaultBlockState()), OreConfiguration.target(OreConfiguration.Predicates.STONE_ORE_REPLACEABLES, ModBlocks.MANHUNT.defaultBlockState())); MANHUNT = (ConfiguredFeature) ((ConfiguredFeature) ((ConfiguredFeature) Feature.ORE.configured(new OreConfiguration(MANHUNT_TARGET_LIST, 8)).rangeUniform(VerticalAnchor.absolute(16), VerticalAnchor.absolute(32))).squared()).count(31); Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, new ResourceLocation(GooseMod.MODID, "manhunt"), MANHUNT); // rv RV_CONFIGURED = RV_FEATURE.configured(NoneFeatureConfiguration.INSTANCE); LOGGER.info("RV_FEATURE: {}", RV_CONFIGURED); } @SubscribeEvent(priority = EventPriority.HIGH) public static void registerBiomeModification(BiomeLoadingEvent event) { // custom ore event.getGeneration().getFeatures(GenerationStep.Decoration.UNDERGROUND_ORES).add(() -> MANHUNT); // add the rv to biomes if (event.getCategory() == Biome.BiomeCategory.DESERT || event.getCategory() == Biome.BiomeCategory.MESA) { event.getGeneration().getStructures().add(() -> RV_CONFIGURED); StringBuilder s = new StringBuilder(); for (Supplier<ConfiguredStructureFeature<?, ?>> feature : event.getGeneration().getStructures()) { s.append(feature.get().feature.getRegistryName()).append(", "); } s.delete(s.length() - 2, s.length()); LOGGER.info("structures in {}: [{}]", event.getName(), s.toString()); } } } @Mod.EventBusSubscriber(modid = GooseMod.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) public static class ModBus { private static final Logger LOGGER = LogManager.getLogger(); @SubscribeEvent public static void loadComplete(FMLLoadCompleteEvent event) { // just logging here StringBuilder s1 = new StringBuilder(); boolean print1 = false; for (StructureFeature<?> feature : ForgeRegistries.STRUCTURE_FEATURES.getValues()) { print1 = true; s1.append(feature.getRegistryName()).append(", "); } if (print1) { s1.delete(s1.length() - 2, s1.length()); LOGGER.info("All structure features: [{}]", s1.toString()); } LOGGER.info(ForgeRegistries.STRUCTURE_FEATURES.getValues()); // loop over biomes for (Biome biome : ForgeRegistries.BIOMES) { // rv biome if (biome.getBiomeCategory() == Biome.BiomeCategory.DESERT || biome.getBiomeCategory() == Biome.BiomeCategory.MESA) { // override structure starts try { Field field = BiomeGenerationSettings.class.getDeclaredField("structureStarts"); field.setAccessible(true); List<Supplier<ConfiguredStructureFeature<?, ?>>> oldStructures = (List<Supplier<ConfiguredStructureFeature<?, ?>>>) field.get(biome.getGenerationSettings()); List<Supplier<ConfiguredStructureFeature<?, ?>>> newStructures = new ArrayList<>(); for (Supplier<ConfiguredStructureFeature<?, ?>> structure : oldStructures) { newStructures.add(structure); } newStructures.add(() -> RV_CONFIGURED); field.set(biome.getGenerationSettings(), newStructures); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } // logging stuff here StringBuilder s = new StringBuilder(); boolean print = false; for (Supplier<ConfiguredStructureFeature<?, ?>> feature : biome.getGenerationSettings().structures()) { print = true; s.append(feature.get().feature.getRegistryName()).append(", "); } if (print) { s.delete(s.length() - 2, s.length()); LOGGER.info("structures in {}:\n [{}]", biome.getRegistryName(), s.toString()); } // lemur biome if (biome.getBiomeCategory() == Biome.BiomeCategory.JUNGLE) { // spawn lemurs try { // make spawn settings accessible Field field = MobSpawnSettings.class.getDeclaredField("spawners"); field.setAccessible(true); // get current spawn settings Map<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>> oldSpawners = (Map<MobCategory, WeightedRandomList<MobSpawnSettings.SpawnerData>>) field.get(biome.getMobSettings()); // create a new list of old spawn settings plus the ones we want to add Map<MobCategory, ArrayList<MobSpawnSettings.SpawnerData>> newSpawners = new HashMap<>(); // add old spawn settings to list for (MobCategory category : oldSpawners.keySet()) { newSpawners.put(category, Lists.newArrayList(oldSpawners.get(category).unwrap())); } // add new spawn settings newSpawners.get(MobCategory.AMBIENT).add(new MobSpawnSettings.SpawnerData(ModEntityTypes.LEMUR, 100, 5, 10)); // replace old spawner settings list field.set(biome.getMobSettings(), newSpawners.entrySet().stream().collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, (list) -> WeightedRandomList.create(list.getValue())))); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } // add rv to vanilla overworld try { Field field = NoiseGeneratorSettings.class.getDeclaredField("BUILTIN_OVERWORLD"); field.setAccessible(true); NoiseGeneratorSettings BUILTIN_OVERWORLD = (NoiseGeneratorSettings) field.get(null); // I don't know what I should actually make the salt so imma just pick 15000000 BUILTIN_OVERWORLD.structureSettings().structureConfig().put(RV_FEATURE, new StructureFeatureConfiguration(32, 8, 15000000)); } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } }
-
21 hours ago, Luis_ST said:
You need to add a PanicGoal to the Entities, look how the existing Goal work
Yes but how do I make all nearby entities start panicking
-
I'm making a mob like zombified piglin except instead of all the mobs getting mad at you I want to make it do they all go into a panic.
How can I do this?
-
I fixed it by making a liquidblock for the fluid, which I didn't do (correctly).
Additionaly, I made the class extend FlowingFluid instead of ForgeFlowingFluid.
-
I made a model for an custom entity in blockbench but the code that blockbench generated didn't work for 1.17.1
My question is how do you model and render an entity in 1.17.1
There aren't a lot of tutorials out there for forge 1.17.1 which is why I ask here
-
public abstract class NitroglycerinFluid extends ForgeFlowingFluid { // Directly reference a log4j logger. private static final Logger LOGGER = LogManager.getLogger(); protected NitroglycerinFluid(Properties properties) { super(properties); } public static Properties createProperties() { return new Properties(() -> ModFluids.NITROGLYCERIN, () -> ModFluids.FLOWING_NITROGLYCERIN, FluidAttributes.builder(new ResourceLocation("sussybakaplus:block/nitroglycerin_still"), new ResourceLocation("sussybakaplus:block/nitroglycerin_flow")).overlay(new ResourceLocation("sussybakaplus:block/nitroglycerin_overlay")).density(3000).viscosity(1000).luminosity(15).temperature(1300)).tickRate(1).canMultiply().bucket(() -> ModItems.NITROGLYCERIN_BUCKET).block(() -> ModBlocks.NITROGLYCERIN); } @Override public boolean isSource(FluidState state) { return false; } @Override public int getAmount(FluidState state) { return state.getValue(LEVEL); } public void animateTick(Level p_76445_, BlockPos p_76446_, FluidState p_76447_, Random p_76448_) { LOGGER.info("animate"); if (!p_76447_.isSource() && !p_76447_.getValue(FALLING)) { if (p_76448_.nextInt(64) == 0) { p_76445_.playLocalSound((double)p_76446_.getX() + 0.5D, (double)p_76446_.getY() + 0.5D, (double)p_76446_.getZ() + 0.5D, SoundEvents.WATER_AMBIENT, SoundSource.BLOCKS, p_76448_.nextFloat() * 0.25F + 0.75F, p_76448_.nextFloat() + 0.5F, false); } } else if (p_76448_.nextInt(10) == 0) { p_76445_.addParticle(ParticleTypes.UNDERWATER, (double)p_76446_.getX() + p_76448_.nextDouble(), (double)p_76446_.getY() + p_76448_.nextDouble(), (double)p_76446_.getZ() + p_76448_.nextDouble(), 0.0D, 0.0D, 0.0D); } } @Nullable public ParticleOptions getDripParticle() { return ParticleTypes.DRIPPING_WATER; } @Override protected void beforeDestroyingBlock(LevelAccessor accessor, BlockPos pos, BlockState state) { BlockEntity blockentity = state.hasBlockEntity() ? accessor.getBlockEntity(pos) : null; LOGGER.info("spread to " + state.getBlock().getRegistryName().toString()); if (state.getBlock().getRegistryName().getPath().equals("fire")) { float f = 4.0F; Minecraft.getInstance().level.explode(null, pos.getX(), pos.getY(), pos.getZ(), f, Explosion.BlockInteraction.BREAK); } //Block.dropResources(state, accessor, pos, blockentity); } @Override public void tick(Level level, BlockPos pos, FluidState state) { //super.tick(level, pos, state); LOGGER.info("tick"); if (this.hasBurningNeighbors(level, pos)) { LOGGER.info("EXPLODING!!!"); float f = 4.0F; level.explode(null, pos.getX(), pos.getY(), pos.getZ(), f, Explosion.BlockInteraction.BREAK); } else { LOGGER.info(pos.toShortString() + " doesn't have any buring neighbors"); } } private boolean hasBurningNeighbors(LevelReader levelReader, BlockPos pos) { for(Direction direction : Direction.values()) { if (this.isBurning(levelReader, pos.relative(direction))) { return true; } } return false; } private boolean isBurning(LevelReader levelReader, BlockPos pos) { return (pos.getY() < levelReader.getMinBuildHeight() || pos.getY() >= levelReader.getMaxBuildHeight() || levelReader.hasChunkAt(pos)) && levelReader.getBlockState(pos).isBurning(levelReader, pos); } protected float getExplosionResistance() { return 0.0F; } public int getTickDelay(LevelReader p_76226_) { return p_76226_.dimensionType().ultraWarm() ? 1 : 1; } protected boolean isRandomlyTicking() { return true; } public Optional<SoundEvent> getPickupSound() { return Optional.of(SoundEvents.BUCKET_FILL); } }
My Fluid Class
-
I've made a simple custom fluid which overrides it's tick method in order to run some checks for any nearby burning blocks. Using the debugger and some breakpoints, I'm able to see that while the tick method for FlowingFluid is being run, my method which overrides that one isn't.
[1.17.1] Error when creating custom biome
in Modder Support
Posted
https://github.com/NotAFlyingGoose/GooseMod