Jump to content

[1.10.2] Blocks that Re-Texture when clicked depending on what the player is holding


Recommended Posts

Posted (edited)

I'm recreating the mod Engineer's Toolbox for my personal use and in this mod you're able to configure a single block's sides for different ports or for the block to be used as different machines.

So for example I could choose what side power got inputed in by right clicking with a power input socket on the side I wanted.

Since this single block could have many different configurations depending on how many sockets I implement from the mod or if I create more I don't think I can create a massive list of blockstates.

 

So my question is what other options do I have for re-rendering a block's side through the block's onBlockActivated() method, AND are there any good tutorials for those methods that you know of.

Edited by 15Cyndaquil
Posted

This would be covered by IBlockStates pretty well.

 

All you have to do is properly define your blockstate json.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

I've gotten my block to now change dynamically with 6 different properties, thank you for sugesting IBlockStates Draco, and while i am able to save each state to a TileEntity as well as able to change the state through the same TileEntity .

 

I have the new problem of when i try to load the states through the TileEntity using the Overriden method readFromNBT() in the TileEntity it loads the default values i set for the states in the TileEntity when I have a non-null world instead of the values saved from the previous session..

Posted

Block code:

 

package com.cynda.cyndas_toolbox.block;

import com.cynda.cyndas_toolbox.CyndasToolbox;
import com.cynda.cyndas_toolbox.EnumHandler.SocketBlockSide;
import com.cynda.cyndas_toolbox.tiles.Test;
import net.minecraft.block.Block;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import javax.annotation.Nullable;

public class BlockSocket extends Block implements ITileEntityProvider{

