Jump to content

Recommended Posts

Posted

I started working on a project about a year ago now that I just started to actually complete. I spent about four hours creating the tile entity to create a pipe that teleports you to a location based on the information stored. However, when I close the world and reload it, the client side does not seem to be able to load up the information stored in the nbt while the server side can. I'm not the greatest at tile entities so I was wondering if anyone could help me fix this problem.

 

This is my tile entity:

package com.championash5357.supermariobrothers.tileentity;

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;

public class TileEntityWarpPipe extends TileEntity {
	
	private double xCoord, yCoord, zCoord;

	@Override
	public void readFromNBT(NBTTagCompound compound) {
		super.readFromNBT(compound);
		this.xCoord = compound.getDouble("XCoordinate");
		this.yCoord = compound.getDouble("YCoordinate");
		this.zCoord = compound.getDouble("ZCoordinate");
		System.out.println("NBT X: "+ compound.getInteger("XCoordinate"));
		System.out.println("NBT Y: "+ compound.getInteger("YCoordinate"));
		System.out.println("NBT Z: "+ compound.getInteger("ZCoordinate"));
	}
	
	@Override
	public NBTTagCompound writeToNBT(NBTTagCompound compound) {
		super.writeToNBT(compound);
		compound.setDouble("XCoordinate", this.xCoord);
		compound.setDouble("YCoordinate", this.yCoord);
		compound.setDouble("ZCoordinate", this.zCoord);
		return compound;
	}
	
	public void setCoordinates(ItemStack wrench) {
		NBTTagCompound nbt = (NBTTagCompound)wrench.getTagCompound().getTag("coordinates");
		this.xCoord = nbt.getDouble("XCoord");
		this.yCoord = nbt.getDouble("YCoord");
		this.zCoord = nbt.getDouble("ZCoord");
	}
	
	public double getX() {
		return this.xCoord;
	}
	
	public double getY() {
		return this.yCoord;
	}
	
	public double getZ() {
		return this.zCoord;
	}
}

 

This is my block code:

package com.championash5357.supermariobrothers.blocks;

import java.util.List;

import org.lwjgl.input.Keyboard;

import com.championash5357.supermariobrothers.client.Reference.SuperMario;
import com.championash5357.supermariobrothers.init.MarioBlocks;
import com.championash5357.supermariobrothers.items.ItemWrench;
import com.championash5357.supermariobrothers.tileentity.TileEntityWarpPipe;

import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

public class BlockWarpPipeBase extends BlockSuperMarioBros implements ITileEntityProvider{
	
	protected static final AxisAlignedBB PIPE_NF = new AxisAlignedBB(0.8125D, 0D, 0D, 0.875D, 1D, 0.8125D);
	protected static final AxisAlignedBB PIPE_NR = new AxisAlignedBB(0D, 0D, 0.8125D, 0.8125D, 1D, 0.875D);
	protected static final AxisAlignedBB PIPE_ND = new AxisAlignedBB(0D, 0D, 0D, 0.8125D, 0.0625D, 0.8125D);
	protected static final AxisAlignedBB PIPE_WF = new AxisAlignedBB(0.8125D, 0D, 0.1875D, 0.875D, 1D, 1D);
	protected static final AxisAlignedBB PIPE_WL = new AxisAlignedBB(0D, 0D, 0.125D, 0.8125D, 1D, 0.1875D);
	protected static final AxisAlignedBB PIPE_WD = new AxisAlignedBB(0D, 0D, 0.1875D, 0.8125D, 0.0625D, 1D);
	protected static final AxisAlignedBB PIPE_SB = new AxisAlignedBB(0.125D, 0D, 0.1875D, 0.1875D, 1D, 1D);
	protected static final AxisAlignedBB PIPE_SL = new AxisAlignedBB(0.1875D, 0D, 0.125D, 1D, 1D, 0.1875D);
	protected static final AxisAlignedBB PIPE_SD = new AxisAlignedBB(0.1875D, 0D, 0.1875D, 1D, 0.0625D, 1D);
	protected static final AxisAlignedBB PIPE_EB = new AxisAlignedBB(0.125D, 0D, 0D, 0.1875D, 1D, 0.8125D);
	protected static final AxisAlignedBB PIPE_ER = new AxisAlignedBB(0.1875D, 0D, 0.8125D, 1D, 1D, 0.875D);
	protected static final AxisAlignedBB PIPE_ED = new AxisAlignedBB(0.1875D, 0D, 0D, 1D, 0.0625D, 0.8125D);
	public static final PropertyDirection FACING = BlockHorizontal.FACING;
	
