Jump to content

Recommended Posts

Posted

Heyo guys, I have started making a system for my blocks with connected textures to be configured (clicked with my chisel) to have the "mode" changed when clicked. These modes with either set it to connect to all blocks of it's same type with the same mode, or if in no connection mode, don't connect to any. I have this part down. My issue is, the mode int, which is stored in a tile entity is not syncing properly. I have

 @Override
    public Packet getDescriptionPacket() 
    {
    	NBTTagCompound nbt = new NBTTagCompound();
        writeToNBT(nbt);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, nbt);
    }
    
    @Override
    public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) 
    { 
        readFromNBT(pkt.func_148857_g());
        Minecraft.getMinecraft().renderGlobal.markBlockForRenderUpdate(xCoord, yCoord, zCoord);
    } 

in my TE already. I can change the mode fine with right clicking with my chisel (I have a mod that let's me see tile's nbt in game), but the block with not change it's render unit the world is reloaded. Even when I place blocks next to it, it acts like it's mode never changed. When the game restarts, the changed you made to the mode would show up, but you would have to reload for any new changes to take affect. I am confused as to what my issue is. Here is my full TE:

 package com.jmanpenilla.carbonmod.common.tileentity;

import net.minecraft.client.Minecraft;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
import net.minecraft.tileentity.TileEntity;

import com.jmanpenilla.carbonmod.common.lib.Names;

public class TileConnectedTextureBlock extends TileEntity {

public static final int connect1 = 0;
public static final int connect2 = 1;
public static final int connect3 = 2;
public static final int connect4 = 3;
public static final int noConnect = 4;

private int mode;

public void readFromNBT(NBTTagCompound nbt) {
	super.readFromNBT(nbt);
	mode = nbt.getInteger(Names.NBT.connectedtexturemode);
}

public void writeToNBT(NBTTagCompound nbt) {
	super.writeToNBT(nbt);
	nbt.setInteger(Names.NBT.connectedtexturemode, mode);
	markDirty();
}

public int getMode() {
	return mode;
}

public void setMode(int mode) {
	this.mode = mode;
	markDirty();
}

@Override
    public Packet getDescriptionPacket() 
    {
    	NBTTagCompound nbt = new NBTTagCompound();
        writeToNBT(nbt);
        return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, nbt);
    }
    
    @Override
    public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) 
    { 
        readFromNBT(pkt.func_148857_g());
        Minecraft.getMinecraft().renderGlobal.markBlockForRenderUpdate(xCoord, yCoord, zCoord);
    }

}

and here is my full block class (If you use this for your connected textures purposes, please give me a bit of credit, it took a while to update to 1.7.2)

 package com.jmanpenilla.carbonmod.common.block;

import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

import com.jmanpenilla.carbonmod.common.creativetabs.TabCarbonMod;
import com.jmanpenilla.carbonmod.common.item.ModItems;
import com.jmanpenilla.carbonmod.common.lib.Reference;
import com.jmanpenilla.carbonmod.common.tileentity.TileConnectedTextureBlock;

public class ModBlockConnectedTextureSolid extends BlockContainer
{	
public IIcon[] textures = new IIcon[47];
public static int[] textureRefByID = 
{		
	0, 0, 6, 6, 0, 0, 6, 6, 3, 3, 19, 15, 3, 3, 19, 15, 1, 1, 18, 18, 1, 1,
    13, 13, 2, 2, 23, 31, 2, 2, 27, 14, 0, 0, 6, 6, 0, 0, 6, 6, 3, 3, 19,
    15, 3, 3, 19, 15, 1, 1, 18, 18, 1, 1, 13, 13, 2, 2, 23, 31, 2, 2, 27,
    14, 4, 4, 5, 5, 4, 4, 5, 5, 17, 17, 22, 26, 17, 17, 22, 26, 16, 16, 20,
    20, 16, 16, 28, 28, 21, 21, 46, 42, 21, 21, 43, 38, 4, 4, 5, 5, 4, 4,
    5, 5, 9, 9, 30, 12, 9, 9, 30, 12, 16, 16, 20, 20, 16, 16, 28, 28, 25,
    25, 45, 37, 25, 25, 40, 32, 0, 0, 6, 6, 0, 0, 6, 6, 3, 3, 19, 15, 3, 3,
    19, 15, 1, 1, 18, 18, 1, 1, 13, 13, 2, 2, 23, 31, 2, 2, 27, 14, 0, 0,
    6, 6, 0, 0, 6, 6, 3, 3, 19, 15, 3, 3, 19, 15, 1, 1, 18, 18, 1, 1, 13,
    13, 2, 2, 23, 31, 2, 2, 27, 14, 4, 4, 5, 5, 4, 4, 5, 5, 17, 17, 22, 26,
    17, 17, 22, 26, 7, 7, 24, 24, 7, 7, 10, 10, 29, 29, 44, 41, 29, 29, 39,
    33, 4, 4, 5, 5, 4, 4, 5, 5, 9, 9, 30, 12, 9, 9, 30, 12, 7, 7, 24, 24,
    7, 7, 10, 10, 8, 8, 36, 35, 8, 8, 34, 11 
};

