Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

SW Raki

Members
  • Joined

  • Last visited

  1. I have yet to look up how to use DeferredRegistry. For now, i will finish implementing the core mechanics of my mod and will then start to clean up things. I last modded like 1.7.10, so i have to refresh my knowledge, but thanks for pointing that out!
  2. Well, that was unfortunate. in the tutorial video, it was actually null. i just shifted the IForgeContainerType.create method to the declaration section of my containertype, and now it works. I Dont know why my GUI is rendering completely in grey, but thats another issue i might get handled myself. Thanks.
  3. Here is my Tile Entity Class package com.kahmi.elementcrops.objects.entities; import javax.annotation.Nonnull; import javax.annotation.Nullable; import com.kahmi.elementcrops.objects.container.DungInfuserBlockContainer; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class DungInfuserTileEntity extends TileEntity implements INamedContainerProvider { //private DungInfuserItemStackHandler handler = new DungInfuserItemStackHandler(); private LazyOptional<IItemHandler> mHandler = LazyOptional.of(this::createHandler); public DungInfuserTileEntity() { super(TileEntities.DUNGINFUSERTILEENTITY); } public DungInfuserItemStackHandler createHandler() { return new DungInfuserItemStackHandler(); } @Override public void read(CompoundNBT pCompound) { CompoundNBT inventory = pCompound.getCompound("inv"); this.mHandler.ifPresent(h -> ((INBTSerializable<CompoundNBT>)h).deserializeNBT(inventory)); super.read(pCompound); } @Override public CompoundNBT write(CompoundNBT pCompound) { this.mHandler.ifPresent(h -> { CompoundNBT inventory = ((INBTSerializable<CompoundNBT>)h).serializeNBT(); pCompound.put("inv", inventory); }); return super.write(pCompound); } @Nonnull @Override public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> pCapability, @Nullable Direction pSide) { if (pCapability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { return mHandler.cast(); } return super.getCapability(pCapability, pSide); } @Nullable @Override public Container createMenu(int pId, PlayerInventory pInventory, PlayerEntity pPlayer) { return new DungInfuserBlockContainer(pId, world, pos, pInventory, pPlayer); } @Override public ITextComponent getDisplayName() { return new StringTextComponent(getType().getRegistryName().getPath()); } }
  4. Hello, i got an issue registering my Screen Container. I followed Jorrit Tybergheins Tutorial on creating a GUI. Again, everything works just fine but the GUI doesnt show up. After checking the logs, i found the error: [m[1;31m[21:24:18] [Server thread/FATAL] [minecraft/ThreadTaskExecutor]: Error executing task on Server java.lang.UnsupportedOperationException: Unable to construct this menu by type at net.minecraft.inventory.container.Container.getType(Container.java:52) ~[?:?] {re:classloading} at net.minecraftforge.fml.network.NetworkHooks.openGui(NetworkHooks.java:207) ~[?:?] {re:classloading} at net.minecraftforge.fml.network.NetworkHooks.openGui(NetworkHooks.java:172) ~[?:?] {re:classloading} at com.kahmi.elementcrops.objects.blocks.DungInfuserBlock.onBlockActivated(DungInfuserBlock.java:65) ~[?:?] {re:classloading} at net.minecraft.block.BlockState.onBlockActivated(BlockState.java:294) ~[?:?] {re:classloading} at net.minecraft.server.management.PlayerInteractionManager.func_219441_a(PlayerInteractionManager.java:343) ~[?:?] {re:classloading} at net.minecraft.network.play.ServerPlayNetHandler.processTryUseItemOnBlock(ServerPlayNetHandler.java:881) ~[?:?] {re:classloading} at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.processPacket(CPlayerTryUseItemOnBlockPacket.java:45) ~[?:?] {re:classloading} at net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket.processPacket(CPlayerTryUseItemOnBlockPacket.java:12) ~[?:?] {re:classloading} at net.minecraft.network.PacketThreadUtil.lambda$checkThreadAndEnqueue$0(PacketThreadUtil.java:19) ~[?:?] {re:classloading} at net.minecraft.util.concurrent.TickDelayedTask.run(TickDelayedTask.java:20) ~[?:?] {re:classloading} at net.minecraft.util.concurrent.ThreadTaskExecutor.run(ThreadTaskExecutor.java:140) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.concurrent.RecursiveEventLoop.run(RecursiveEventLoop.java:22) [?:?] {re:classloading} at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:759) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:141) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.concurrent.ThreadTaskExecutor.driveOne(ThreadTaskExecutor.java:110) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.driveOneInternal(MinecraftServer.java:742) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.driveOne(MinecraftServer.java:736) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.util.concurrent.ThreadTaskExecutor.driveUntil(ThreadTaskExecutor.java:123) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.runScheduledTasks(MinecraftServer.java:722) [?:?] {re:classloading,pl:accesstransformer:B} at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:666) [?:?] {re:classloading,pl:accesstransformer:B} at java.lang.Thread.run(Unknown Source) [?:1.8.0_241] {} After hours of searching for a solution, i came to the point that it must be failing at the registration of my Container, but i cant get why it doesnt work. Here is my Registry Class: package com.kahmi.elementcrops.init; import com.kahmi.elementcrops.ElementCrops; import com.kahmi.elementcrops.objects.container.DungInfuserBlockContainer; import net.minecraft.inventory.container.ContainerType; import net.minecraft.util.math.BlockPos; import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; import net.minecraftforge.registries.ObjectHolder; @Mod.EventBusSubscriber(modid = ElementCrops.MOD_ID, bus = Bus.MOD) @ObjectHolder(ElementCrops.MOD_ID) public class ContainerInitializer { @SubscribeEvent public static void registerContainer(final RegistryEvent.Register<ContainerType<?>> pEvent) { pEvent.getRegistry().register(IForgeContainerType.create((pWindowID, pInventory, pData) -> { BlockPos pos = pData.readBlockPos(); return new DungInfuserBlockContainer(pWindowID, ElementCrops.PROXY.getClientWorld(), pos, pInventory, ElementCrops.PROXY.getClientPlayer()); }).setRegistryName("dunginfuser")); } } Here is my Container Class: package com.kahmi.elementcrops.objects.container; import com.kahmi.elementcrops.ElementCrops; import com.kahmi.elementcrops.objects.blocks.Blocks; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IWorldPosCallable; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.wrapper.InvWrapper; import net.minecraftforge.registries.ObjectHolder; @ObjectHolder(ElementCrops.MOD_ID) public class DungInfuserBlockContainer extends Container { private TileEntity mEntity; private PlayerEntity mPlayer; private IItemHandler mPlayerInventory; public DungInfuserBlockContainer(int pId, World pWorld, BlockPos pPos, PlayerInventory pInventory, PlayerEntity pPlayer) { super(Containers.DUNGINFUSERBLOCK_CONTAINER, pId); this.mEntity = pWorld.getTileEntity(pPos); this.mPlayer = pPlayer; this.mPlayerInventory = new InvWrapper(mPlayer.inventory); this.mEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).ifPresent(h -> { addSlot(h, 0, 13, 34); addSlot(h, 1, 34, 34); addSlotRange(h, 2, 55, 34, 3, 18); addSlot(h, 5, 141, 34); }); layoutPlayerInventorySlots(7, 83); } @Override public boolean canInteractWith(PlayerEntity pPlayerIn) { return isWithinUsableDistance(IWorldPosCallable.of(mEntity.getWorld(), mEntity.getPos()), pPlayerIn, Blocks.DUNGINFUSER); } private void addSlot(IItemHandler pItemHandler, int pIndex, int pX, int pY) { addSlot(new SlotItemHandler(pItemHandler, pIndex, pX, pY)); } private int addSlotRange(IItemHandler pItemHandler, int pIndex, int pX, int pY, int pAmount, int pDistanceX) { for (int i = 0; i < pAmount; i++) { addSlot(pItemHandler, pIndex, pX, pY); pX += pDistanceX; pIndex++; } return pIndex; } private int addSlotBox(IItemHandler pItemHandler, int pIndex, int pX, int pY, int pColumns, int pDistanceX, int pRows, int pDistanceY) { for (int i = 0; i < pRows; i++) { pIndex = addSlotRange(pItemHandler, pIndex, pX, pY, pColumns, pDistanceX); pY += pDistanceY; } return pIndex; } private void layoutPlayerInventorySlots(int pX, int pY) { addSlotBox(this.mPlayerInventory, 9, pX, pY, 9, 18, 3, 18); pY += 58; addSlotRange(this.mPlayerInventory, 0, pX, pY, 9, 18); } } Here is my Block Class: package com.kahmi.elementcrops.objects.blocks; import javax.annotation.Nullable; import com.kahmi.elementcrops.objects.entities.DungInfuserTileEntity; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.pathfinding.PathType; import net.minecraft.state.IntegerProperty; import net.minecraft.state.StateContainer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; public class DungInfuserBlock extends Block { public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 5); private static final VoxelShape INSIDE = makeCuboidShape(2.0D, 4.0D, 2.0D, 14.0D, 16.0D, 14.0D); private static final VoxelShape SHAPE = VoxelShapes.combineAndSimplify(VoxelShapes.fullCube(), VoxelShapes.or(makeCuboidShape(0.0D, 0.0D, 4.0D, 16.0D, 3.0D, 12.0D), makeCuboidShape(4.0D, 0.0D, 0.0D, 12.0D, 3.0D, 16.0D), makeCuboidShape(2.0D, 0.0D, 2.0D, 14.0D, 3.0D, 14.0D), INSIDE), IBooleanFunction.ONLY_FIRST); public DungInfuserBlock(Properties pProperties) { super(pProperties); this.setDefaultState(this.stateContainer.getBaseState().with(LEVEL, Integer.valueOf(0))); } @Override public boolean hasTileEntity(BlockState pState) { return true; } @Nullable @Override public TileEntity createTileEntity(BlockState pState, IBlockReader pWorld) { return new DungInfuserTileEntity(); } @Override public VoxelShape getShape(BlockState pState, IBlockReader pWorldIn, BlockPos pPos, ISelectionContext pContext) { return SHAPE; } @Override public VoxelShape getRaytraceShape(BlockState pState, IBlockReader pWworldIn, BlockPos pPos) { return INSIDE; } @Override public ActionResultType onBlockActivated(BlockState pState, World pWorldIn, BlockPos pPos, PlayerEntity pPlayer, Hand pHandIn, BlockRayTraceResult pResult) { if (!pWorldIn.isRemote) { TileEntity entity = pWorldIn.getTileEntity(pPos); if (entity instanceof INamedContainerProvider) { NetworkHooks.openGui((ServerPlayerEntity)pPlayer, (INamedContainerProvider)entity, entity.getPos()); } else { throw new IllegalStateException("Our named container provider is missing!"); } return ActionResultType.SUCCESS; } return super.onBlockActivated(pState, pWorldIn, pPos, pPlayer, pHandIn, pResult); } public void setContentLevel(World pWorldIn, BlockPos pPos, BlockState pState, int pLevel) { pWorldIn.setBlockState(pPos, pState.with(LEVEL, Integer.valueOf(MathHelper.clamp(pLevel, 0, 5))), 2); pWorldIn.updateComparatorOutputLevel(pPos, this); } /** * @deprecated call via {@link IBlockState#hasComparatorInputOverride()} whenever possible. Implementing/overriding * is fine. */ public boolean hasComparatorInputOverride(BlockState pState) { return true; } /** * @deprecated call via {@link IBlockState#getComparatorInputOverride(World,BlockPos)} whenever possible. * Implementing/overriding is fine. */ public int getComparatorInputOverride(BlockState pBlockState, World pWorldIn, BlockPos pPos) { return pBlockState.get(LEVEL); } protected void fillStateContainer(StateContainer.Builder<Block, BlockState> pBuilder) { pBuilder.add(LEVEL); } public boolean allowsMovement(BlockState pState, IBlockReader pWorldIn, BlockPos pPos, PathType pType) { return false; } } if you need more code, i will setup github tomorrow. Thanks in advance! EDIT: this is my GitHub
  5. Oh well, i kinda get the Flyweight Pattern. Then i will get into TileEntities. Thank you!
  6. Hello my dear friends. I created a custom cauldron-like block. everything works fine, it renders like i want it to. The block cant accept duplicate items to generate tier-based dung item. Example: to generate tier 1 crafting dung, you need 1 dirt, then 1 bone meal, and then 3 different tier 0 crop products (vanilla items like wheat, carrot, potato etc.). The Problem: if i use, for example, wheat on one DungInfuser Block, i can't use wheat anymore on any DungInfuser Block. It doesn't matter if i destroy the block or place multiple blocks, destroy and replace them. I started modding this week and i havent used java for quite a while, so i dont really get what i did wrong. I apologise in advance for my terrible english and hope you get my issue right. PS: Currently, it doesnt drop the resulting crafting dung, it is not implemented yet. I want to fix this issue first. package com.kahmi.elementcrops.objects.blocks; import java.util.Arrays; import com.kahmi.elementcrops.objects.items.FruitModItem; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.pathfinding.PathType; import net.minecraft.state.IntegerProperty; import net.minecraft.state.StateContainer; import net.minecraft.stats.Stats; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; public class DungInfuserBlock extends Block { public static final IntegerProperty LEVEL = IntegerProperty.create("level", 0, 5); private static final VoxelShape INSIDE = makeCuboidShape(2.0D, 4.0D, 2.0D, 14.0D, 16.0D, 14.0D); private static final VoxelShape SHAPE = VoxelShapes.combineAndSimplify(VoxelShapes.fullCube(), VoxelShapes.or(makeCuboidShape(0.0D, 0.0D, 4.0D, 16.0D, 3.0D, 12.0D), makeCuboidShape(4.0D, 0.0D, 0.0D, 12.0D, 3.0D, 16.0D), makeCuboidShape(2.0D, 0.0D, 2.0D, 14.0D, 3.0D, 14.0D), INSIDE), IBooleanFunction.ONLY_FIRST); private int mContentTier = 0; private Item[] mUsedContent = new Item[3]; public DungInfuserBlock(Properties pProperties) { super(pProperties); this.setDefaultState(this.stateContainer.getBaseState().with(LEVEL, Integer.valueOf(0))); } public VoxelShape getShape(BlockState pState, IBlockReader pWorldIn, BlockPos pPos, ISelectionContext pContext) { return SHAPE; } public VoxelShape getRaytraceShape(BlockState pState, IBlockReader pWworldIn, BlockPos pPos) { return INSIDE; } public ActionResultType onBlockActivated(BlockState pState, World pWorldIn, BlockPos pPos, PlayerEntity pPlayer, Hand pHandIn, BlockRayTraceResult p_225533_6_) { ItemStack heldItemStack = pPlayer.getHeldItem(pHandIn); int level = pState.get(LEVEL); if (heldItemStack.isEmpty() || level == 5) { return ActionResultType.PASS; } else { Item heldItem = heldItemStack.getItem(); if ((heldItem == Items.DIRT || heldItem == Items.COARSE_DIRT) && level == 0 && !pWorldIn.isRemote) { if (!pPlayer.abilities.isCreativeMode) { pPlayer.setHeldItem(pHandIn, ItemStack.EMPTY); } pPlayer.addStat(Stats.FILL_CAULDRON); this.setContentLevel(pWorldIn, pPos, pState, 1); return ActionResultType.SUCCESS; } else if (heldItem == Items.BONE_MEAL && level == 1 && !pWorldIn.isRemote) { if (!pPlayer.abilities.isCreativeMode) { pPlayer.setHeldItem(pHandIn, ItemStack.EMPTY); } pPlayer.addStat(Stats.FILL_CAULDRON); this.setContentLevel(pWorldIn, pPos, pState, 2); return ActionResultType.SUCCESS; } else if ((heldItem == Items.POTATO || heldItem == Items.CARROT || heldItem == Items.WHEAT || heldItem == Items.BEETROOT || heldItem == Items.MELON_SLICE || heldItem == Items.PUMPKIN) && level >= 2 && !Arrays.asList(mUsedContent).contains(heldItem) && !pWorldIn.isRemote) { if (!pPlayer.abilities.isCreativeMode) { pPlayer.setHeldItem(pHandIn, ItemStack.EMPTY); } pPlayer.addStat(Stats.FILL_CAULDRON); this.setContentLevel(pWorldIn, pPos, pState, level + 1); this.mUsedContent[level - 2] = heldItem; return ActionResultType.SUCCESS; } else if (heldItem instanceof FruitModItem && level >= 2 && !pWorldIn.isRemote) { FruitModItem iHeldItem = (FruitModItem)heldItem; if (level == 2) { this.mContentTier = iHeldItem.TIER; if (!pPlayer.abilities.isCreativeMode) { pPlayer.setHeldItem(pHandIn, ItemStack.EMPTY); } pPlayer.addStat(Stats.FILL_CAULDRON); this.setContentLevel(pWorldIn, pPos, pState, level + 1); this.mUsedContent[level - 2] = heldItem; return ActionResultType.SUCCESS; } else if (this.mContentTier == iHeldItem.TIER) { if (!pPlayer.abilities.isCreativeMode) { pPlayer.setHeldItem(pHandIn, ItemStack.EMPTY); } pPlayer.addStat(Stats.FILL_CAULDRON); this.setContentLevel(pWorldIn, pPos, pState, level + 1); this.mUsedContent[level - 2] = heldItem; return ActionResultType.SUCCESS; } } } return ActionResultType.PASS; } public void setContentLevel(World pWorldIn, BlockPos pPos, BlockState pState, int pLevel) { pWorldIn.setBlockState(pPos, pState.with(LEVEL, Integer.valueOf(MathHelper.clamp(pLevel, 0, 5))), 2); pWorldIn.updateComparatorOutputLevel(pPos, this); } /** * @deprecated call via {@link IBlockState#hasComparatorInputOverride()} whenever possible. Implementing/overriding * is fine. */ public boolean hasComparatorInputOverride(BlockState pState) { return true; } /** * @deprecated call via {@link IBlockState#getComparatorInputOverride(World,BlockPos)} whenever possible. * Implementing/overriding is fine. */ public int getComparatorInputOverride(BlockState pBlockState, World pWorldIn, BlockPos pPos) { return pBlockState.get(LEVEL); } protected void fillStateContainer(StateContainer.Builder<Block, BlockState> pBuilder) { pBuilder.add(LEVEL); } public boolean allowsMovement(BlockState pState, IBlockReader pWorldIn, BlockPos pPos, PathType pType) { return false; } }

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.