Jump to content

[1.19.2] Easy way to make a custom furnace?


Thread

Recommended Posts

Hi modders,

as title says I wanted to make a custom furnace (with same recipes as vanilla) but slightly faster.

Is it possible in forge 1.19? If it is, how?

 

So far I made these classes:

Block:

package com.angelobdev.openindustry.block.custom;

import com.angelobdev.openindustry.block.entity.IronFurnaceBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.util.RandomSource;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.AbstractFurnaceBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;

import javax.annotation.Nullable;

public class IronFurnaceBlock extends AbstractFurnaceBlock {

    public IronFurnaceBlock(BlockBehaviour.Properties properties) {
        super(properties);
    }

    public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
        return new IronFurnaceBlockEntity(pos, state);
    }

    @Nullable
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState blockState, BlockEntityType<T> blockEntityType) {
        return createFurnaceTicker(level, blockEntityType, BlockEntityType.FURNACE);
    }

    protected void openContainer(Level level, BlockPos blockPos, Player player) {
        BlockEntity blockentity = level.getBlockEntity(blockPos);
        if (blockentity instanceof IronFurnaceBlockEntity) {
            player.openMenu((MenuProvider) blockentity);
            player.awardStat(Stats.INTERACT_WITH_FURNACE);
        }

    }

    public void animateTick(BlockState blockState, Level level, BlockPos blockPos, RandomSource randomSource) {
        if (blockState.getValue(LIT)) {
            double d0 = (double) blockPos.getX() + 0.5D;
            double d1 = (double) blockPos.getY();
            double d2 = (double) blockPos.getZ() + 0.5D;
            if (randomSource.nextDouble() < 0.1D) {
                level.playLocalSound(d0, d1, d2, SoundEvents.FURNACE_FIRE_CRACKLE, SoundSource.BLOCKS, 1.0F, 1.0F, false);
            }

            Direction direction = blockState.getValue(FACING);
            Direction.Axis direction$axis = direction.getAxis();
            double d3 = 0.52D;
            double d4 = randomSource.nextDouble() * 0.6D - 0.3D;
            double d5 = direction$axis == Direction.Axis.X ? (double) direction.getStepX() * 0.52D : d4;
            double d6 = randomSource.nextDouble() * 6.0D / 16.0D;
            double d7 = direction$axis == Direction.Axis.Z ? (double) direction.getStepZ() * 0.52D : d4;
            level.addParticle(ParticleTypes.SMOKE, d0 + d5, d1 + d6, d2 + d7, 0.0D, 0.0D, 0.0D);
            level.addParticle(ParticleTypes.FLAME, d0 + d5, d1 + d6, d2 + d7, 0.0D, 0.0D, 0.0D);
        }
    }


}

BlockEntity:

package com.angelobdev.openindustry.block.entity;

import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.FurnaceMenu;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;

public class IronFurnaceBlockEntity extends AbstractFurnaceBlockEntity {
    public IronFurnaceBlockEntity(BlockPos pos, BlockState state) {
        super(BlockEntityType.FURNACE, pos, state, RecipeType.SMELTING);
    }

    protected @NotNull Component getDefaultName() {
        return Component.translatable("container.iron_furnace");
    }

    protected @NotNull AbstractContainerMenu createMenu(int id, @NotNull Inventory inventory) {
        return new FurnaceMenu(id, inventory, this, this.dataAccess);
    }
}

 

UPDATE. Got this warning:

[00:11:10] [Server thread/WARN] [minecraft/LevelChunk]: Block entity minecraft:furnace @ BlockPos{x=119, y=64, z=102} state Block{open_industry:iron_furnace}[facing=west,lit=false] invalid for ticking:

 

Edited by Thread
Warning update
Link to comment
Share on other sites

  • Thread changed the title to [1.19.2] Easy way to make a custom furnace?
1 hour ago, poopoodice said:

The warning means the block and the TE does not match, where and how do you register your TE? Is your block added to the list when constructing your TE?

Sorry I’m new to modding. What is the TE?

Btw I solved the warn by implementing a custom Menu, but the furnace still doesn’t smelt. (BlockEntity is working fine and recipes are loaded correctly)

I don’t know what the error is…

Link to comment
Share on other sites

TE = Tile Entity, or Block Entity in recent versions.

I believe you need one for yourself (both MenuType and BlockEntityType) since certain TE/BEs only allows certain blocks (e.g. Vanilla Furnace TE/BE does not work on a custom furnace).