    protected String folder;

    public ModBlockConnectedTextureSolid(Material material, String location)
    {
        super(material);
        this.stepSound = soundTypeStone;
        folder = location;
        setHardness(0.3F);
        this.setCreativeTab(TabCarbonMod.tabCarbonMod);
    }
    
    @Override
    public void registerBlockIcons(IIconRegister iconRegistry)
    {
    	for (int i = 0; i < 47; i++) {
    		textures[i] = iconRegistry.registerIcon(Reference.MOD_ID + ":ct/" + folder + "/" + (i+1));
    		//System.out.println(Reference.MOD_ID + ":ct/" + folder + "/" + (i+1));
    	}
    }

    private boolean shouldConnect(Block cBlock) {
    	if(this == ModBlocks.compressedcarbonBlock && Reference.bricksConnectToBlocks) {
    		if(cBlock == ModBlocks.compressedcarbonBlock || cBlock == ModBlocks.compressedcarbonBrick) {
    			return true;
    		}
    	}
    	else if(this == ModBlocks.refinedBluchoriditeBlock && Reference.bricksConnectToBlocks) {
    		if(cBlock == ModBlocks.refinedBluchoriditeBlock || cBlock == ModBlocks.refinedBluchoriditeBrick) {
    			return true;
    		}
    	}
    	else {
    		return cBlock == this;
    	}
    	
    	return false;
    }
    
    public boolean shouldConnectToBlock(IBlockAccess w, int cx, int cy, int cz, int x, int y, int z) {
    	Block cBlock = w.getBlock(cx, cy, cz);
    	TileConnectedTextureBlock cTile = null;
    	TileConnectedTextureBlock tTile = (TileConnectedTextureBlock) w.getTileEntity(x, y, z);
    	if(w.getTileEntity(cx, cy, cz) != null) {
    		cTile = (TileConnectedTextureBlock) w.getTileEntity(cx, cy, cz);
    	} 	
    	    	
    	if(cTile != null && cTile.getMode() == tTile.getMode()) {
    		return shouldConnect(cBlock);
    	}
    	
    	System.out.println(tTile.getMode());
    	
	return false;   	
    }
    
