[TUTORIAL 1.14.4] Change a block's texture (in-game)

Started by Max094_Reikeb on

Topic category: User side tutorials

Joined Jun 2015
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
[TUTORIAL 1.14.4] Change a block's texture (in-game)

Hey everyone, welcome for my tutorial about how to change a block's texture in-game.
I made a video tutorial, available now on YouTube!
Link : https://www.youtube.com/watch?v=M2ksabM0xR8
Don't forget to subscribe and to like the video for more tutorials. (and sorry for the sound quality)

Joined Dec 2017
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Now it works just had the…
Sun, 12/13/2020 - 10:37

Now it works just had the change the

(pos, state.with(AGE, Integer.valueOf(2)), 3); to (pos, state.with(STATE, Integer.valueOf(2)), 3);

Another question is what does the 3 in (pos, state.with(AGE, Integer.valueOf(2)), 3); do?

Joined Jun 2015
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
I don't know what the "3'…
Mon, 12/14/2020 - 11:54

I don't know what the "3' does. You must keep it however.

Joined Dec 2017
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Another thing is that it…
Tue, 12/15/2020 - 20:31

Another thing is that it seems like the block doesnt rotate towards the player it says in F3 that its north,west etc. but it always faces the same direction any solution for this?

Joined Nov 2020
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
You just saved mah brainz!…
Sun, 03/07/2021 - 22:17

You just saved mah brainz! Thanks for the help ;)

Joined Aug 2020
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Great tutorial!! But i have…
Tue, 04/06/2021 - 20:15

Great tutorial!! But i have some errors, it all works all right exept the texture, the bock has the error texture (pink and black tiles).

I think the error occurs in the blockstate. (I am on the lastest snapshot)

Joined Aug 2020
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Never mind... I solved it!! …
Tue, 04/06/2021 - 20:28

Never mind... I solved it!! (It was on the blockstate)

Joined Dec 2017
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
I need some help, I also…
Wed, 05/12/2021 - 16:31

I need some help, I also have those black/purple tiles but only when the block is placed, when in Inventory or dropped as items it looks fine also in F3 it works aswell so theres a problem with the code but I dont know where any Ideas?

 

package net.mcreator.magnets.block;

import net.minecraftforge.registries.ObjectHolder;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.ToolType;

import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.World;
import net.minecraft.world.IBlockReader;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.Rotation;
import net.minecraft.util.NonNullList;
import net.minecraft.util.Mirror;
import net.minecraft.util.Direction;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.LockableLootTileEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.StateContainer;
import net.minecraft.state.DirectionProperty;
import net.minecraft.state.BooleanProperty;
import net.minecraft.network.play.server.SUpdateTileEntityPacket;
import net.minecraft.network.NetworkManager;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.loot.LootContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Item;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.BlockItem;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.ChestContainer;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.block.material.Material;
import net.minecraft.block.SoundType;
import net.minecraft.block.DirectionalBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Block;

import net.mcreator.magnets.procedures.MagnetUpdateTickProcedure;
import net.mcreator.magnets.procedures.MagnetRedstoneOnProcedure;
import net.mcreator.magnets.procedures.MagnetRedstoneOffProcedure;
import net.mcreator.magnets.MagnetsModElements;

import javax.annotation.Nullable;

import java.util.stream.IntStream;
import java.util.Random;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.Collections;

@MagnetsModElements.ModElement.Tag
public class MagnetBlock extends MagnetsModElements.ModElement {
    @ObjectHolder("magnets:magnet")
    public static final Block block = null;
    @ObjectHolder("magnets:magnet")
    public static final TileEntityType<CustomTileEntity> tileEntityType = null;
    public MagnetBlock(MagnetsModElements instance) {
        super(instance, 6);
        FMLJavaModLoadingContext.get().getModEventBus().register(new TileEntityRegisterHandler());
    }

    @Override
    public void initElements() {
        elements.blocks.add(() -> new CustomBlock());
        elements.items
                .add(() -> new BlockItem(block, new Item.Properties().group(ItemGroup.BUILDING_BLOCKS)).setRegistryName(block.getRegistryName()));
    }
    private static class TileEntityRegisterHandler {
        @SubscribeEvent
        public void registerTileEntity(RegistryEvent.Register<TileEntityType<?>> event) {
            event.getRegistry().register(TileEntityType.Builder.create(CustomTileEntity::new, block).build(null).setRegistryName("magnet"));
        }
    }