It's also better to post your TE/BE and Menu class along with where and how you register your custom types.

Link to comment
Share on other sites

Alright, the BE class is already posted, here is the Menu:

package com.angelobdev.openindustry.block.entity.menu;

import net.minecraft.core.Registry;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.crafting.RecipeType;

public class IronFurnaceMenu extends AbstractFurnaceMenu {

    //public static final MenuType<IronFurnaceMenu> IRON_FURNACE = Registry.register(Registry.MENU, "iron_furnace", new MenuType<>(IronFurnaceMenu::new));

//    public IronFurnaceMenu(int ID, Inventory inventory) {
//        super(MenuType.FURNACE, RecipeType.SMELTING, RecipeBookType.FURNACE, ID, inventory);
//    }

    public IronFurnaceMenu(int ID, Inventory inventory, Container container, ContainerData data) {
        super(MenuType.FURNACE, RecipeType.SMELTING, RecipeBookType.FURNACE, ID, inventory, container, data);
    }
}

As you can see I tried to register a custom MenuType (obv it crashed)

Here, instead the BlockEntityType register:

package com.angelobdev.openindustry.block.entity;

import com.angelobdev.openindustry.OpenIndustry;
import com.angelobdev.openindustry.block.OIBlocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class OIBlockEntities {

    public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, OpenIndustry.MODID);

    public static final RegistryObject<BlockEntityType<IronFurnaceBlockEntity>> IRON_FURNACE = BLOCK_ENTITIES.register(
            "iron_furnace",
            () -> BlockEntityType.Builder.of(
                    IronFurnaceBlockEntity::new,
                    OIBlocks.IRON_FURNACE.get()
            ).build(null)
    );

    public static void register(IEventBus eventBus) {
        BLOCK_ENTITIES.register(eventBus);
    }
}

I updated the BE class too:

package com.angelobdev.openindustry.block.entity;

import com.angelobdev.openindustry.block.entity.menu.IronFurnaceMenu;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.NotNull;

public class IronFurnaceBlockEntity extends AbstractFurnaceBlockEntity {

    public IronFurnaceBlockEntity(BlockPos blockPos, BlockState blockState) {
        super(OIBlockEntities.IRON_FURNACE.get(), blockPos, blockState, RecipeType.SMELTING);
    }

    protected @NotNull Component getDefaultName() {
        return Component.literal("Iron Furnace");
    }

    protected @NotNull AbstractContainerMenu createMenu(int id, @NotNull Inventory inventory) {
        return new IronFurnaceMenu(id, inventory, this, this.dataAccess);
    }

    @Override
    protected int getBurnDuration(@NotNull ItemStack itemStack) {
        return super.getBurnDuration(itemStack) / 2;
    }


}

 

 

Edited by Thread
Link to comment
Share on other sites

Update, I got some progress. I've registered the custom MenuType as:

package com.angelobdev.openindustry.block.entity.menu;

import com.angelobdev.openindustry.OpenIndustry;
import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;

public class OIMenuType {

    public static final DeferredRegister<MenuType<?>> MENU_TYPES = DeferredRegister.create(ForgeRegistries.MENU_TYPES, OpenIndustry.MODID);

    public static final RegistryObject<MenuType<IronFurnaceMenu>> IRON_FURNACE_MENU = MENU_TYPES.register(
            "name",
            () -> new MenuType<>(IronFurnaceMenu::new)
    );

    public static void register(IEventBus eventBus) {
        MENU_TYPES.register(eventBus);
    }

}

But now I got this warn in the console:

[10:44:16] [Render thread/WARN] [minecraft/MenuScreens]: Failed to create screen for menu type: open_industry:iron_furnace_menu

I'll figure it out, hopefully.

Edited by Thread
Link to comment
Share on other sites

Alright I solved.

The problem was in registering the screen. I did it by passing this command in the commonSetup.

MenuScreens.register(OIMenuType.IRON_FURNACE_MENU.get(), IronFurnaceScreen::new);

Instead it has to be passed in the clientSetup like so:

    @Mod.EventBusSubscriber(modid = MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
    public static class ClientModEvents{
        @SubscribeEvent
        public static void onClientSetup(FMLClientSetupEvent event){
            MenuScreens.register(OIMenuType.IRON_FURNACE_MENU.get(), IronFurnaceScreen::new);
        }
    }

Thanks @poopoodice you have been really helpful ❤️

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

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