    @Override
    public IIcon getIcon(IBlockAccess w, int x, int y, int z, int side)
    {
	boolean[] bitMatrix = new boolean[8];

	switch (side) {
		case 0:
			bitMatrix[0] = shouldConnectToBlock(w, x-1, y, z-1, x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y, z-1, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x+1, y, z-1, x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x-1, y, z, x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x+1, y, z, x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x-1, y, z+1, x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y, z+1, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x+1, y, z+1, x, y, z);
	 		break;
	 	case 1:
	 		bitMatrix[0] = shouldConnectToBlock(w, x-1, y, z-1, x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y, z-1, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x+1, y, z-1, x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x-1, y, z, x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x+1, y, z, x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x-1, y, z+1, x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y, z+1, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x+1, y, z+1, x, y, z);
	 		break;
	 	case 2:
	 		bitMatrix[0] = shouldConnectToBlock(w, x+(side==3?1:-1), y+1, z, x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y+1, z, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x+(side==2?1:-1), y+1, z, x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x+(side==3?1:-1), y, z, x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x+(side==2?1:-1), y, z, x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x+(side==3?1:-1), y-1, z, x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y-1, z, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x+(side==2?1:-1), y-1, z, x, y, z);
	 		break;
	 	case 3:
	 		bitMatrix[0] = shouldConnectToBlock(w, x+(side==2?1:-1), y+1, z, x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y+1, z, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x+(side==3?1:-1), y+1, z, x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x+(side==2?1:-1), y, z, x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x+(side==3?1:-1), y, z, x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x+(side==2?1:-1), y-1, z, x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y-1, z, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x+(side==3?1:-1), y-1, z, x, y, z);
	 		break;
	 	case 4:
	 		bitMatrix[0] = shouldConnectToBlock(w, x, y+1, z+(side==5?1:-1), x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y+1, z, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x, y+1, z+(side==4?1:-1), x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x, y, z+(side==5?1:-1), x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x, y, z+(side==4?1:-1), x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x, y-1, z+(side==5?1:-1), x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y-1, z, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x, y-1, z+(side==4?1:-1), x, y, z);
	 		break;
	 	case 5:
	 		bitMatrix[0] = shouldConnectToBlock(w, x, y+1, z+(side==4?1:-1), x, y, z);
	        bitMatrix[1] = shouldConnectToBlock(w, x, y+1, z, x, y, z);
	        bitMatrix[2] = shouldConnectToBlock(w, x, y+1, z+(side==5?1:-1), x, y, z);
	        bitMatrix[3] = shouldConnectToBlock(w, x, y, z+(side==4?1:-1), x, y, z);
	        bitMatrix[4] = shouldConnectToBlock(w, x, y, z+(side==5?1:-1), x, y, z);
	        bitMatrix[5] = shouldConnectToBlock(w, x, y-1, z+(side==4?1:-1), x, y, z);
	        bitMatrix[6] = shouldConnectToBlock(w, x, y-1, z, x, y, z);
	        bitMatrix[7] = shouldConnectToBlock(w, x, y-1, z+(side==5?1:-1), x, y, z);
	 		break;
	}
	        
        int idBuilder = 0;

        for (int i = 0; i <= 7; i++) idBuilder = idBuilder + (bitMatrix[i]?(i==0?1:(i==1?2:(i==2?4:(i==3?8:(i==4?16:(i==5?32:(i==6?64:128))))))):0);
        
        TileConnectedTextureBlock tile = (TileConnectedTextureBlock) w.getTileEntity(x, y, z);
        if(Reference.connectedTextures && tile.getMode() != TileConnectedTextureBlock.noConnect) {
        	return idBuilder>255||idBuilder<0?textures[0]:textures[textureRefByID[idBuilder]];
        }
        else {
        	return textures[0];
        }
    }

    @Override
    public IIcon getIcon(int side, int meta)
    {
    	return textures[0];
    }

    public boolean onBlockActivated(World w, int x, int y, int z, EntityPlayer p, int p_149727_6_, float p_149727_7_, float p_149727_8_, float p_149727_9_)
    {	
    	TileConnectedTextureBlock tile = (TileConnectedTextureBlock) w.getTileEntity(x, y, z);
    	
    	if(!w.isRemote && p.inventory.getCurrentItem() != null && p.inventory.getCurrentItem().getItem() == ModItems.chisel && p.inventory.getCurrentItem().getItemDamage() == 0) {
    		switch(tile.getMode()) {
    			case TileConnectedTextureBlock.connect1:
    				tile.setMode(TileConnectedTextureBlock.connect2);
    				return true;
    			case TileConnectedTextureBlock.connect2:
    				tile.setMode(TileConnectedTextureBlock.connect3);
    				return true;
    			case TileConnectedTextureBlock.connect3:
    				tile.setMode(TileConnectedTextureBlock.connect4);
    				return true;
    			case TileConnectedTextureBlock.connect4:
    				tile.setMode(TileConnectedTextureBlock.noConnect);
    				return true;
    			case TileConnectedTextureBlock.noConnect:
    				tile.setMode(TileConnectedTextureBlock.connect1);
    				return true;
    		}
    	}
        return false;
    }

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

 

Thanks for any help!

Posted

you'll notice System.out.println(tTile.getMode()); in shouldConnectToBlock();, this prints out 0, even after I make the change, until world reload.

 

EDIT: I figured out my issue, it is that the packet sending nbt to the client is only sent at world load/chunk load/tileentity loaded. I don't know how to force the packet to send, if anyone knows how, I guess that is the relevant question now. I want to be able to send it whenever the nbt is saved.

Posted

I cam across the same problem with my tile entitys when coding my mod, the way to get it to sync is to create your own packets.

To do this I first created a abstract class called IPacket which all my packet classes will extend;

 

[spoiler=IPacket Class]

import net.minecraft.entity.player.EntityPlayer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

public abstract class IPacket {

public abstract void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer);

public abstract void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer);