    final static PropertyEnum<SocketBlockSide> EAST = PropertyEnum.create("east", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> WEST = PropertyEnum.create("west", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> NORTH = PropertyEnum.create("north", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> SOUTH = PropertyEnum.create("south", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> UP = PropertyEnum.create("up", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> DOWN = PropertyEnum.create("down", SocketBlockSide.class);

    

    public BlockSocket(String unlocalizedName){
        super(Material.IRON);
        setUnlocalizedName(unlocalizedName);
        setCreativeTab(CyndasToolbox.tabBlocks);



        setDefaultState(getBlockState().getBaseState().withProperty(EAST, SocketBlockSide.BLANK));
        setDefaultState(getBlockState().getBaseState().withProperty(WEST, SocketBlockSide.BLANK));
        setDefaultState(getBlockState().getBaseState().withProperty(NORTH, SocketBlockSide.BLANK));
        setDefaultState(getBlockState().getBaseState().withProperty(SOUTH, SocketBlockSide.BLANK));
        setDefaultState(getBlockState().getBaseState().withProperty(UP, SocketBlockSide.BLANK));
        setDefaultState(getBlockState().getBaseState().withProperty(DOWN, SocketBlockSide.BLANK));
    }


    @SideOnly(Side.CLIENT)
    @Override
    public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, @Nullable ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ) {

        if(!worldIn.isRemote) {
//            worldIn.markBlocksDirtyVertical(pos.getX(), pos.getZ(), pos.getX(), pos.getZ());

            TileEntity te = worldIn.getTileEntity(pos);
            if (te != null && te instanceof Test) {
                Test tileTest = (Test) te;
                state = setFaceRandom(state, getSide(side), playerIn, tileTest, side);
                worldIn.setBlockState(pos, state);
                tileTest.markDirty();
                if (playerIn.isSneaking()) {
                    playerIn.addChatMessage(new TextComponentString("Clicks " + tileTest.getClicks()));
                } else {
                    tileTest.setClicks(tileTest.getClicks() + 1);
                    tileTest.markDirty();
                }
            }
        }
        return true;
    }

    private IBlockState setFaceRandom(IBlockState state, PropertyEnum side, EntityPlayer playerIn, Test tileTest, EnumFacing sideFace){
        if(playerIn.getHeldItemMainhand()==null){
            state = state.withProperty(side, SocketBlockSide.INPUT_POWER);
            tileTest.setSide(sideFace, "input_power");
            System.out.println("INPUT");
        }else {
            state = state.withProperty(side, SocketBlockSide.BLANK);
            tileTest.setSide(sideFace, "blank");
            System.out.println("BLANK");
        }
        return state;
    }

    private PropertyEnum getSide(EnumFacing side){
        PropertyEnum enumSide = EAST;
        switch (side){
            case EAST:
                enumSide = EAST;
                break;
            case WEST:
                enumSide = WEST;
                break;
            case NORTH:
                enumSide = NORTH;
                break;
            case SOUTH:
                enumSide = SOUTH;
                break;
            case UP:
                enumSide = UP;
                break;
            case DOWN:
                enumSide = DOWN;
                break;
        }
        return enumSide;
    }

    public void setEast(SocketBlockSide value){

        setDefaultState(getBlockState().getBaseState().withProperty(EAST, value));
    }
    @Override
    public IBlockState getStateFromMeta(int meta) {return this.getDefaultState();}
    @Override
    public int getMetaFromState(IBlockState state) {return 0;}

    //Methods for ITileEntityProvider
    @Override
    public TileEntity createNewTileEntity(World worldIn, int meta) { return new Test(); }

    @Override
    protected BlockStateContainer createBlockState() {
        return new BlockStateContainer(this, EAST, WEST, NORTH, SOUTH, UP, DOWN);
    }


    public PropertyEnum<SocketBlockSide> getEAST() {return EAST;}
    public PropertyEnum<SocketBlockSide> getWEST() {return WEST;}
    public PropertyEnum<SocketBlockSide> getNORTH() {return NORTH;}
    public PropertyEnum<SocketBlockSide> getSOUTH() {return SOUTH;}
    public PropertyEnum<SocketBlockSide> getUP() {return UP;}
    public PropertyEnum<SocketBlockSide> getDOWN() {return DOWN;}
}

 

TileEntity code:

 

package com.cynda.cyndas_toolbox.tiles;

import akka.io.Tcp;
import com.cynda.cyndas_toolbox.EnumHandler.SocketBlockSide;
import com.cynda.cyndas_toolbox.block.BlockSocket;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class Test extends TileEntity{

    private int clicks = 0;
    private int east = 0;

    private IntegerProperty eastProptery = new SimpleIntegerProperty(east);
//    private String west = "blank";
//    private String north = "blank";
//    private String south = "blank";
//    private String up = "blank";
//    private String down = "blank";

    private World world;


    final static PropertyEnum<SocketBlockSide> EAST = PropertyEnum.create("east", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> WEST = PropertyEnum.create("west", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> NORTH = PropertyEnum.create("north", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> SOUTH = PropertyEnum.create("south", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> UP = PropertyEnum.create("up", SocketBlockSide.class);
    final static PropertyEnum<SocketBlockSide> DOWN = PropertyEnum.create("down", SocketBlockSide.class);

    public Test(){
        eastProptery.addListener(new InvalidationListener() {
            @Override
            public void invalidated(Observable e) {
                boolean firstLoad = true;
                if(getWorld()==null){
                    System.out.println(e + " East + null");
//                        int x = Integer.valueOf(e.toString().substring(e.toString().length() - 2, e.toString().length() - 1)) - 1;
//                        System.out.println(x);
//                        eastProptery.setValue(x);
                }else {
                    System.out.println(e + " East");
                    final IBlockState state = getWorld().getBlockState(getPos());
//
////            EAST = ((BlockSocket) getBlockType()).getEAST();
////            WEST = ((BlockSocket) getBlockType()).getWEST();
////            NORTH = ((BlockSocket) getBlockType()).getNORTH();
////            SOUTH = ((BlockSocket) getBlockType()).getSOUTH();
////            UP = ((BlockSocket) getBlockType()).getUP();
////            DOWN = ((BlockSocket) getBlockType()).getDOWN();
//
                    setState(state);
                }
            }
        });
    }

    @Override
    public NBTTagCompound writeToNBT(NBTTagCompound compound) {
        compound.setInteger("Clicks", clicks);
        compound.setInteger("East", east);
//        compound.setString("West", west);
//        compound.setString("North", north);
//        compound.setString("South", south);
//        compound.setString("Up", up);
//        compound.setString("Down", down);
        markDirty();
        super.writeToNBT(compound);

        return compound;
    }




    @Override
    public void readFromNBT(NBTTagCompound compound){
        System.out.println("Hello NBTReadNOW");
        super.readFromNBT(compound);
        if(getWorld()==null){
            clicks = compound.getInteger("Clicks");
            east = compound.getInteger("East");
            eastProptery.setValue(east);
            System.out.println(compound.getInteger("East")+" Read "+compound.getInteger("Clicks"));
        }
        System.out.println(getWorld());
        if(getWorld()!=null) {
            System.out.println(eastProptery.intValue() +" East Value");
            final IBlockState state = getWorld().getBlockState(getPos());
            setState(state);

        }
    }



    public int getClicks() {return clicks; }

    public void setClicks(int clicks) { this.clicks = clicks; markDirty();}
    public void setEast(int east){this.east = east; eastProptery.setValue(east);}

    public void setSide(EnumFacing side, String value) {
        switch (side){
            case EAST:
                east = SocketBlockSide.getName(value).getID();
                eastProptery.setValue(east);
//                System.out.println(eastProptery);
                markDirty();
                break;
            case WEST:
//                west = value;
                markDirty();
                break;
            case NORTH:
//                north = value;
                markDirty();
                break;
            case SOUTH:
//                south = value;
                markDirty();
                break;
            case UP:
//                up = value;
                markDirty();
                break;
            case DOWN:
//                down = value;
                markDirty();
                break;
        }

    }


    public void setState(IBlockState state){
        System.out.println(east+" Set State");
        state = state.withProperty(EAST, SocketBlockSide.values()[eastProptery.intValue()]);
//        state = state.withProperty(WEST, SocketBlockSide.getName(west));
//        state = state.withProperty(NORTH, SocketBlockSide.getName(north));
//        state = state.withProperty(SOUTH, SocketBlockSide.getName(south));
//        state = state.withProperty(UP, SocketBlockSide.getName(up));
//        state = state.withProperty(DOWN, SocketBlockSide.getName(down));
        getWorld().setBlockState(pos, state);
        System.out.println("set BlockState"+getPos().toString()+state.toString());
    }


    /**
     * This controls whether the tile entity gets replaced whenever the block state
     * is changed. Normally only want this when block actually is replaced.
     */
    @Override
    public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newState)
    {
        return (oldState.getBlock() != newState.getBlock());
    }


}
Posted

So I think I know what the issue is. My theory is that there are two tileEntities. one on the server and one on the client. when the tileEntities are created the server side one doesn't initially have a world object so I cant set a block's state in the readFromNBT() method from the server side, and when the client creates its tileEntities it doesnt have the nbt Data the server has so it creates a default one.

 

I've tried to sync them by requesting the information from the server when the client loads it's tileEntities but from what i can see it doesnt get the data quick enough to be useful for when the game renders in.

 

Does anyone know either another way to save the blockstate that would be more reliable or a way to get the nbt data to sync before the game loads.

Posted

You are essentially correct on all points.

 

Have you overridden these three methods? One of them is explicitly for the purpose of telling the client what the nbt data was when the TE was loaded from disk.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • logs too big for one pastebin https://pastebin.com/ZjUGHu3u  https://pastebin.com/RqCUZf3X  https://pastebin.com/6ZPS99nD
    • You probably used jd-gui to open it, didn't you? Nothing wrong with that, I also made that mistake, except that Notch was a smart guy and he obfuscated the code. That's why you only see files called "a", "b", "c" and then a file that combines them all. As I said, use RetroMCP to deobfuscate the code so that you will 100% understand it and be able to navigate it.
    • Decompiling minecraft indev, infdev, alpha, beta or whichever legacy version is really easy. I'm not a plug, I just also got interested in modding legacy versions (Infdev to be specific). Use https://github.com/MCPHackers/RetroMCP-Java Once you install their client and the Zulu Architecture that they say they recommend (or use your own Java). I encountered some problems, so I run it with: "java -jar RetroMCP-Java-CLI.jar". You should run it in a seperate folder (not in downloads), otherwise the files and folders will go all over the place. How to use RetroMCP: Type setup (every time you want change version), copy-paste the version number from their list (they support indev), write "decompile" and done! The code will now be deobfuscated and filenames will be normal, instead of "a", "b" and "c"! Hope I helped you, but I don't expect you to reply, as this discussion is 9 years old! What a piece of history!  
    • I know that this may be a basic question, but I am very new to modding. I am trying to have it so that I can create modified Vanilla loot tables that use a custom enchantment as a condition (i.e. enchantment present = item). However, I am having trouble trying to implement this; the LootItemRandomChanceWithEnchantedBonusCondition constructor needs a Holder<Enchantment> and I am unable to use the getOrThrow() method on the custom enchantment declared in my mod's enchantments class. Here is what I have so far in the GLM:   protected void start(HolderLookup.Provider registries) { HolderLookup.RegistryLookup<Enchantment> registrylookup = registries.lookupOrThrow(Registries.ENCHANTMENT); LootItemRandomChanceWithEnchantedBonusCondition lootItemRandomChanceWithEnchantedBonusCondition = new LootItemRandomChanceWithEnchantedBonusCondition(0.0f, LevelBasedValue.perLevel(0.07f), registrylookup.getOrThrow(*enchantment here*)); this.add("nebu_from_deepslate", new AddItemModifier(new LootItemCondition[]{ LootItemBlockStatePropertyCondition.hasBlockStateProperties(Blocks.DEEPSLATE).build(), LootItemRandomChanceCondition.randomChance(0.25f).build(), lootItemRandomChanceWithEnchantedBonusCondition }, OrichalcumItems.NEBU.get())); }   Inserting Enchantments.[vanilla enchantment here] actually works but trying to declare an enchantment from my custom enchantments class as [mod enchantment class].[custom enchantment] does not work even though they are both a ResourceKey and are registered in Registries.ENCHANTMENT. Basically, how would I go about making it so that a custom enchantment declared as a ResourceKey<Enchantment> of value ResourceKey.create(Registries.ENCHANTMENT, ResourceLocation.fromNamespaceAndPath([modid], [name])), declared in a seperate enchantments class, can be used in the LootItemRandomChanceWithEnchantedBonusCondition constructor as a Holder? I can't use getOrThrow() because there is no level or block entity/entity in the start() method and it is running as datagen. It's driving me nuts.
  • Topics

×
×
  • Create New...

Important Information

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