	public BlockWarpPipeBase() { 
		super(Material.ROCK);
		setUnlocalizedName(SuperMario.WARP_PIPE_BASE.getUnlocalizedName());
		setRegistryName(SuperMario.WARP_PIPE_BASE.getRegistryName());
		setWikiName(SuperMario.WARP_PIPE_BASE.getWikiName());
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH));
	}
	
	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) {
		ItemStack stack = playerIn.getHeldItem(hand);
		if(stack != null) {
			if(stack.getItem() instanceof ItemWrench) {
				if(stack.getItem().hasEffect(stack)) {
					TileEntityWarpPipe pipe = (TileEntityWarpPipe)worldIn.getTileEntity(pos);
					pipe.setCoordinates(stack);
					NBTTagCompound nbt = (NBTTagCompound)stack.getTagCompound().getTag("coordinates");
					double x = nbt.getDouble("XCoord");
					double y = nbt.getDouble("YCoord");
					double z = nbt.getDouble("ZCoord");
					stack.func_190918_g(1);
					if(!worldIn.isRemote) playerIn.addChatMessage(new TextComponentString("This warp pipe at " + TextFormatting.GOLD + pos.getX() + ", " + pos.getY() + ", " + pos.getZ() + TextFormatting.WHITE + " will now teleport the player to " + TextFormatting.GOLD + x + ", " + y + ", " + z + TextFormatting.WHITE + "."));
				}
			}
		}
		return true;
	}
	
	@Override
	public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos) {
		return FULL_BLOCK_AABB.offset(pos);
	}
	
	@Override
	public void onEntityCollidedWithBlock(World worldIn, BlockPos pos, IBlockState state, Entity entityIn) {
		if(entityIn instanceof EntityPlayer) teleport((EntityPlayer)entityIn, pos, worldIn);
		super.onEntityCollidedWithBlock(worldIn, pos, state, entityIn);
	}
	
	private void teleport(EntityPlayer player, BlockPos pos, World world) {
		TileEntityWarpPipe pipe = (TileEntityWarpPipe)world.getTileEntity(pos);
		if(player.isSneaking()) {
			player.setLocationAndAngles(pipe.getX(), pipe.getY(), pipe.getZ(), player.rotationYaw, player.rotationPitch);
		}
	}
	
	@Override
	public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
        EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);
        switch(enumfacing) {
			case EAST:
				return PIPE_ED;
			case SOUTH:
				return PIPE_SD;
			case WEST:
				return PIPE_WD;
			case NORTH:
			default:
				return PIPE_ND;
        }
    }
	
	@Override
	public void addCollisionBoxToList(IBlockState state, World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn) {
		addCollisionBoxToList(pos, entityBox, collidingBoxes, state.getBoundingBox(worldIn, pos));
		addCollisionBoxToList(pos, entityBox, collidingBoxes, this.getFrontShape(state));
		addCollisionBoxToList(pos, entityBox, collidingBoxes, this.getSideShape(state));
	}
	
	private AxisAlignedBB getFrontShape(IBlockState state) {
		switch((EnumFacing)state.getValue(FACING)) {
			case EAST:
				return PIPE_EB;
			case SOUTH:
				return PIPE_SB;
			case WEST:
				return PIPE_WF;
			case NORTH:
			default:
				return PIPE_NF;
		}
	}
	
	private AxisAlignedBB getSideShape(IBlockState state) {
		switch ((EnumFacing)state.getValue(FACING))
        {
            case EAST:
                return PIPE_ER;
            case SOUTH:
                return PIPE_SL;
            case WEST:
                return PIPE_WL;
            case NORTH:
            default:
                return PIPE_NR;
        }
	}
	
	public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
    {
        this.setDefaultFacing(worldIn, pos, state);
    }

    private void setDefaultFacing(World worldIn, BlockPos pos, IBlockState state)
    {
        if (!worldIn.isRemote)
        {
            IBlockState iblockstate = worldIn.getBlockState(pos.north());
            IBlockState iblockstate1 = worldIn.getBlockState(pos.south());
            IBlockState iblockstate2 = worldIn.getBlockState(pos.west());
            IBlockState iblockstate3 = worldIn.getBlockState(pos.east());
            EnumFacing enumfacing = (EnumFacing)state.getValue(FACING);

            if (enumfacing == EnumFacing.NORTH && iblockstate.isFullBlock() && !iblockstate1.isFullBlock())
            {
                enumfacing = EnumFacing.SOUTH;
            }
            else if (enumfacing == EnumFacing.SOUTH && iblockstate1.isFullBlock() && !iblockstate.isFullBlock())
            {
                enumfacing = EnumFacing.NORTH;
            }
            else if (enumfacing == EnumFacing.WEST && iblockstate2.isFullBlock() && !iblockstate3.isFullBlock())
            {
                enumfacing = EnumFacing.EAST;
            }
            else if (enumfacing == EnumFacing.EAST && iblockstate3.isFullBlock() && !iblockstate2.isFullBlock())
            {
                enumfacing = EnumFacing.WEST;
            }

            worldIn.setBlockState(pos, state.withProperty(FACING, enumfacing), 2);
        }
    }
    
    public static void setState(boolean active, World worldIn, BlockPos pos)
    {
    	IBlockState iblockstate = worldIn.getBlockState(pos);
    	worldIn.setBlockState(pos, MarioBlocks.warp_pipe_base.getDefaultState().withProperty(FACING, iblockstate.getValue(FACING)), 3);
    	worldIn.setBlockState(pos, MarioBlocks.warp_pipe_base.getDefaultState().withProperty(FACING, iblockstate.getValue(FACING)), 3);
    }
	
    public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
    {
        return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
    }
    
    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        worldIn.setBlockState(pos, state.withProperty(FACING, placer.getHorizontalFacing().getOpposite()), 2);
    }
    
    public IBlockState getStateFromMeta(int meta)
    {
        EnumFacing enumfacing = EnumFacing.getFront(meta);

        if (enumfacing.getAxis() == EnumFacing.Axis.Y)
        {
            enumfacing = EnumFacing.NORTH;
        }

        return this.getDefaultState().withProperty(FACING, enumfacing);
    }
    
    public int getMetaFromState(IBlockState state)
    {
        return ((EnumFacing)state.getValue(FACING)).getIndex();
    }
    
    public IBlockState withRotation(IBlockState state, Rotation rot)
    {
        return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
    }
    
    public IBlockState withMirror(IBlockState state, Mirror mirrorIn)
    {
        return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
    }

    protected BlockStateContainer createBlockState()
    {
        return new BlockStateContainer(this, new IProperty[] {FACING});
    }
	
	@Override
	public boolean isOpaqueCube(IBlockState state) {
        return false;
    }

	@Override
	public boolean isFullCube(IBlockState state) {
        return false;
    }
	
	@Override
	public void func_190948_a(ItemStack stack, EntityPlayer player, List<String> tooltip, boolean advanced) {
		tooltip.add(""  + TextFormatting.DARK_RED + "Super Mario Bros.");
		tooltip.add("");
		if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
			tooltip.add("" + TextFormatting.GOLD + "One of the main modes of transportation that transports the traveler to the other end.");
		}
		else {
			tooltip.add("" + TextFormatting.WHITE + "Hold " + TextFormatting.AQUA + TextFormatting.UNDERLINE + "LShift" + TextFormatting.RESET + " for more information.");
		}
    }

	@Override
	public TileEntity createNewTileEntity(World worldIn, int meta) {
		return new TileEntityWarpPipe();
	}
}

 