public abstract void handleClientSide(EntityPlayer player);

public abstract void handleServerSide(EntityPlayer player);

}

 

 

then from this I created a PacketPipeline class that will handle the packets for me

 

[spoiler=PacketPipeline Class]

import java.util.*;

import com.sirfatal.adventureplus.Network.Packets.*;
import com.sirfatal.adventureplus.utils.ModInfo;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetHandlerPlayServer;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.FMLEmbeddedChannel;
import cpw.mods.fml.common.network.FMLOutboundHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

@ChannelHandler.Sharable
public class PacketPipeline extends MessageToMessageCodec<FMLProxyPacket, IPacket> {

private EnumMap<Side, FMLEmbeddedChannel> channels;
private LinkedList<Class<? extends IPacket>> packets = new LinkedList<Class<? extends IPacket>>();
private boolean isPostInitialised = false;

/**
 * Register your packet with the pipeline. Discriminators are automatically
 * set.
 * 
 * @param clazz
 *            the class to register
 * 
 * @return whether registration was successful. Failure may occur if 256
 *         packets have been registered or if the registry already contains
 *         this packet
 */
public boolean registerPacket(Class<? extends IPacket> clazz) {
	if (this.packets.size() > 256) {
		// You should log here!!
		return false;
	}

	if (this.packets.contains(clazz)) {
		// You should log here!!
		return false;
	}

	if (this.isPostInitialised) {
		// You should log here!!
		return false;
	}

	this.packets.add(clazz);
	return true;
}

// In line encoding of the packet, including discriminator setting
@Override
protected void encode(ChannelHandlerContext ctx, IPacket msg, List<Object> out)
		throws Exception {
	ByteBuf buffer = Unpooled.buffer();
	Class<? extends IPacket> clazz = msg.getClass();
	if (!this.packets.contains(msg.getClass())) {
		throw new NullPointerException("No Packet Registered for: "
				+ msg.getClass().getCanonicalName());
	}

	byte discriminator = (byte) this.packets.indexOf(clazz);
	buffer.writeByte(discriminator);
	msg.encodeInto(ctx, buffer);
	FMLProxyPacket proxyPacket = new FMLProxyPacket(buffer.copy(), ctx.channel()
			.attr(NetworkRegistry.FML_CHANNEL).get());
	out.add(proxyPacket);
}

// In line decoding and handling of the packet
@Override
protected void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List<Object> out)
		throws Exception {
	ByteBuf payload = msg.payload();
	byte discriminator = payload.readByte();
	Class<? extends IPacket> clazz = this.packets.get(discriminator);
	if (clazz == null) {
		throw new NullPointerException("No packet registered for discriminator: "
				+ discriminator);
	}

	IPacket pkt = clazz.newInstance();
	pkt.decodeInto(ctx, payload.slice());

	EntityPlayer player;
	switch (FMLCommonHandler.instance().getEffectiveSide()) {
	case CLIENT:
		player = this.getClientPlayer();
		pkt.handleClientSide(player);
		break;

	case SERVER:
		INetHandler netHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get();
		player = ((NetHandlerPlayServer) netHandler).playerEntity;
		pkt.handleServerSide(player);
		break;

	default:
	}

	out.add(pkt);
}

