Jump to content

[1.7.10] Server Client variable generation issue


Thornack

Recommended Posts

Hi everybody,

 

I have a tile entity that generates a random number and stores this number as a variable. I wish to access this variable inside a GUI. But (and correct me if i am wrong) GUI's seem to stop all packets from being sent. How could I achieve this (how could I get the random number that is generated when the tile entity is placed in the world). When I try using nbt to save the variable and then get the variable again in the gui the gui picks up a different value for the variable because the variable is a random number.

 

in my tile entity class I generate the random number and have a getter for it as well as a setter for it

 

int randomNumber;

public void generateRandomNumber(String blockType){	 
	 if (blockType.equals("BasicBlock")) {
		 randomNumber = new Random().nextInt(36) + 1;
		 System.out.println("BasicBlock " + randomNumber);
	 }

public int getRandomNumber () {
	 return randomNumber;
 }
public void setRandomNumber (int numb) {
	 randomNumber = numb;
 }

@Override
public void readFromNBT(NBTTagCompound nbtCompound) {
	super.readFromNBT(nbtCompound);
	if (nbtCompound.hasKey("typeOfBlock") && nbtCompound.hasKey("randNumber")) {
		typeOfBlock = nbtCompound.getString("typeOfBlock");
		randomNumber = nbtCompound.getInteger("randNumber");
			}

}

@Override
public void writeToNBT(NBTTagCompound nbtCompound) {
	super.writeToNBT(nbtCompound);
	if(!typeOfBlock.isEmpty()){
		nbtCompound.setString("typeOfBlock",typeOfBlock);
	}
	nbtCompound.setInteger("randNumber",randomNumber);

}

 

in my GUI class I want to get the random number that is saved server side (at least im pretty sure it is saved server side)

private TileEntityRandomBlock tileBlock;

//all the stuff required to draw it etc etc... and the render method where I need to access the random number generated by the tile entity

@Override
    public void drawScreen(int mouseX, int mouseY, float p_73863_3_){
    	 super.drawScreen(mouseX, mouseY, p_73863_3_);
int blockRandNumb = this.tileBlock.getRandomNumber();
}

 

if I do this then I get what seems to be the clients version of my random number but I need the servers version. How could I achieve this result. Any help is appreciated (sorry for the psuedo code my class is very large and complicated so I tried to isolate what is needed to understand the issue at hand).

Link to comment
Share on other sites

Since GUI elements are client side only, if you want to want to have access to some variable on the server, you must send it to the client via a packet. You can then send that packet on the server side to the client at various times using events.

 

This is different from reading from/writing to NBT. The NBT functions are only called when you want to "save" a value so that it persists the next time you need to use it; they cannot be used to send packets arbitrarily. This is likely what causes the "queuing" effect that you describe.

 

See this for more information on packet sending.

Link to comment
Share on other sites

From what I understand, nbt is saving my variable when you write to disk and read from disk, nbt data seems to also be sent from the server to the client when the client initially loads the chunks, but any updates after that require packets. when i try using cpw.mods.fml.common.network.simpleimpl.IMessage; (i created a class to do this) i try to send packets while inside the gui and it seems to que the packets while i am inside the gui but when I close the gui it sends all the packets all at once. Is there a way to enable sending packets without having to close the gui? Also, how would you recommend I try to send the packets from the server to the client containing my variables value given that setup (sorry again for the psuedo code) if you need more info please let me know.

 

The packet code

public abstract class MyAbstractMessage<T extends IMessage> implements IMessage, IMessageHandler<T, IMessage>{

@Override
public IMessage onMessage(T message, MessageContext ctx) {
	if (ctx.side == Side.CLIENT) {
		return handleClientMessage(Minecraft.getMinecraft().thePlayer, message, ctx);
	} else {
		return handleServerMessage(ctx.getServerHandler().playerEntity, message, ctx);
	}
}

public abstract void fromBytes(ByteBuf buf);

public abstract void toBytes(ByteBuf buf);

public abstract IMessage handleClientMessage(EntityPlayer player, T message, MessageContext ctx);

public abstract IMessage handleServerMessage(EntityPlayer player, T message, MessageContext ctx);

}

 

Message class

public class MessageUpdateBlockState extends MyAbstractMessage<MessageUpdateBlockState>{

private int x,y,z;
private int block;

public MessageUpdateBlockState(){}

public MessageUpdateBlockState(TileEntityBlock tileBlock, int randNumb){
	this.x = tileBlock.xCoord;
	this.y = tileBlock.yCoord;
	this.z = tileBlock.zCoord;
	this.block =randNumb;
}

@Override
public void fromBytes(ByteBuf buf) {
	this.x = buf.readInt();
	this.y = buf.readInt();
	this.z = buf.readInt();
	this.block = buf.readInt();
}

@Override
public void toBytes(ByteBuf buf) {
	buf.writeInt(this.x);
	buf.writeInt(this.y);
	buf.writeInt(this.z);
	buf.writeInt(this.block);
}

@Override
public IMessage handleClientMessage(EntityPlayer player, MessageUpdateBlockState message, MessageContext ctx) {
		return null;
}

@Override
public IMessage handleServerMessage(EntityPlayer player, MessageUpdateBlockState message, MessageContext ctx) {
	handle(player, message, ctx);
	return message;
}

private void handle(EntityPlayer player, MessageUpdateBlockState message, MessageContext ctx){

	TileEntity te = player.worldObj.getTileEntity(message.x, message.y, message.z);
	if(te instanceof TileEntityBlock{
		TileEntityBlock blockTE= (TileEntityBlock) te;
		blockTE.updateBlocksStateNow(blockTE, player.getCurrentEquippedItem(), message.block;
	}
}

}

 

 

Link to comment
Share on other sites

Can you post the code that sends the packet? I'm not exactly sure what you mean when you send packets while inside the Gui. Do you mean when you're rendering the Gui? Or when you're interacting with the Gui? When I want to send packets from the server to the client at arbitrary times, I register an event handler and send the packet based on when events are fired.

 

If you want a Gui element (e.g. button press) to trigger a packet being sent from the server to the client, you'll need to send a packet from the client to the server. Then, when you're handling that packet on the server side, send a second packet from the server back to the client containing the relevant information.

Link to comment
Share on other sites

You can send a packet immediately from just about anywhere, client or server. There should not be any queuing involved.

 

In your particular case, you can take advantage of TileEntity#getDescriptionPacket and TileEntity#onDataPacket; any time a block updates (which you can manually trigger), the tile entity's description packet is sent to the client.

Link to comment
Share on other sites

I want the packet sent when the GUI opens but for now I tried it with a button click so I send the packets  in the GUI class at the following method

 

@Override
    protected void actionPerformed(GuiButton button){
        if (button.enabled){
            if (button.id == BUTTON_DONE_ID){
MessageUpdateBlockState msg = new MessageUpdateBlockState(tileBlock, this.randomNumber);// I think the issue is here i dont think i am sending the random number that is being generated in the TileEntity
                CustomMod.network.sendToServer(msg);
            	this.mc.displayGuiScreen((GuiScreen)null);
      }
            else if(button.id == BUTTON_CANCEL_ID){
            	this.mc.displayGuiScreen((GuiScreen)null);
            }
        }
    }
    

Link to comment
Share on other sites

I solved it,

my TileEntity required the following

 

@Override

public Packet getDescriptionPacket(){

NBTTagCompound nbtCompound = new NBTTagCompound();

this.writeToNBT(nbtCompound);

return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 0, nbtCompound);

}

 

@Override

    public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt){

NBTTagCompound nbtCompound = pkt.func_148857_g();

this.readFromNBT(nbtCompound);

    }

Link to comment
Share on other sites

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.



×
×
  • Create New...

Important Information

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