Guest Posted August 7, 2017 Posted August 7, 2017 (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 August 12, 2017 by XFactHD Quote
Abastro Posted August 8, 2017 Posted August 8, 2017 Probably because there's two copies of TileEntity, one is for server and another for client. Try checking that part using breakpoints. Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
Guest Posted August 8, 2017 Posted August 8, 2017 I checked and getWeakPower() is called on the server. That's why this makes absolutely no sense. Quote
Abastro Posted August 8, 2017 Posted August 8, 2017 So is the power value updated on the server? Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
Guest Posted August 8, 2017 Posted August 8, 2017 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. Quote
Abastro Posted August 8, 2017 Posted August 8, 2017 So while updateValue(0) isn't called on both server & client, both getValue gives 0? It couldn't be... Quote I. Stellarium for Minecraft: Configurable Universe for Minecraft! (WIP) II. Stellar Sky, Better Star Rendering&Sky Utility mod, had separated from Stellarium.
Guest Posted August 9, 2017 Posted August 9, 2017 updateValue() with either value is only called on the server but I haven't checked what getPower() returns on the client. Quote
Guest Posted August 12, 2017 Posted August 12, 2017 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. Quote
Recommended Posts
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.