// Method to call from FMLInitializationEvent
public void initialise() {
	this.channels = NetworkRegistry.INSTANCE.newChannel(ModInfo.CHANNEL, this);
	registerPackets();
}

public void registerPackets() {
	//registerPacket(PACKETFILENAME.class);
}

// Method to call from FMLPostInitializationEvent
// Ensures that packet discriminators are common between server and client
// by using logical sorting
public void postInitialise() {
	if (this.isPostInitialised) {
		return;
	}

	this.isPostInitialised = true;
	Collections.sort(this.packets, new Comparator<Class<? extends IPacket>>() {

		@Override
		public int compare(Class<? extends IPacket> clazz1, Class<? extends IPacket> clazz2) {
			int com = String.CASE_INSENSITIVE_ORDER.compare(clazz1.getCanonicalName(),
					clazz2.getCanonicalName());
			if (com == 0) {
				com = clazz1.getCanonicalName().compareTo(clazz2.getCanonicalName());
			}

			return com;
		}
	});
}

@SideOnly(Side.CLIENT)
private EntityPlayer getClientPlayer() {
	return Minecraft.getMinecraft().thePlayer;
}

/**
 * Send this message to everyone.
 * <p/>
 * Adapted from CPW's code in
 * cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
 * 
 * @param message
 *            The message to send
 */
public void sendToAll(IPacket message) {
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET)
			.set(FMLOutboundHandler.OutboundTarget.ALL);
	this.channels.get(Side.SERVER).writeAndFlush(message);
}

/**
 * Send this message to the specified player.
 * <p/>
 * Adapted from CPW's code in
 * cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
 * 
 * @param message
 *            The message to send
 * @param player
 *            The player to send it to
 */
public void sendTo(IPacket message, EntityPlayerMP player) {
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET)
			.set(FMLOutboundHandler.OutboundTarget.PLAYER);
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
	this.channels.get(Side.SERVER).writeAndFlush(message);
}

/**
 * Send this message to everyone within a certain range of a point.
 * <p/>
 * Adapted from CPW's code in
 * cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
 * 
 * @param message
 *            The message to send
 * @param point
 *            The
 *            {@link cpw.mods.fml.common.network.NetworkRegistry.TargetPoint}
 *            around which to send
 */
public void sendToAllAround(IPacket message, NetworkRegistry.TargetPoint point) {
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET)
			.set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
	this.channels.get(Side.SERVER).writeAndFlush(message);
}

/**
 * Send this message to everyone within the supplied dimension.
 * <p/>
 * Adapted from CPW's code in
 * cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
 * 
 * @param message
 *            The message to send
 * @param dimensionId
 *            The dimension id to target
 */
public void sendToDimension(IPacket message, int dimensionId) {
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET)
			.set(FMLOutboundHandler.OutboundTarget.DIMENSION);
	this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS)
			.set(dimensionId);
	this.channels.get(Side.SERVER).writeAndFlush(message);
}

/**
 * Send this message to the server.
 * <p/>
 * Adapted from CPW's code in
 * cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper
 * 
 * @param message
 *            The message to send
 */
public void sendToServer(IPacket message) {
	this.channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET)
			.set(FMLOutboundHandler.OutboundTarget.TOSERVER);
	this.channels.get(Side.CLIENT).writeAndFlush(message);
}
}

 

 

 

In the register packet function you will want to put all the packets you want to register for example

registerPacket(PacketUpdateTE.class);

 

 

Next you want to setup your packet class for that tileentity, it will take in 3 parameters and also any other parameters you want to set, for example valueToSet can be whatever you want just make sure you register all your packet classes inside the packetpipeline.

[spoiler=Packet TileEntity Class]

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

public class PacketTileTE extends IPacket {

int xPos, yPos, zPos, dimension;

int valueToSet;

public PacketTileTE() {

}

public PacketTileTE(int dimension, int xPos, int yPos, int zPos, int valueToSet) {
	this.dimension = dimension;
	this.xPos = xPos;
	this.yPos = yPos;
	this.zPos = zPos;

	this.valueToSet = valueToSet;
}

@Override
public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
	buffer.writeInt(xPos);
	buffer.writeInt(yPos);
	buffer.writeInt(zPos);

