Jump to content

JoieNL

Members
  • Posts

    32
  • Joined

  • Last visited

Recent Profile Visitors

2788 profile views

JoieNL's Achievements

Tree Puncher

Tree Puncher (2/8)

2

Reputation

  1. Heya, thanks for the swift reply. Changing the method return value to InteractionResult.sidedSuccess(level.isClientSide) actually resolved the issue somehow. Thanks for pointing out the flags in the Block class too, I was looking for those exactly. Not that I need them anymore, but at least I know where to look now.
  2. Hey y'all, I've been working on a simple farming mod for a while, and I ran into some trouble trying to implement a scythe tool. When the player right-clicks on a crop using the tool, I want that crop and the two adjacent crops (in the direction perpendicular to the player's horizontal view direction) to break. Currently, when I right-click a crop with a scythe, the clicked crop breaks normally but the adjacent crops stay behind as ghost blocks. All three crops do drop their respective loot, however. Interacting with the ghost blocks makes them vanish. Here's my relevant code in the ScytheItem class: My guess is that I should pass some (non-default) integer flag in all the calls to destroyBlock. I can't seem to find what each integer flag does though. Any help would be greatly appreciated!
  3. Alright, I'm an idiot. I was registering my codec in a static initialiser in the biome provider class, meaning it was only registered when the class was loaded (i.e. when creating a world with my custom world type). I moved the registration to common setup and it works fine now.
  4. Hey guys, I've been working on my custom world type lately, and I ran into an issue again. My custom world type is based off of the default world type, but I would like to replace the default fluid used below sea level by compressed ice. I noticed that vanilla defines the default fluid using the DimensionSettings class. I would like to use my custom settings (say "FROZEN_OVERWORLD_SETTINGS") for the NoiseChunkGenerator constructor that I pass to the ForgeWorldType constructor: new ForgeWorldType((biomeRegistry, dimensionSettingsRegistry, seed) -> new NoiseChunkGenerator(new FrozenOverworldBiomeProvider(seed, false, false, biomeRegistry), seed, () -> FROZEN_OVERWORLD_SETTINGS) ) The problem is: I can't instantiate DimensionSettings without using reflection. The constructor is private, the class is final, and there is no builder method. Using reflection seems to work when first creating a world and entering is as long as the client is left running. But after closing the game and rerunning it, I am unable to re-enter the world, instead getting the following error message: [13:07:56] [Render thread/ERROR] [minecraft/SaveFormat]: WorldGenSettings: Unknown registry key: aid:biome_source missed input: {"minecraft:overworld":{generator:{settings:"aid:frozen_overworld",seed:-2783071959927850081L,biome_source:{seed:-2783071959927850081L,large_biomes:0b,type:"aid:biome_source"},type:"minecraft:noise"},type:"minecraft:overworld"}}; Overworld settings missing I know this error message is referring to the registry key I use to register my biome provider codec in my FrozenOverworldBiomeProvider class: Registry.register(Registry.BIOME_PROVIDER_CODEC, new ResourceLocation(MOD_ID, "biome_source"), CODEC); Yet this line seems necessary, because I get this error message when creating a world without the codec being registered: [13:27:33] [Render thread/ERROR] [minecraft/Minecraft]: Error reading worldgen settings after loading data packs: Unknown registry element RecordCodec[UnitDecoder[joienl.world.FrozenOverworldBiomeProvider$$Lambda$4386/249483336@a859c5] * Field[seed: Long] * OptionalFieldCodec[legacy_biome_init_layer: Bool][flatXmapped] * Field[large_biomes: Bool][mapResult OrElse[false]] * RegistryLookupCodec[ResourceKey[minecraft:root / minecraft:worldgen/biome]]] [13:27:33] [Render thread/ERROR] [minecraft/ServerWorldInfo]: WorldGenSettings: Unknown registry element RecordCodec[UnitDecoder[joienl.world.FrozenOverworldBiomeProvider$$Lambda$4386/249483336@a859c5] * Field[seed: Long] * OptionalFieldCodec[legacy_biome_init_layer: Bool][flatXmapped] * Field[large_biomes: Bool][mapResult OrElse[false]] * RegistryLookupCodec[ResourceKey[minecraft:root / minecraft:worldgen/biome]]] I am unable to reload the world at all if I don't register the codec. I just don't know where to look anymore. Any help would be greatly appreciated.
  5. So it took me a few days, but I managed to figure things out myself. First of all, apparently RegistryObject<Biome> fields used with DeferredRegister cannot be referenced directly. When you want to reference your custom biomes, you need to get them from the biome registry itself. This solves the issues I had with the getNoiseBiome method. Secondly, the codec thing. All I had to do to get that working, was to register the codec in a static initialiser in my biome provider class: static { Registry.register(Registry.BIOME_PROVIDER_CODEC, new ResourceLocation(MOD_ID, "biome_source"), CODEC); } I hope this helps anyone trying this for themselves.
  6. Hey y'all, I've been trying my hands at making a new world type lately. This works exactly as it should using the recently added class ForgeWorldType . Now, I want my custom world type to use a set of custom biomes, and this is where I run into trouble. I've copied the code in OverworldBiomeProvider and swapped the entries of the biomes field out for my custom biomes. However, the vanilla biomes spawn like in the Default world type when I generate a world using my custom world type. And for the record: yes, I am passing it into the constructor of ForgeWorldType. I have already located the issue: the getNoiseBiome method in my copied biome provider class uses a lookup registry that always contains the vanilla biomes. How would I go about correctly implementing this method, such that my custom biomes generate instead? And on the subject of implementing biome provider methods, how do I implement the getBiomeProviderCodec method? TL;DR: How do I implement BiomeProvider's abstract methods in my custom biome provider class?
  7. Good thing this forum has people with functional brain cells to compensate for my lack thereof. I was running runClient instead of runData. I'll look into generating the bow model files once I find the time to. If I run into any problems along the way, I'll post them here.
  8. I can't believe I've never seen this Forge test library before, thanks for sharing! I'm still having trouble though. My model provider class listens to GatherDataEvent and the listener is registered to the mod event bus like in the Forge test, but it seems the event never fires. The model provider should spit some "Hello World"s into the console but it never does. Here's the relevant part of my model provider class: public class ModelGenerators { static { System.out.println("Hello World!"); } @SubscribeEvent public static void gatherData(GatherDataEvent event) { System.out.println("Hello World!"); DataGenerator generator = event.getGenerator(); ExistingFileHelper helper = event.getExistingFileHelper(); if (event.includeClient()) { generator.addProvider(new BowModelProvider(generator, helper)); } } } In my main mod class I have added the following line: FMLJavaModLoadingContext.get().getModEventBus().addListener(ModelGenerators::gatherData); What's going wrong here?
  9. Hmm... extending ItemModelProvider seems like the way to go, but how would I implement the registerModels method? The documentation on https://mcforge.readthedocs.io/en/1.16.x/datagen/modelproviders/ is rather concise and there's obviously no vanilla implementations to look at.
  10. Hiya guys, I'm developing a mod that adds, among other things, custom bows and arrows to the game. The different arrows can have different damage output, knockback, velocity, or even special attributes. I would like the player to be able to see which arrow they're using when pulling a bow, as opposed to how vanilla handles things. That is, I want to be able to dynamically add another layer to my bow models depending on the arrow used, without having to write a .json file for every combination of bow, arrow, and pull phase. Now I know that ItemModelsProperties are a thing, but I feel like this is not the right approach. I'm pretty sure I'd have to add overrides for every new arrow type to every new bow type model if I used that. And if I were to add another arrow type, I'd have to change every bow model again. Seems like a lot of unnecessary work. I looked at vanilla's DynamicBucketModel and forge's ItemLayerModel , and these look promising. I'm just not sure how to go about making these bow models in code, and especially where to register them. Could anyone point me in the right direction or provide some relevant documentation/code? Thanks in advance!
  11. You're right, I completely missed that because it's called twice during setup as well and it crashed before I could test stuff in-game. It was stupid of me to assume it wasn't called in-game. I got things working now with a simple nullity check on the world parameter. Thanks for clearing things up!
  12. Hey everyone, I've always been a fan of dynamic items that display useful information like the clock and compass, and I want to make my own take on the clock this time. Instead of having the texture update though, I would like it to display the current day time as a tooltip. Is this possible? From what I've gathered, tooltips are generated whenever an ItemStack is created, and then never touched again. Maybe I can do something with NBT? Hopefully someone can help me out, because I'm rather stuck.
  13. Thanks everyone! I got things working with ease thanks to your help. Here's what my ModItemGroup class looks like now for future reference: public class ModItemGroup extends ItemGroup { private Supplier<ItemStack> displayStack; public static final ModItemGroup ACCESSORIES = new ModItemGroup("accessories", () -> new ItemStack(ModItems.SHACKLE.get())); private ModItemGroup(String label, Supplier<ItemStack> displayStack) { super(label); this.displayStack = displayStack; } @Override public ItemStack createIcon() { return displayStack.get(); } }
  14. Hey y'all, I'm currently working on a mod that adds a bunch of equipable accessories to the game. I've put them all in their own creative tab, which works fine. The only thing I'm stuck on is the icon. I'd like it to be one of the accessories, but this creates a reference loop. I need to supply the custom ItemGroup to the Item when I register it: public static final RegistryObject<Item> SHACKLE = ITEMS.register("shackle", () -> new Item(new Item.Properties().group(ModItemGroup.ACCESSORIES))); But at the same time I need to supply the Item to the custom ItemGroup when I create it: public static final ItemGroup ACCESSORIES = new ItemGroup("accessories") { @Override public ItemStack createIcon() { return new ItemStack(ModItems.SHACKLE.get(); } }; How do I work around this issue? I've tried registering the Shackle without an ItemGroup first, then creating the ItemGroup, and then setting the Shackle's ItemGroup with SHACKLE.get().getCreativeTabs().add(), but this doesn't work either. I'm probably overlooking something really simple, but my brain has just been refusing to work lately. Thanks in advance for any help!
  15. Thanks for the quick reply. I had indeed already had a look at this post and read about the offsetting by (8, 8). But I don't think this is the problem. I believe that vanilla methods like MapGenStructure#generateStructure handle that: int i = (chunkCoord.x << 4) + 8; int j = (chunkCoord.z << 4) + 8; I think things are going wrong because pieces of the structure (and with pieces I mean StructureFrozenNetherBridgePieces.Pieces) are being generated in unloaded chunks when they should not. I believe that pieces that are awaiting generation are stored in StructureFrozenNetherBridgePieces.Start#pendingChildren and generated in MapGenFrozenNetherBridge.Start like such: List<StructureComponent> list = structurefrozennetherbridgepieces$start.pendingChildren; while (!list.isEmpty()) { int i = random.nextInt(list.size()); StructureComponent structurecomponent = list.remove(i); structurecomponent.buildComponent(structurefrozennetherbridgepieces$start, this.components, random); } My hypothesis that somehow all pieces of the structure end up in this list when the first crossing is initialised and everything tries to generate at once. Does anyone know how this could be? Edit: I should've definitely checked this before I made this post... Printing the list after it is initialised reveals that it is always empty of all things: [13:37:16] [Server thread/INFO]: [STDOUT]: [] Does this mean that all the structure pieces generate even before entering this list? It would explain why it remains empty. I will conduct further research regarding this finding. Edit again: I did some more testing and it turns out that this list was empty because things were passing null all over the place. Bottom line is: IntelliJ was trying to be a smartass, replacing this... return isAboveGround(structureboundingbox) && StructureComponent.findIntersecting(p_175882_0_, structureboundingbox) == null ? new StructureFrozenNetherBridgePieces.Straight(p_175882_6_, p_175882_1_, structureboundingbox, p_175882_5_) : null; ...with... return null; ...for every piece. Now that that's solved, the entire structure spawns, but the cascading worldgen lag remains. I'll continue my investigations. I keep having to edit this post: I've 'turned off' all world generation features for my dimension except fortresses, and the cascading worldgen lag is gone. This means that there has been something besides the fortresses causing lag as well. I will now turn all features on again one by one to see if I can determine which of them causes the lag. One last edit: All is well now! I figured out this line was the culprit: this.lavaTrapGen.generate(this.world, this.rand, blockpos.add(this.rand.nextInt(16), this.rand.nextInt(108) + 4, this.rand.nextInt(16))); So I added an (8, 8) offset and things are working fine now! Thanks again for the help jabelar.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.