    public static class CustomBlock extends Block {
        public static final DirectionProperty FACING = DirectionalBlock.FACING;
        public static final BooleanProperty REPEL = BlockStateProperties.INVERTED;
        public CustomBlock() {
            super(Block.Properties.create(Material.IRON).sound(SoundType.METAL).hardnessAndResistance(3f, 6f).setLightLevel(s -> 0).harvestLevel(1)
                    .harvestTool(ToolType.PICKAXE).setRequiresTool());
            this.setDefaultState(this.stateContainer.getBaseState().with(FACING, Direction.NORTH).with(REPEL, Boolean.valueOf(false)));
            setRegistryName("magnet");
        }

        @Override
        protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
            builder.add(FACING, REPEL);
        }

        public BlockState rotate(BlockState state, Rotation rot) {
            return state.with(FACING, rot.rotate(state.get(FACING)));
        }

        public BlockState mirror(BlockState state, Mirror mirrorIn) {
            return state.rotate(mirrorIn.toRotation(state.get(FACING)));
        }

        @Override
        public BlockState getStateForPlacement(BlockItemUseContext context) {
            ;
            return this.getDefaultState().with(FACING, context.getNearestLookingDirection().getOpposite());
        }

        @Override
        public List<ItemStack> getDrops(BlockState state, LootContext.Builder builder) {
            List<ItemStack> dropsOriginal = super.getDrops(state, builder);
            if (!dropsOriginal.isEmpty())
                return dropsOriginal;
            return Collections.singletonList(new ItemStack(this, 1));
        }

