Jump to content

[Solved][1.10.2] Redstone power returned by TileEntity is always 0


Recommended Posts

Posted (edited)

I am creating a singleplayer-only mod where you can control an Arduino from within Minecraft and vice versa. The communication is already working almost perfectly (apart from some rare interferences between incoming and outgoing serial data).

When the receiver TileEntity gets data from the SerialPort and the value is different than the one stored in the TileEntity, the Integer is stored in the TileEntity, an update tag is sent to the client and World#notifyNeighborsOfStateChange(BlockPos, Block) is called. This all happens in updateValue(int value). This leads to getWeakPower() being called on the block which in my block returns getStrongPower() which accesses the TileEntity and returns the power value stored in it. The problem is that for some reason the method getPower() in my TileEntity always returns 0 but if I go through the update of the value, it is correctly assigned and if the value to assign is 0, I can even see that the power stored in the TileEntity is 15 before the new value is assigned.

 

This is my TileEntity:

package XFactHD.mineduino.common.blocks;

import XFactHD.mineduino.common.utils.DimBlockPos;
import XFactHD.mineduino.common.utils.serial.SerialHandler;
import XFactHD.mineduino.common.utils.serial.ThreadCommHandler;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class TileEntitySerialReceiver extends TileEntitySerial implements ITickable
{
    private DimBlockPos dimPos = null;
    private boolean initialized = false;
    private int ticks = 0;
    private String pin = "";
    private SerialHandler.PinMode mode = SerialHandler.PinMode.NONE;
    private int power = 0;

    @Override
    public void update()
    {
        if (dimPos == null) { dimPos = new DimBlockPos(world.provider.getDimension(), pos); }
        if (!world.isRemote)
        {
            initialize();
            if (initialized && mode != SerialHandler.PinMode.IR && SerialHandler.getSerialHandler().isInitialized())
            {
                if (ticks == 10)
                {
                    ticks = 0;
                    ThreadCommHandler.sendData(dimPos, pin, mode, 0);
                }
                ticks += 1;
            }
        }
    }

    public void updateValue(int value)
    {
        if (this.power != value)
        {
            this.power = value;
            notifyBlockUpdate();
            Block block = world.getBlockState(pos).getBlock();
            world.notifyNeighborsOfStateChange(pos, block);
        }
    }

    public int getPower()
    {
        return this.power;
    }

    @Override
    public void setPin(String pin)
    {
        this.pin = pin;
        notifyBlockUpdate();
    }

    @Override
    public void setMode(SerialHandler.PinMode mode)
    {
        if (ThreadCommHandler.getPinMode(pin) == SerialHandler.PinMode.NONE)
        {
            this.mode = mode;
            ThreadCommHandler.setPinMode(pin, mode);
            notifyBlockUpdate();
        }
    }

    @Override
    public String getPin()
    {
        return pin;
    }

    @Override
    public SerialHandler.PinMode getMode()
    {
        return mode;
    }

    @Override
    public void invalidate()
    {
        super.invalidate();
        ThreadCommHandler.removePosFromPin(pin, dimPos);
    }

    private void initialize()
    {
        if (!isInvalid() && !initialized && !pin.equals(""))
        {
            initialized = true;
            SerialHandler.PinMode pinMode = ThreadCommHandler.addPosToPin(pin, dimPos);
            if (pinMode == SerialHandler.PinMode.NONE)
            {
                ThreadCommHandler.setPinMode(pin, mode);
            }
            else
            {
                this.mode = pinMode;
                notifyBlockUpdate();
            }
        }
    }

    @Override
    public void writeCustomNBT(NBTTagCompound nbt)
    {
        nbt.setString("pin", pin);
        nbt.setInteger("mode", mode.ordinal());
    }

    @Override
    public void readCustomNBT(NBTTagCompound nbt)
    {
        pin = nbt.getString("pin");
        mode = SerialHandler.PinMode.values()[nbt.getInteger("mode")];
    }

    @Override
    public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IBlockState newState)
    {
        return oldState != newState;
    }

 

This is my Block:

package XFactHD.mineduino.common.blocks;

import XFactHD.mineduino.MineDuino;
import XFactHD.mineduino.common.utils.Reference;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
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.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.GameRegistry;

import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

@SuppressWarnings("deprecation")
public class BlockSerial extends Block
{
    public static final PropertyEnum<Type> TYPE = PropertyEnum.create("type", Type.class);

    public BlockSerial()
    {
        super(Material.IRON);
        setRegistryName(new ResourceLocation(Reference.MOD_ID, "block_serial"));
        setCreativeTab(CreativeTabs.REDSTONE);
        setHardness(5.0F);
        setResistance(10.0F);
        setSoundType(SoundType.METAL);
        setHarvestLevel("pickaxe", 1);
        GameRegistry.register(this);
        GameRegistry.register(new ItemBlockSerial(this).setRegistryName(getRegistryName()));
        GameRegistry.registerTileEntity(TileEntitySerialSender.class, "SerialSender");
        GameRegistry.registerTileEntity(TileEntitySerialReceiver.class, "SerialReceiver");
    }