	buffer.writeInt(valueToSet);
}

@Override
public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
	xPos = buffer.readInt();
	yPos = buffer.readInt();
	zPos = buffer.readInt();

	x = buffer.readInt();
}

@Override
public void handleClientSide(EntityPlayer player) {
}

@Override
public void handleServerSide(EntityPlayer player) {
	World world = player.worldObj;
	TileEntity te = world.getTileEntity(xPos, yPos, zPos);
	if (te instanceof TILE) {
		NBTTagCompound data = new NBTTagCompound();
		((YOURTileEntity) te).setVALUE(valueToSet);
		((eventTileEntity) te).writeToNBT(data);
		packetPipeline.sendToAll(new PacketUpdateTE(xPos, yPos, zPos, data));
	}
}

}

 

 

 

The last class you will want to make is the PacketUpdateTE. This will just update you tile entity on the client side and can be used by multiple packet tile entity classes.

 

[spoiler=PacketUpdateTE]

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;

import com.sirfatal.adventureplus.Network.IPacket;

public class PacketUpdateTE extends IPacket {

private int xPos, yPos, zPos;
private NBTTagCompound data;

public PacketUpdateTE() {

}

public PacketUpdateTE(int xPos, int yPos, int zPos, NBTTagCompound data) {
	this.xPos = xPos;
	this.yPos = yPos;
	this.zPos = zPos;
	this.data = data;
}

@Override
public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
	PacketBuffer pckBuff = new PacketBuffer(buffer);
	pckBuff.writeInt(xPos);
	pckBuff.writeShort(yPos);
	pckBuff.writeInt(zPos);
	try {
		pckBuff.writeNBTTagCompoundToBuffer(data);
	} catch (Exception e) {
		e.printStackTrace();
	}
}

@Override
public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) {
	PacketBuffer pckBuff = new PacketBuffer(buffer);
	xPos = pckBuff.readInt();
	yPos = pckBuff.readShort();
	zPos = pckBuff.readInt();
	try {
		data = pckBuff.readNBTTagCompoundFromBuffer();
	} catch (Exception e) {
		e.printStackTrace();
	}
}

@Override
public void handleClientSide(EntityPlayer player) {
	TileEntity te = player.worldObj.getTileEntity(xPos, yPos, zPos);
	if (te != null) {
		te.readFromNBT(data);
	}
}

@Override
public void handleServerSide(EntityPlayer player) {
}

}

 

 

 

The final things you want to do is in your main mod class initialise the packet pipeline

public static final PacketPipeline packetPipeline = new PacketPipeline();

@EventHandler
public void initialise(FMLInitializationEvent evt) {
	packetPipeline.initialise();
}

@EventHandler
public void postInitialise(FMLPostInitializationEvent evt) {
	packetPipeline.postInitialise();
}

 

And also in your entity class where you want the sync to happen put

packetPipeline.sendToServer(new PacketENTITYTE(
			this.worldObj.provider.dimensionId, this.xCoord, this.yCoord, this.zCoord, VALUE));

 

If you want some more help just ask and also all this information can be found in the Netty Packet Tutorial on the forums HERE

 

-SirFatal :)

Posted

If you are going to send the entire NBT data, the easiest way is to use the vanilla TileEntity methods:

@Override
public Packet getDescriptionPacket() {
NBTTagCompound tag = new NBTTagCompound();
this.writeToNBT(tag);
return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 1, tag);
}

@Override
public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity packet) {
readFromNBT(packet.func_148857_g());
}

That will make sure your tile entity is updated on the client when the block is first placed or the world loads, as well as whenever the block is forced to update.

 

Then, whenever you need to update your tile entity manually, you can simply mark the block for an update and it will do the work for you:

worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);

Posted

I'm still having issues with the block not re-rendering when it receives packets and blocks around it not doing the same thing.

 

EDIT: I should have tried this before posting, but I used my original onDataPacket method to fix it (marking block for redner update.)

Guest
This topic is now closed to further replies.

Announcements



×
×
  • Create New...

Important Information

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