        @Override
        public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean moving) {
            super.onBlockAdded(state, world, pos, oldState, moving);
            int x = pos.getX();
            int y = pos.getY();
            int z = pos.getZ();
            world.getPendingBlockTicks().scheduleTick(new BlockPos(x, y, z), this, 10);
        }

        @Override
        public void neighborChanged(BlockState state, World world, BlockPos pos, Block neighborBlock, BlockPos fromPos, boolean moving) {
            super.neighborChanged(state, world, pos, neighborBlock, fromPos, moving);
            int x = pos.getX();
            int y = pos.getY();
            int z = pos.getZ();
            if (world.getRedstonePowerFromNeighbors(new BlockPos(x, y, z)) > 0) {
                {
                    Map<String, Object> $_dependencies = new HashMap<>();
                    $_dependencies.put("x", x);
                    $_dependencies.put("y", y);
                    $_dependencies.put("z", z);
                    $_dependencies.put("world", world);
                    MagnetRedstoneOnProcedure.executeProcedure($_dependencies);
                }
            } else {
                {
                    Map<String, Object> $_dependencies = new HashMap<>();
                    $_dependencies.put("x", x);
                    $_dependencies.put("y", y);
                    $_dependencies.put("z", z);
                    $_dependencies.put("world", world);
                    MagnetRedstoneOffProcedure.executeProcedure($_dependencies);
                }
            }
        }

        @Override
        public void tick(BlockState state, ServerWorld world, BlockPos pos, Random random) {
            int x = pos.getX();
            int y = pos.getY();
            int z = pos.getZ();
            if (((new Object() {
                public boolean getValue(BlockPos pos, String tag) {
                    TileEntity tileEntity = world.getTileEntity(pos);
                    if (tileEntity != null)
                        return tileEntity.getTileData().getBoolean(tag);
                    return false;
                }
            }.getValue(new BlockPos((int) x, (int) y, (int) z), "repel")) == (true))) {
                world.setBlockState(pos, state.with(REPEL, Boolean.valueOf(true)), 3);
            } else {
                world.setBlockState(pos, state.with(REPEL, Boolean.valueOf(false)), 3);
            }
            super.tick(state, world, pos, random);
            {
                Map<String, Object> $_dependencies = new HashMap<>();
                MagnetUpdateTickProcedure.executeProcedure($_dependencies);
            }
            world.getPendingBlockTicks().scheduleTick(new BlockPos(x, y, z), this, 10);
        }

        @Override
        public INamedContainerProvider getContainer(BlockState state, World worldIn, BlockPos pos) {
            TileEntity tileEntity = worldIn.getTileEntity(pos);
            return tileEntity instanceof INamedContainerProvider ? (INamedContainerProvider) tileEntity : null;
        }

        @Override
        public boolean hasTileEntity(BlockState state) {
            return true;
        }

        @Override
        public TileEntity createTileEntity(BlockState state, IBlockReader world) {
            return new CustomTileEntity();
        }

        @Override
        public boolean eventReceived(BlockState state, World world, BlockPos pos, int eventID, int eventParam) {
            super.eventReceived(state, world, pos, eventID, eventParam);
            TileEntity tileentity = world.getTileEntity(pos);
            return tileentity == null ? false : tileentity.receiveClientEvent(eventID, eventParam);
        }

        @Override
        public boolean hasComparatorInputOverride(BlockState state) {
            return true;
        }

        @Override
        public int getComparatorInputOverride(BlockState blockState, World world, BlockPos pos) {
            TileEntity tileentity = world.getTileEntity(pos);
            if (tileentity instanceof CustomTileEntity)
                return Container.calcRedstoneFromInventory((CustomTileEntity) tileentity);
            else
                return 0;
        }
    }

    public static class CustomTileEntity extends LockableLootTileEntity implements ISidedInventory {
        private NonNullList<ItemStack> stacks = NonNullList.<ItemStack>withSize(9, ItemStack.EMPTY);
        protected CustomTileEntity() {
            super(tileEntityType);
        }

        @Override
        public void read(BlockState blockState, CompoundNBT compound) {
            super.read(blockState, compound);
            if (!this.checkLootAndRead(compound)) {
                this.stacks = NonNullList.withSize(this.getSizeInventory(), ItemStack.EMPTY);
            }
            ItemStackHelper.loadAllItems(compound, this.stacks);
        }

        @Override
        public CompoundNBT write(CompoundNBT compound) {
            super.write(compound);
            if (!this.checkLootAndWrite(compound)) {
                ItemStackHelper.saveAllItems(compound, this.stacks);
            }
            return compound;
        }

        @Override
        public SUpdateTileEntityPacket getUpdatePacket() {
            return new SUpdateTileEntityPacket(this.pos, 0, this.getUpdateTag());
        }

        @Override
        public CompoundNBT getUpdateTag() {
            return this.write(new CompoundNBT());
        }

        @Override
        public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
            this.read(this.getBlockState(), pkt.getNbtCompound());
        }

        @Override
        public int getSizeInventory() {
            return stacks.size();
        }

        @Override
        public boolean isEmpty() {
            for (ItemStack itemstack : this.stacks)
                if (!itemstack.isEmpty())
                    return false;
            return true;
        }

        @Override
        public ITextComponent getDefaultName() {
            return new StringTextComponent("magnet");
        }

        @Override
        public int getInventoryStackLimit() {
            return 64;
        }

        @Override
        public Container createMenu(int id, PlayerInventory player) {
            return ChestContainer.createGeneric9X3(id, player, this);
        }

        @Override
        public ITextComponent getDisplayName() {
            return new StringTextComponent("Magnet");
        }

        @Override
        protected NonNullList<ItemStack> getItems() {
            return this.stacks;
        }

        @Override
        protected void setItems(NonNullList<ItemStack> stacks) {
            this.stacks = stacks;
        }

        @Override
        public boolean isItemValidForSlot(int index, ItemStack stack) {
            return true;
        }

        @Override
        public int[] getSlotsForFace(Direction side) {
            return IntStream.range(0, this.getSizeInventory()).toArray();
        }

        @Override
        public boolean canInsertItem(int index, ItemStack stack, @Nullable Direction direction) {
            return this.isItemValidForSlot(index, stack);
        }

        @Override
        public boolean canExtractItem(int index, ItemStack stack, Direction direction) {
            return true;
        }
        private final LazyOptional<? extends IItemHandler>[] handlers = SidedInvWrapper.create(this, Direction.values());
        @Override
        public <T> LazyOptional<T> getCapability(Capability<T> capability, @Nullable Direction facing) {
            if (!this.removed && facing != null && capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
                return handlers[facing.ordinal()].cast();
            return super.getCapability(capability, facing);
        }

        @Override
        public void remove() {
            super.remove();
            for (LazyOptional<? extends IItemHandler> handler : handlers)
                handler.invalidate();
        }
    }
}
 

Joined Dec 2017
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Btw I`m on 1.16.5 2021.1 and…
Mon, 05/31/2021 - 16:21

Btw I`m on 1.16.5 2021.1 and the block also has DUNSWE Rotation if that makes any difference...