    @Override
    public void getSubBlocks(Item item, CreativeTabs tab, List<ItemStack> list)
    {
        list.add(new ItemStack(this, 1, 0));
        list.add(new ItemStack(this, 1, 1));
    }

    @Override
    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, TYPE);
    }

    @Override
    public IBlockState getStateFromMeta(int meta)
    {
        return getDefaultState().withProperty(TYPE, Type.values()[meta]);
    }

    @Override
    public int getMetaFromState(IBlockState state)
    {
        return state.getValue(TYPE).ordinal();
    }

    @Override
    public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, @Nullable ItemStack heldItem, EnumFacing side, float hitX, float hitY, float hitZ)
    {
        if (!world.isRemote)
        {
            player.openGui(MineDuino.INSTANCE, 0, world, pos.getX(), pos.getY(), pos.getZ());
        }
        return true;
    }

    @Override
    public TileEntity createTileEntity(World world, IBlockState state)
    {
        return state.getValue(TYPE) == Type.SENDER ? new TileEntitySerialSender() : new TileEntitySerialReceiver();
    }

    @Override
    public boolean canProvidePower(IBlockState state)
    {
        return state.getValue(TYPE) == Type.RECEIVER;
    }

    @Override
    public int getStrongPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
    {
        if (state.getValue(TYPE) == Type.RECEIVER)
        {
            TileEntity te = world.getTileEntity(pos);
            if (te instanceof TileEntitySerialReceiver && Arrays.binarySearch(EnumFacing.HORIZONTALS, side) != -1)
            {
                return ((TileEntitySerialReceiver)te).getPower();
            }
        }
        return 0;
    }

    @Override
    public int getWeakPower(IBlockState state, IBlockAccess word, BlockPos pos, EnumFacing side)
    {
        return getStrongPower(state, word, pos, side);
    }

    @Override
    public void breakBlock(World world, BlockPos pos, IBlockState state)
    {
        super.breakBlock(world, pos, state);
        world.notifyNeighborsOfStateChange(pos, this);
    }

    @Override
    public int damageDropped(IBlockState state)
    {
        return state.getBlock().getMetaFromState(state);
    }

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

    @Nullable
    @Override
    public RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end)
    {
        AxisAlignedBB aabb = getCollisionBoundingBox(state, world, pos);
        return rayTrace(pos, start, end, aabb != null ? aabb : Block.FULL_BLOCK_AABB);
    }

    @Nullable
    @Override
    public AxisAlignedBB getCollisionBoundingBox(IBlockState state, World world, BlockPos pos)
    {
        return new AxisAlignedBB(0, 0, 0, 1, 6F/16F, 1);
    }

    @Override
    public AxisAlignedBB getSelectedBoundingBox(IBlockState state, World world, BlockPos pos)
    {
        //noinspection ConstantConditions
        return getCollisionBoundingBox(state, world, pos).offset(pos);
    }

    @Override
    public boolean isOpaqueCube(IBlockState state)
    {
        return false;
    }

    @Override
    public boolean isFullCube(IBlockState state)
    {
        return false;
    }

    @Override
    public boolean isFullBlock(IBlockState state)
    {
        return false;
    }

    public enum Type implements IStringSerializable
    {
        SENDER,
        RECEIVER;

        @Override
        public String getName()
        {
            return this == SENDER ? "tx" : "rx";
        }
    }

    public static class ItemBlockSerial extends ItemBlock
    {
        public ItemBlockSerial(Block b)
        {
            super(b);
            setHasSubtypes(true);
        }

        @Override
        public int getMetadata(int damage)
        {
            return damage;
        }
    }
}

 

Edited by XFactHD
Posted

Probably because there's two copies of TileEntity, one is for server and another for client. Try checking that part using breakpoints.

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

I checked and getWeakPower() is called on the server. That's why this makes absolutely no sense.

Posted

So is the power value updated on the server?

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

Yes, it is. When a value is received from the SerialPort, it is mapped to redstone values and then a call to MinecraftServer#addScheduledTask() sorts out the update of the value in the TileEntity.

Posted

So while updateValue(0) isn't called on both server & client, both getValue gives 0? It couldn't be...

I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP)

II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.

Posted

updateValue() with either value is only called on the server but I haven't checked what getPower() returns on the client.

Posted

I found the issue: It was by me using a custom BlockPos object to get the TileEntity from the World. This for some strange reason caused a second TileEntity to be created at the position of the Block instead of returning null.

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



×
×
  • Create New...

Important Information

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