Started by
Max094_Reikeb
on
Topic category: User side tutorials
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)
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?
I don't know what the "3' does. You must keep it however.
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?
You just saved mah brainz! Thanks for the help ;)
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)
Never mind... I solved it!! (It was on the blockstate)
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();
}
}
}
Btw I`m on 1.16.5 2021.1 and the block also has DUNSWE Rotation if that makes any difference...
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.
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.
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.
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:
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" ??
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).