Joined Feb 2018
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Does this work for 1.16.5? I…
Mon, 05/31/2021 - 22:00

Does this work for 1.16.5?

I tried to get it to work with a custom block model, and it seemed to just break it. Granted, I didn't perfectly follow the tutorial, I made some minor changes, such as changing the STATE type to be AGE_0_2, because I only had three blockstates, and instead of changing the "facing=x" variations to be "age=x" variations in the blockstates JSON file, I changed it to be similar to how buttons work, adding in a "facing=north,age=0", "facing=north,age=1", "facing=north,age=2", "facing=east,age=0", etc. so that way I could have it face different directions and have different age-states, but I might have done that wrong as well.
Here are the JSON and Java files for inspection. If you need the workspace, I can export that as well, but it's a fairly large one.

 

Joined Feb 2018
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Ok, I just tested changing…
Mon, 05/31/2021 - 22:15

Ok, I just tested changing the Blockstate JSON to not take into account the direction it's facing, and it seems to work flawlessly, just without a directional difference, which is a pity. So clearly, something in that file is what was breaking it.

Joined Feb 2018
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Ok, looking at the…
Mon, 05/31/2021 - 22:35

Ok, looking at the decompressed 1.16.5 files, I can see that what I want to copy is the Cocoa Bean Pod blockstate setup. It seems that maybe what caused the error was that I had to have the blockstates defined as "age=x,facing=x" instead of "facing=x,age=x". I'll follow up after some testing.

Joined Feb 2018
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Alright, it worked! So if…
Mon, 05/31/2021 - 22:56

Alright, it worked! So if anyone wants to be able to have multiple blockstates and have it face multiple directions, you're going to want to use a variation of this code for the blockstate JSON file:
 

{
  "variants": {
    "age=0,facing=east": {
        "model": "vftweaks:block/spinning_wheel",
        "y": 90
    },
    "age=0,facing=north": {
        "model": "vftweaks:block/spinning_wheel"
    },
    "age=0,facing=south": {
      "model": "vftweaks:block/spinning_wheel",
      "y": 180
    },
    "age=0,facing=west": {
      "model": "vftweaks:block/spinning_wheel",
      "y": 270
    },
    "age=1,facing=east": {
      "model": "vftweaks:block/spinning_wheel_state1",
      "y": 90
    },
    "age=1,facing=north": {
      "model": "vftweaks:block/spinning_wheel_state1"
    },
    "age=1,facing=south": {
      "model": "vftweaks:block/spinning_wheel_state1",
      "y": 180
    },
    "age=1,facing=west": {
      "model": "vftweaks:block/spinning_wheel_state1",
      "y": 270
    },
    "age=2,facing=east": {
      "model": "vftweaks:block/spinning_wheel_state2",
      "y": 90
    },
    "age=2,facing=north": {
      "model": "vftweaks:block/spinning_wheel_state2"
    },
    "age=2,facing=south": {
      "model": "vftweaks:block/spinning_wheel_state2",
      "y": 180
    },
    "age=2,facing=west": {
      "model": "vftweaks:block/spinning_wheel_state2",
      "y": 270
    }
  }
}

 

Joined Dec 2017
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
Ok thx Cyndi4U it seems to…
Tue, 06/01/2021 - 11:37

Ok thx Cyndi4U it seems to work now but theres just one catch my block has 5 Blockstates but the closest I can select is

BlockStateProperties.AGE_0_5;

but I need a AGE_0_4 I`m going to make another block later on that will have 100 but you can only select up to AGE_0_25 so how can you "add" more blockstates or can I make 2 variables that use 5 Blockstates each + 4 Directions meaning 4*5*5 = 100 and in the JSON write something like "age1=0,age2=0,facing=east" ??

Joined Feb 2018
Points:

User statistics:

  • Modifications:
  • Forum topics:
  • Wiki pages:
  • MCreator plugins:
  • Comments:
I'm... Not entirely sure…
Tue, 06/01/2021 - 22:23

I'm... Not entirely sure what you're asking of me, but you can actually just use AGE_0_5, but never use the sixth age state.
If you need 100 blockstates, then yes, I would think you could just combine AGE_0_25 with the four directions, as 26*4 is 104, and then just not use the last four states (don't use age=25).