-
Posts
117 -
Joined
-
Last visited
-
Days Won
1
Everything posted by Cratthorax
-
Don't be silly. A script kiddie is capable of basic copy pasting. I can't even do that. However, one more thing to add. How do you connect the registered FlowingFluidBlock, to your actual FluidBlock.class? I wasn't aware that you can actually customize the FlowingFluidBlock RegistryObject(or any other RegistryObject in that regard). Do it like that, and take info from the vanilla FluidBlocks how to build your FluidBlock.class accordingly: Change that... public static final RegistryObject<FlowingFluidBlock> OIL_BLOCK = MatLibRegister.BLOCKS.register("crudeoil", () -> new FlowingFluidBlock(() -> MatLibFluidOil.OIL_FLUID.get(), AbstractBlock.Properties.create(MATOIL) .doesNotBlockMovement().hardnessAndResistance(100f).noDrops())); ...to that... public static final RegistryObject<MyCustomFluidBlock> OIL_BLOCK = MatLibRegister.BLOCKS.register("crudeoil", () -> new MyCustomFluidBlock(() -> MatLibFluidOil.OIL_FLUID.get(), AbstractBlock.Properties.create(MATOIL) .doesNotBlockMovement().hardnessAndResistance(100f).noDrops())); ...and name your FluidBlock MyCustomFluidBlock.class. As far as I understand you do not want to extend to FlowableFluidBlock, but to FlowableFluid. I've yet to understand why, because in the past a fluid block, was still a block. It seems like it is now an "in between" thingy, or no longer a block at all. I hope someone of the wizards can spread some wisdom on that? And if it's just to ease the tinkering...👍 Edit: If someone wants more learning material, I'd recommend the TechReborn FlowableFluid.class, and their actual Fluid.class(Fabric only, so lots of adaptions needed, but good for getting an idea of structure), or PneumaticCraft(Forge). Notice they seem to be on 1.16.5 or even 1.17.1, but the code is compiling fine and dandy with minor adaptions(for 1.17.1 only?). You'd quickly find traces on how to "adapt" by highlighting methods/fields/etc., and open the declaration. Trouble starts really if references aren't public, because then you have to @Override in a custom.class. Which is something I've yet to learn as well. In the past, for 1.7(yes, that's 2013), it looked something like that:
-
Ok so, this is going to be a long one. This will show you(probably in a ugly, hacky way), how to spawn your custom fluid in patches of custom lakes in worldGen for 1.16.4. It may as well work for 1.16-1.16.5. But don't nail me on this one. Notice that all terminology and labels containing the words oil, or crudeoil, can very well be anything you want. Be sure to first do the tutorial I posted upside, or find your individual way of creating a custom fluid. This will also have the bucketItem covered you'd need to pick up your customFluid. What you need for the DataPack(click the links for code on pastebin, the .meta files basically just contain one column handling animation frames, search online for how to do this, it's really easy): assets/yourmod/blockstate/crudeoil.json, assets/yourmod/lang/en_us.json, assets/yourmod/models/block/crudeoil.json, assets/yourmod/textures/fluid/oil_flow.png; oil_flow.png.meta; oil_overlay.png; oil_still.png; oil_still.png.meta, assets/yourmod/worldgen/configured_feature/lake_oil.json Now the actual .java code: In your main file register the DECORATORS and FEATURES with a modBus, the worldGen clientside with an event.enqueueWork(), and the onBiomeLoading event with a forgeBus. It should look something like this: @Mod(MatLibMain.MODID) public class MatLibMain { public static final String MODID = "matlib"; public static final String ModName = "Material Library"; public static final String VersionMajor = "0"; public static final String VersionMinor = "4"; public static final String VersionPatch = "0"; public static final String BuildVersion = VersionMajor + "." + VersionMinor + "." + VersionPatch; public static final String MinecraftVersion = "1.16.4"; public MatLibMain() { // Register the setup method for modloading IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); IEventBus forgeBus = MinecraftForge.EVENT_BUS; MatLibRegister.register(eventBus); MatLibFluids.register(eventBus); MatLibRegister.DECORATORS.register(eventBus); MatLibRegister.FEATURES.register(eventBus); eventBus.addListener(this::setup); // Register the enqueueIMC method for modloading eventBus.addListener(this::enqueueIMC); // Register the processIMC method for modloading eventBus.addListener(this::processIMC); // Register the doClientStuff method for modloading eventBus.addListener(this::doClientStuff); // Register ourselves for server and other game events we are interested in MinecraftForge.EVENT_BUS.register(this); forgeBus.addListener(EventPriority.HIGH, MatLibWorldGen::onBiomeLoading); } private void doClientStuff(final FMLClientSetupEvent event) { event.enqueueWork(() -> { MatLibWorldGen.registerConfiguredFeatures(); RenderTypeLookup.setRenderLayer(MatLibFluids.OIL_FLUID.get(), RenderType.getTranslucent()); RenderTypeLookup.setRenderLayer(MatLibFluids.OIL_BLOCK.get(), RenderType.getTranslucent()); RenderTypeLookup.setRenderLayer(MatLibFluids.OIL_FLOWING.get(), RenderType.getTranslucent()); }); } ==================================================here is a code break========================================================= The register can happen in your main file as well, but I do it inside a dedicated MatLibRegister.class. //decorators public static final DeferredRegister<Placement<?>> DECORATORS = DeferredRegister.create(ForgeRegistries.DECORATORS, MatLibMain.MODID); public static final RegistryObject<MatLibLakePlacement> OIL_DECO = registerDeco("oil_deco", () -> new MatLibLakePlacement(ChanceConfig.CODEC)); private static <T extends Placement<?>> RegistryObject<T> registerDeco(final String name, final Supplier<T> sup) { return DECORATORS.register(name, sup); } //features public static final DeferredRegister<Feature<?>> FEATURES = DeferredRegister.create(ForgeRegistries.FEATURES, MatLibMain.MODID); public static final RegistryObject<Feature<BlockStateFeatureConfig>> OIL_FEAT = registerFeat("oil_feat", MatLibLakeFeature::new); private static <T extends Feature<?>> RegistryObject<T> registerFeat(String name, final Supplier<T> sup) { return FEATURES.register(name, sup); } The MatLibLakeFeature.class: public class MatLibLakeFeature extends LakesFeature { public MatLibLakeFeature() { super(BlockStateFeatureConfig.field_236455_a_); } @Override public boolean generate(ISeedReader level, ChunkGenerator generator, Random rand, BlockPos pos, BlockStateFeatureConfig config) { return super.generate(level, generator, rand, pos, config); } } The MatLibLakePlacement.class: public class MatLibLakePlacement extends Placement<ChanceConfig> { public static int genChance = 100; public MatLibLakePlacement(Codec<ChanceConfig> codec) { super(codec); } @Override public Stream<BlockPos> getPositions(WorldDecoratingHelper helper, Random rand, ChanceConfig chanceConfig, BlockPos pos) { if (rand.nextInt(100) < chanceConfig.chance) { int x = rand.nextInt(16) + pos.getX(); int z = rand.nextInt(16) + pos.getZ(); int y = rand.nextInt(rand.nextInt(helper.func_242891_a() - + 8); // sea level check to reduce random placement chance if (y < helper.func_242895_b() || rand.nextInt(100) < genChance) { return Stream.of(new BlockPos(x, y, z)); } } return Stream.empty(); } } And last but not least, the MatLibWorldGen.class: public class MatLibWorldGen { public static ConfiguredFeature<?,?> OIL_LAKES; public static void registerConfiguredFeatures() { Registry<ConfiguredFeature<?, ?>> registry = WorldGenRegistries.CONFIGURED_FEATURE; OIL_LAKES = MatLibRegister.OIL_FEAT.get() .withConfiguration(new BlockStateFeatureConfig(MatLibFluids.OIL_BLOCK.get().getDefaultState())) .withPlacement(MatLibRegister.OIL_DECO.get().configure(new ChanceConfig(100))); Registry.register(registry, RL("oil_lakes"), OIL_LAKES); } public static ResourceLocation RL(String path) { return new ResourceLocation(MatLibMain.MODID, path); } @SubscribeEvent(priority = EventPriority.HIGHEST) public static void onBiomeLoading(final BiomeLoadingEvent event) { event.getGeneration().withFeature(GenerationStage.Decoration.LAKES, OIL_LAKES); } } If you have questions, ask right away. Also, make sure to keep the names of the .class files, unless you know how to change and how to fix the refactorings you did. Oh yeah, and the fluid.class according to the video. Make sure to register in your main/register-file, and don't forget the DataPack for your bucketitem.: public class MatLibFluids { public static final ResourceLocation OIL_STILL_RL = new ResourceLocation("fluid/oil_still"); public static final ResourceLocation OIL_FLOWING_RL = new ResourceLocation("fluid/oil_flow"); public static final ResourceLocation OIL_OVERLAY_RL = new ResourceLocation("fluid/oil_overlay"); public static final DeferredRegister<Fluid> FLUIDS = DeferredRegister.create(ForgeRegistries.FLUIDS, MatLibMain.MODID); public static final RegistryObject<FlowingFluid> OIL_FLUID = FLUIDS.register("oil_fluid", () -> new ForgeFlowingFluid.Source(MatLibFluids.OIL_PROPERTIES)); public static final RegistryObject<FlowingFluid> OIL_FLOWING = FLUIDS.register("oil_flowing", () -> new ForgeFlowingFluid.Flowing(MatLibFluids.OIL_PROPERTIES)); public static final ForgeFlowingFluid.Properties OIL_PROPERTIES = new ForgeFlowingFluid.Properties( () -> OIL_FLUID.get(), () -> OIL_FLOWING.get(), FluidAttributes.builder(OIL_STILL_RL, OIL_FLOWING_RL) .density(800).temperature(300).viscosity(10000).sound(SoundEvents.ITEM_HONEY_BOTTLE_DRINK).overlay(OIL_OVERLAY_RL) .color(0xff000000)).slopeFindDistance(2).levelDecreasePerBlock(2).tickRate(45) .block(() -> MatLibFluids.OIL_BLOCK.get()).bucket(() -> MatLibRegister.BUCKETOIL.get()); public static class Source extends ForgeFlowingFluid.Source { public Source() { super(OIL_PROPERTIES); } public int getTickDelay(IWorldReader world) { return 20; } } public static final RegistryObject<FlowingFluidBlock> OIL_BLOCK = MatLibRegister.BLOCKS.register("crudeoil", () -> new FlowingFluidBlock(() -> MatLibFluids.OIL_FLUID.get(), AbstractBlock.Properties.create(Material.WATER) .doesNotBlockMovement().hardnessAndResistance(100f).noDrops())); public static void register(IEventBus eventBus) { FLUIDS.register(eventBus); } }
-
I disagree. A coder is someone doing what you just said on a professional level. I'm not a professional. But I get things working, even if it doesn't look nice, and takes ages. By that I'd label me an endurant tinkerer...:D You may as well just close this thread, as I figured how to solve my fluid/lake/worldGen problem as well. For anyone interested, it basically also covers the issue I had posted inside here: How to make a fluid, and spawn in it worldGen(without building an object.class)
-
@Sieben, always a charming...:D I already made clear that I'm not a coder, but a mod building hacker. The reason for this has been stated as well. Limited time and other obligations. I do hear you though, once I get to be a pensioner, and have the time to spend all my focus on coding Java....in like 20 years from now. However. The correct answer would have been: "You can either define object.class logic/properties in the place you are doing the register, OR you can do it in the object.class, and then refer to this object.class in your register method. You can't do both, because they are two different objects.". Sure it does. The underlying problem was, and still is, I'm used to 2013/2015 code, and 2021 is far away from that. I have to accept that starting from all over would have been the better solution when I started. But now that I've done so much "conversion work" already, I might have done things more complicated than they need to be.
-
I'm sorry, but you guys seem to understand my problem just as much as I understand the technical details you're directing me at. What you said @Sieben is not my problem. My problem is, I, somehow managed to create a custom object(regardless of being block, item, or fluid, or whatever) without using an actual item./block./fluid.class. And I fail at connecting a(n) item/block/fluid.class to the registered version of my already existing object. Hence why I'm asking which name I need to give the .class object in order to make the registered object use the .class's logic? So again, if I have my registered object: public static final RegistryObject<Item> GRAVELANTIMONY = ITEMS.register("gravelantimony", () -> new Item( new Item.Properties().group(MATLIB_GROUP))); And I have my item.class which is named ItemGravelAntimony.java, and use the naming method posted downside, inside the item.class, why does the registered item not make use of the actual item.class? public ItemGravelAntimony(String name){ this(name, MatLibMain.MODID, "item/" + "gravelantimony"); }
-
Found the tutorial. Please don't judge me. The guy just presented a very convenient and easy way to implement fluids.
-
So I just followed this tutorial, which I can't even find any longer, about creating fluids. The very cool thing about the whole tutorial was that I could easily do this inside a single file. Don't ask me why, but I hate spreading it all over the place. The .class looks like this:
-
Yeah. Obviously I had the details mixed up. Forgive me, as I am still in a state of confusion about the whole DataPack way of doing things. But I get to understand a bit more every week. So, if I have registered my item like this: public static final RegistryObject<Item> GRAVELANTIMONY = ITEMS.register("gravelantimony", () -> new Item( new Item.Properties().group(MATLIB_GROUP))); Which would be the correct naming for the corresponding item.class? The one with the capital letters, or the non capital letters? The DataPacks are referring to the one with non capital inside the strings, but the actual .json files have the corresponding object type as starting name convention, like this f.e: blockantimony itemgravelantimony fluidcrudeoil etc. etc. etc. Oh wait. The actual item.class is supposed to have the same naming convention as the DataPack name declaration, right? Edit: shit's going to get even more confused now, since I just last week started to implement custom fluids. But I'm gonna make a new thread for this.
-
Good day, I'm trying to get a second mod running from inside the run/mods folder, when ever I would test my current project. For one I'm trying to make my current project based on one of my library's, second, since I would spawn an awful lot of new blocks during world creation, I would use a X-Ray mod in the past, in order to quickly verify my ore spawn is actually working. Unfortunately I can't get any of the already compiled mods running from inside the run/mods folder. I remember this was perfectly possible in the past.
-
Well, me neither English. So language barriers are indeed a problem sometimes. The above code I posted is sitting inside my registry.class, where I register all blocks/items. I combine this with DataPacks to create the items/blocks via .json. Now @Sieben said you can't do all you want inside the DataPacks, that you could do inside a "regular" item.class. But since the registry method already does what I had done inside the item.class in the past, I'm asking if all methods that I would use in the item.class are useable in the registry method properties as well?
-
Ok. I was about to say "wtf!" since you two guys were just recommending to me 2 weeks ago, or so, to do items/blocks via DataPacks. So if I use the same ID that I'm using for said item/block in my registerMain.class, will it refer to the corresponding item/block.class? Because I'm already using that kind of code structure in my registry for items/blocks:
-
Ok. So how do I connect the ItemFood.class to already existing items imported via DataPacks then? I assumed this would happen automatically when using the same internal name, but it didn't. I tried this already 3 times, but failed miserably. Then I got annoyed because I'd failed at something(supposedly) so trivial, and never tried again.
-
Hello, as by title. I'd experience a pretty strange and random bug, that, at one point, I can no longer harvest any blocks when in survival mode. Once the bug occurs, it would also prevent me from saving my world, and forcing me to end the game via task bar. There is no crash log, nor is there anything special happening inside the standard logs, that would hint me to said bug. I've googled the issue, and while it seems to happen quite often, there was no solution to be found anywhere. I suspect Optifine, but that's just a shot in the dark.
-
Good morning, now with the new Data Pack system in place, I'd like to address a couple of things. 1. is there a comprehensive list of things to do with DataPacks vs item.class? 2. which of the two, code wise, is more efficient/resource friendly? 3. Can you bake any item.class property to the register method? In special, I'd like to comprehend how to define an item as FoodItem in the DataPack? This doesn't seem to be covered on any of the MC Wiki's?
-
[1.16.4]Items don't appear in alphabetical order in custom menu
Cratthorax replied to Cratthorax's topic in Modder Support
Yeah, thanks for the help. Googling I found traces of custom item groups. But again, I would always search for methods with very low scope to prevent code bloat. I'd end up most of the time developing something myself, which usually takes ages. As stated before in another thread, it's quite hard to cover all the cross references specially if you're working with a huge project. Just a couple of links to give the thread purpose, if anyone shows up here googling for the same problem. They didn't conveniently fixed the issue I was having, which turned out to be a non issue. -
[1.16.4]Items don't appear in alphabetical order in custom menu
Cratthorax replied to Cratthorax's topic in Modder Support
Oups. Happily ignore this. Obviously it's baken in to the world save. Starting a new world will fix it. -
Good morning, as by title, I made sure all objects and related content(textures, database files, registry etc.) are sorted alphabetically, yet they randomly do not appear in the menu like that. I would use terminology like this, to make sure I would also get a sorting by item type: ...gravelantimony, gravelcopper, gravelgold...gravelroastedantimony, gravelroastedcopper, gravelroastediron...ingotantimony, ingotbronze, ingotcopper...etc. etc. etc. This is how it looks in the menu, obviously not sorted the way I'd like to see it. The gravels are mixed with some of the ingots, and some of the blocks should be sorted into ores/rocks etc.: The fill method in ItemGroup.class has deprecated content: /** * Fills {@code items} with all items that are in this group. */ @OnlyIn(Dist.CLIENT) public void fill(NonNullList<ItemStack> items) { for(Item item : Registry.ITEM) { //.ITEM is deprecated item.fillItemGroup(this, items); } } Any relation?
-
I have to say it's quite a hard nut to crack, primarily due to its scope, and the quantity of cross references you'd have to code. The best I could find trying to comprehend was on Github with Arctics mod. But the difficulty and time investment deters me from implementing it now. I'll do it for 1.17 maybe. But there's more than enough work for me to forward right now.