Thank you for your time.

  • 2 weeks later...
Posted

Your problem is, that all the Data reading is performed Server side (because it is the Server providing the World data and such things). To solve this you have to send Packets when needed to the client to sync the data or provide a possibility for the client to request an data sync. it might be possible to achieve, what you want using standard tile entity update packets, I'm not sure about that... 

 

Further reference can be found in the Forge's docs under the Networking section (you should have read the Sides section before that). 

Posted

One more thing, when you add tooltips, you should not rely on hardcoded Strings, but rather use localized ones... 

(e. g. use I18n. format(String key, Object...  args), where key is a key defined in your lang files and args are arguments which are used in the resulting String like String.format does (this is generally prefered to String concatisation because it is far more flexible)) 

Posted
36 minutes ago, Major Tuvok said:

His class implicitly uses an empty constructor... 

(If none is specified java generates an empty public constructor...) 

My fault, I was looking at the Block class and not at the TileEntity. Anyways, don't use ITileEntityProvider, override

Block::hasTileEntity and Block::createTileEntity .

 

Posted
57 minutes ago, ArmamentHaki said:

My fault, I was looking at the Block class and not at the TileEntity. Anyways, don't use ITileEntityProvider, override

Block::hasTileEntity and Block::createTileEntity .

 

The reason I use ITileEntityProvider is because I'm overriding a custom class for blocks. ITileEntityProvider does the same as extending BlockContainer.

 

1 hour ago, Major Tuvok said:

Your problem is, that all the Data reading is performed Server side (because it is the Server providing the World data and such things). To solve this you have to send Packets when needed to the client to sync the data or provide a possibility for the client to request an data sync. it might be possible to achieve, what you want using standard tile entity update packets, I'm not sure about that... 

 

Further reference can be found in the Forge's docs under the Networking section (you should have read the Sides section before that). 

Thanks, I'll look into it.

Posted (edited)
8 minutes ago, ChampionAsh5357 said:

The reason I use ITileEntityProvider is because I'm overriding a custom class for blocks. ITileEntityProvider does the same as extending BlockContainer.

 

That doesn't change anything, it still shouldn't be used.

Edited by Choonster

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

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.