Jump to content

Syncing and saving string value for Block Entity and screen [1.19.2] [SOLVED]


RInventor7

Recommended Posts

Hey. I have created a custom Block entity, which on right click opens a screen. The screen has only 1 EditBox. I now want to save the EditBox value (String) and load it back every time I open the screen again. I've managed to do achieve half of that. When I close the world and open it and open the screen again the EditBox is empty and the BlockEntity has no idea what the String value is. For saving the value I overrided the saveAdditional and Load methods in my BlockEntity class. Why this thing happens? Am I doing something wrong? Thanks.

Here's the block entity class code

package com.rinventor.transportmod.objects.blockentities.station;

import com.rinventor.transportmod.core.init.ModBlockEntities;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;

public class StationBlockEntity extends BlockEntity implements WorldlyContainer {
	private String name;
	
	public StationBlockEntity(BlockPos position, BlockState state) {
		super(ModBlockEntities.STATION_ENTITY.get(), position, state);
	}
	
	@Override
	public void load(CompoundTag nbt) {
		super.load(nbt);
		this.name = nbt.getString("StationName");
	}

	@Override
	public void saveAdditional(CompoundTag nbt) {
		super.saveAdditional(nbt);
		nbt.putString("StationName", this.name);
	}

	@Override
	public ClientboundBlockEntityDataPacket getUpdatePacket() {
		return ClientboundBlockEntityDataPacket.create(this);
	}

	@Override
	public CompoundTag getUpdateTag() {
		return this.saveWithFullMetadata();
	}

	@Override
	public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
		this.load(pkt.getTag());
	}
	
}

 

Edited by RInventor7
Link to comment
Share on other sites

The screen is on the client while the saving is done on the server.

 

You need to send a network packet to the server when you want to rmodify the real block entity.

https://forge.gemwire.uk/wiki/SimpleChannel

This is similar to how the AnvilScreen renames an item.

 

You also need to sync the value to the client from the server.

e.g. always synching the data to the client (looks like you are using this method already)

https://forge.gemwire.uk/wiki/Block_Entities#Synchronizing_the_Data_to_the_Client

or just sending it when the screen is used

https://docs.minecraftforge.net/en/latest/gui/menus/#icontainerfactory

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

I added the functions to sync on block update but the value is still empty string on client. So the screen's EditBox just shows empty string. When I have written something to the EditBox it will send packet to the server just before closing the screen with the value. 

Packet handle function on server:

public static void set(LevelAccessor world, BlockPos pos, String name) {
	if (world.getBlockEntity(pos) instanceof StationBlockEntity be) {
		be.getPersistentData().putString("StationName", name);
		be.setChanged();
		if (world instanceof Level level) {
			BlockState state = PTMBlock.getBlockState(world, pos.getX(), pos.getY(), pos.getZ());
			level.sendBlockUpdated(pos, state, state, 2);
		}
	}
}

And the syncing function in my block entity class:

@Override
public void load(CompoundTag tag) {
	super.load(tag);
	this.name = tag.getString("StationName");
}

@Override
public void saveAdditional(CompoundTag tag) {
	super.saveAdditional(tag);
	tag.putString("StationName", this.name);
}

@Override
public void handleUpdateTag(CompoundTag tag) {
	load(tag);
}
	
@Override
public CompoundTag getUpdateTag() {
  CompoundTag tag = new CompoundTag();
  tag.putString("StationName", this.name);
  return tag;
}

@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
  return ClientboundBlockEntityDataPacket.create(this);
}

@Override
public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
	this.load(pkt.getTag());
}

So why is this value still not synced with client? Am I missing something? 

It's not synced after I reload the world!

Edited by RInventor7
Link to comment
Share on other sites

Can't help you if you only post snippets. I answered your original question in generalities for this reason.

Put the full code on github so we can see everything in context.

 

You don't even show how the data is retrieved on the client or the screen code using it.

Kind of central to locating the problem don't you think?

 

 

One thing I can see is:

You are putting the data in the persistent data.

This won't change the real "name" field in the block entity.

And you are storing that name in the main tag in load/saveAdditionalData().

Or even why you are using the persistent data at all.

That is for things like forge storing additional data against the block entity such as serializable capabilities attached by other mods.

 

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

  • RInventor7 changed the title to Syncing and saving string value for Block Entity and screen [1.19.2] [SOLVED]

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.