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


  • Posts

  • Joined

  • Last visited

Everything posted by Majd123mc

  1. Thanks everybody! I managed to fix it. I just had some missing attributes in my OilFluid class
  2. Thank you everybody, I have figured out the cause. I was accidentally passing in the constructor for the Fluids instead of the RegistryObject. I changed: super(new ForgeFlowingFluid.Properties( OilFluid.Source::new, OilFluid.Flowing::new, to: super(new ForgeFlowingFluid.Properties( ModFluids.OIL, ModFluids.FLOWING_OIL, And now the fluid actually works! But it doesn't spread though, I think I'd be able to figured it out from now. Thanks a lot Luis_ST and Cratthorax!
  3. Thanks for the help everybody! I tried this and although the block did register, the fluid just appears as a flat plane you can only see if you break the block under it. I tried debugging it as much as I could but alas I couldn't solve it Here is the code for my "fixed" liquidblock as suggested by Luis_ST: package com.hotmail.majdroaydi.minitech.blocks; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.FluidTags; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.FlowingFluid; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import java.util.Optional; import java.util.function.Supplier; public class ForgeLiquidBlock extends LiquidBlock { public ForgeLiquidBlock(Supplier<? extends FlowingFluid> supplier, Properties properties) { super(supplier, properties); } @Override public VoxelShape getCollisionShape(BlockState p_54760_, BlockGetter p_54761_, BlockPos p_54762_, CollisionContext p_54763_) { return p_54763_.isAbove(STABLE_SHAPE, p_54762_, true) && p_54760_.getValue(LEVEL) == 0 && p_54763_.canStandOnFluid(p_54761_.getFluidState(p_54762_.above()), getFluid()) ? STABLE_SHAPE : Shapes.empty(); } @Override public boolean isPathfindable(BlockState p_54704_, BlockGetter p_54705_, BlockPos p_54706_, PathComputationType p_54707_) { return !getFluid().is(FluidTags.LAVA); } @Override public boolean skipRendering(BlockState p_54716_, BlockState p_54717_, Direction p_54718_) { return p_54717_.getFluidState().getType().isSame(getFluid()); } @Override public void onPlace(BlockState p_54754_, Level p_54755_, BlockPos p_54756_, BlockState p_54757_, boolean p_54758_) { if (this.shouldSpreadLiquid(p_54755_, p_54756_, p_54754_)) { p_54755_.getLiquidTicks().scheduleTick(p_54756_, p_54754_.getFluidState().getType(), getFluid().getTickDelay(p_54755_)); } } @Override public BlockState updateShape(BlockState p_54723_, Direction p_54724_, BlockState p_54725_, LevelAccessor p_54726_, BlockPos p_54727_, BlockPos p_54728_) { if (p_54723_.getFluidState().isSource() || p_54725_.getFluidState().isSource()) { p_54726_.getLiquidTicks().scheduleTick(p_54727_, p_54723_.getFluidState().getType(), getFluid().getTickDelay(p_54726_)); } //return super.updateShape(p_54723_, p_54724_, p_54725_, p_54726_, p_54727_, p_54728_); return p_54723_; // Calling super.updateShape will just call LiquidBlock's updateShape, not what we are looking for! Thankfully, Block.updateShape, simply enough, just returns the first parameter. } @Override public void neighborChanged(BlockState p_54709_, Level p_54710_, BlockPos p_54711_, Block p_54712_, BlockPos p_54713_, boolean p_54714_) { if (this.shouldSpreadLiquid(p_54710_, p_54711_, p_54709_)) { p_54710_.getLiquidTicks().scheduleTick(p_54711_, p_54709_.getFluidState().getType(), getFluid().getTickDelay(p_54710_)); } } private boolean shouldSpreadLiquid(Level p_54697_, BlockPos p_54698_, BlockState p_54699_) { if (getFluid().is(FluidTags.LAVA)) { boolean flag = p_54697_.getBlockState(p_54698_.below()).is(Blocks.SOUL_SOIL); for(Direction direction : POSSIBLE_FLOW_DIRECTIONS) { BlockPos blockpos = p_54698_.relative(direction.getOpposite()); if (p_54697_.getFluidState(blockpos).is(FluidTags.WATER)) { Block block = p_54697_.getFluidState(p_54698_).isSource() ? Blocks.OBSIDIAN : Blocks.COBBLESTONE; p_54697_.setBlockAndUpdate(p_54698_, net.minecraftforge.event.ForgeEventFactory.fireFluidPlaceBlockEvent(p_54697_, p_54698_, p_54698_, block.defaultBlockState())); this.fizz(p_54697_, p_54698_); return false; } if (flag && p_54697_.getBlockState(blockpos).is(Blocks.BLUE_ICE)) { p_54697_.setBlockAndUpdate(p_54698_, net.minecraftforge.event.ForgeEventFactory.fireFluidPlaceBlockEvent(p_54697_, p_54698_, p_54698_, Blocks.BASALT.defaultBlockState())); this.fizz(p_54697_, p_54698_); return false; } } } return true; } private void fizz(LevelAccessor p_54701_, BlockPos p_54702_) { p_54701_.levelEvent(1501, p_54702_, 0); } @Override public ItemStack pickupBlock(LevelAccessor p_153772_, BlockPos p_153773_, BlockState p_153774_) { if (p_153774_.getValue(LEVEL) == 0) { p_153772_.setBlock(p_153773_, Blocks.AIR.defaultBlockState(), 11); return new ItemStack(getFluid().getBucket()); } else { return ItemStack.EMPTY; } } @Override public Optional<SoundEvent> getPickupSound() { return getFluid().getPickupSound(); } } The code for my OilFluid can be found above.
  4. Whoops! Sorry, my fault. But yes, a block entity (tile entity in 1.16-) *is* needed for storing data (i.e. furnace). But I think what OP is doing is making an item combiner, which doesn't need one
  5. Fair enough, I haven't considered that. I'll try it later thank you
  6. Sorry I can't find any premade tutorials for 1.17 at the moment. It really depends on the version of forge you are using. But here's the rundown: You want to look at classes such as BeaconBlock, or ChestBlock, BeaconMenu, etc. to help you with these steps, but you need to do the following: 1. Make a block extending BaseEntityBlock (BeaconBlock) 2. Make a block entity for it (BeaconTileEntity) 3. Make a menu for it (BeaconMenu) 4. Make a screen for it (BeaconScreen) I know it's a little complex, but I'm sure you can find tutorials online, or if someone else comes in to help.
  7. This usually happens because of a bad manifest (mods.toml). Can you show us what's in your src folder?
  8. Solved: Hello all. I am trying to implement oil into my mod (I know I know, unoriginal). But I just can't seem to get it to work. (System/Minecraft information: Java 17, forge: 1.17.1-37.0.95, mappings: official) I am using DeferredRegisters. In the current configuration, the bucket doesn't do anything most of the time, the block doesn't appear and doesn't flow. I am extending "ForgeFlowingFluid". It seems in LiquidBlock there are two constructors, one deprecated taking in a Fluid, the other takes in a supplier/RegistryObject<Fluid>. Because I am using DeferredRegisters, I have to use the second one, because blocks are registered before fluids. But it seems that in the code, most of it relies on the LiquidBlock.fluid field, which never gets set in the second constructor. I tried hacking in a solution with a "Fixed" version of LiquidBlock: public class FixedLiquidBlock extends LiquidBlock { private static final List<FixedLiquidBlock> liquidBlocksNeedingFixing = new ArrayList<>(); // Check if the supplier is a registry object. If it is, and the value is not null, set the value of the fluid field, else mark it so that it gets set later. public FixedLiquidBlock(Supplier<? extends FlowingFluid> supplier, Properties properties) { super(supplier, properties); try { if (supplier instanceof RegistryObject registryObject && registryObject.get() != null) { try { Class<?> class_ = LiquidBlock.class; Field fluidField = ObfuscationReflectionHelper.findField(class_, "fluid"); fluidField.setAccessible(true); fluidField.set(this, supplier.get()); } catch (Exception e) { throw new RuntimeException(e); } } } catch (NullPointerException ignored) {} liquidBlocksNeedingFixing.add(this); } @Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) private static class FixedLiquidBlockEvents { @SubscribeEvent(priority = EventPriority.LOWEST) // Force the event to be called last // After registration of fluids is finished, set the fluids field. public static void onFluidsRegister(RegistryEvent<Fluid> fluidRegistryEvent) { for (FixedLiquidBlock fixedLiquidBlock : liquidBlocksNeedingFixing) { try { Class<?> class_ = LiquidBlock.class; Field fluidField = ObfuscationReflectionHelper.findField(class_, "fluid"); fluidField.setAccessible(true); fluidField.set(fixedLiquidBlock, fixedLiquidBlock.getFluid()); } catch (Exception e) { throw new RuntimeException(e); } } } } } But clearly what I'm doing is stupid because it still doesn't work. I even tried without my hacky solution, and it still didn't work! Am I doing something wrong? Should I be extending something else? What else should I do? Code for fluid, OilFluid.java: public abstract class OilFluid extends ForgeFlowingFluid { protected OilFluid() { super(new ForgeFlowingFluid.Properties( Source::new, Flowing::new, FluidAttributes.builder( new ResourceLocation(MiniTech.MODID, "block/oil_still"), new ResourceLocation(MiniTech.MODID, "block/oil_flow") ).overlay(new ResourceLocation(MiniTech.MODID, "block/oil_overlay")) .translationKey("block." + MiniTech.MODID + ".oil") .color(0xffffff))); } public static class Flowing extends OilFluid { public Flowing() { registerDefaultState(getStateDefinition().any().setValue(LEVEL, 7)); } @Override protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> p_76476_) { super.createFluidStateDefinition(p_76476_); p_76476_.add(LEVEL); } @Override public int getAmount(FluidState p_76480_) { return p_76480_.getValue(LEVEL); } @Override public boolean isSource(FluidState p_76478_) { return false; } } public static class Source extends OilFluid { @Override public int getAmount(FluidState p_76485_) { return 8; } @Override public boolean isSource(FluidState p_76483_) { return true; } } } Code for ModBlocks.java: public class ModBlocks { private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, MiniTech.MODID); public static final RegistryObject<RefineryFurnaceBlock> REFINERY_FURNACE = BLOCKS.register("refinery_furnace", () -> new RefineryFurnaceBlock(BlockBehaviour.Properties.of(Material.STONE).requiresCorrectToolForDrops().strength(3.5F).lightLevel(litBlockEmission(13)))); // Fluids public static final RegistryObject<LiquidBlock> OIL = BLOCKS.register("oil", () -> new FixedLiquidBlock(ModFluids.OIL, BlockBehaviour.Properties.of(Material.WATER).noCollission().strength(100.0F).noDrops())); public static void register(IEventBus eventBus) { BLOCKS.register(eventBus); } private static ToIntFunction<BlockState> litBlockEmission(int lightLevel) { return (blockState) -> { return blockState.getValue(BlockStateProperties.LIT) ? lightLevel : 0; }; } }
  9. Hello, I am trying to make my own furnace. But I have ran into an issue. How am I supposed to register a Screen? In the vanilla implementation, it uses "MenuScreen.register", but it does not accept a supplier, and by the time I am registering it the blocks and menu haven't been registered yet. I have heard to use ScreenManager.registerFactory, but it seems that method doesn't exist anymore. Where/when/how should I register the screen? Thanks a lot. Code for ModScreens.java: public class ModScreens { public static void register() { MenuScreens.register(ModMenus.REFINERY_FURNACE.get(), RefineryFurnaceScreen::new); // Doesn't work because ModMenus.REFINERY_FURNACE is not initialized until registry. } } Code for MiniTech.java: @Mod(MiniTech.MODID) public class MiniTech { // Directly reference a log4j logger. public static final Logger LOGGER = LogManager.getLogger(); public static final String MODID = "minitech"; private static final List<Consumer<IEventBus>> registrationFunctions = Arrays.asList( ModBlocks::register, ModItems::register, ModBlockEntities::register, ModMenus::register, __ -> ModScreens.register() ); public MiniTech() { IEventBus eventBus = FMLJavaModLoadingContext.get().getModEventBus(); for (var registrationFunction : registrationFunctions) { registrationFunction.accept(eventBus); } } }
  10. Yup, I saw that as well. And I'm not sure of any way around it. I guess you'll have to manually add the colors to each block using your own system.
  11. For DyeColor, you can try using MaterialColor instead. DyeColor really is just a wrapper for it anyway. Note: You must create your OWN MaterialColor Instance with NO constructor arguments (the default one has a hard limit for the number of colors) and manually set the "colorValue" field It's pretty complicated
  12. BTW, you'd get the player's skin by first getting their info. To get all players info, first get the connection = minecraft.player.connection, then you can get the info list with connection.getPlayerInfoMap();
  13. SOLVED: I figured out why it wasn't working. Turns out you HAVE to initialize your widgets in init(); I had already done this, but because of the way I was doing things I thought I could get away with putting it in my infoReceived method, turns out I couldn't.
  14. [SOVLED] Hello, for my system, I need to display a number for each item in a list, I have found an object just for this. It is called ExtendedList. However, it is implemented not to be used as a widget in the same way, for instance, I had to disable the dirt background and manually set left and right values. The problem is when I resize my Minecraft window, the scrolling becomes completely unresponsive, and the bounds of the widget go completely off. I found a solution for problem 2, as I can reset the left and right values during render, however scrolling functionality still breaks. Here is my code: Most of this code was influenced by LoadingErrorScreen as suggested by others in the forums, as some of the method arguments are labeled. Here are some screenshots to demonstrate this (note that the code that fixes the resolution resize issue have been commented out):
  15. I already answered it in another post. In your ExtendedList constructor, call the correct method here: (link)
  16. I already answered it in another post. Don't override the method as it isn't necessary In your list constructor, call the correct method here: (link)
  17. There is a method that allows you to get rid of it: func_244606_c(false) func_244606_c(false) // Disables dirt outline func_244605_b(false) // Disables black background Note that false disables them, whilst true enables them.
  • Create New...

Important Information

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