Jump to content

Update item attributes on server from dialog


Recommended Posts

Hi guys, I'm trying to implement following logic:

  1. User puts item into active slot.
  2. Right clicks on specific block
  3. Pop-up asking for text entry is shown
  4. When pop-up content is saved (and only if) - save entered text into item, and block coordinates

I've implemented it in the following way:

			
            if (!(byEntity.World is IClientWorldAccessor))
            {
               return;
            }
            
            string prevName = _name == null ? "" : _name;
            BlockPos prevPos = _pos;
            GuiDialogBlockEntityTextInput dlg = new GuiDialogBlockEntityTextInput("Enter your text",
                                                bec.Pos, prevName, bec.Api as ICoreClientAPI, 500);
            dlg.OnTextChanged = (text) =>
            {
                _pos = bec.Pos;
                _name = text;
            };
            dlg.OnCloseCancel = () =>
            {
                _name = prevName == "" ? null : _name;
                _pos = _prevPos;
            };
            dlg.TryOpen();
       

But, this _name property is set only on Client's side, I've tried to use :

            slot.Itemstack.Attributes.SetString("name", _name);

But they are also set only on client's side.

So the question is - how can I send information from client's copy of an item to server's copy of an item?

Edited by Denis Kosher
Link to comment
Share on other sites

  • 2 weeks later...

Found solution for this problem - right now the only way to synchronize something between client and server (in this specific order) - is to use BlockEntity (there is ItemEntity class with same functionality, but I was not able to find a way how to use it):

1. You'll need to create block entity which will be used as mediator for data synchronization, and add field which will store item for synchronization (either as ItemSlot, either as HashMap of itemId and itemSlot):

    public class BEMyEntity : BlockEntity
    {

        private ItemSlot _itemForSynch;

2. Before UI is opened - populate this field from item, in the BlockEntity (I did it as part of OnHeldInteractStep method, when user clicks on Mediator object):

		public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
		{
			if (byEntity.World is IClientWorldAccessor)
			{
				... Other logic
			}
			else
			{
				BEMyEntity bec = byEntity.World.BlockAccessor.GetBlockEntity(blockSel.Position) as BEMyEntity;
				if 	(bec != null) 
				{
					bec.setItemForSynch(slot);
				}
			}

3. When text is changed - send packet to the server side copy of BlockEntity

            if (byEntity.World is IClientWorldAccessor)
            {
                GuiDialogBlockEntityTextInput dlg = new GuiDialogBlockEntityTextInput(Lang.Get("message"),
                                                bec.Pos, "", bec.Api as ICoreClientAPI, 500);
                dlg.OnTextChanged = (text) =>
                {
                    int packetId = (int)EnumSignPacketId.SaveText;

                    using (MemoryStream ms = new MemoryStream())
                    {
                        BinaryWriter writer = new BinaryWriter(ms);
                        writer.Write(text);
                        byte[] data = ms.ToArray();
                        (bec.Api as ICoreClientAPI).Network.SendBlockEntityPacket(bec.Pos.X, bec.Pos.Y, bec.Pos.Z, packetId, data);
                    }
                };
                dlg.OnCloseCancel = () =>
                {
                    int packetId = (int)EnumSignPacketId.SaveText;
                    (bec.Api as ICoreClientAPI).Network.SendBlockEntityPacket(bec.Pos.X, bec.Pos.Y, bec.Pos.Z, packetId, null);
                };
                dlg.TryOpen();
            }

4. Add handler into blockEntity that will synchronize client and server side copy of items on package receive:

        public override void OnReceivedClientPacket(IPlayer player, int packetid, byte[] data)
        {
            string text = "";
            if (packetid == (int)EnumSignPacketId.SaveText)
            {
                if (data != null)
                {
                    using (MemoryStream ms = new MemoryStream(data))
                    {
                        BinaryReader reader = new BinaryReader(ms);
                        text = reader.ReadString();
                        if (text == null) text = "";
                    }
                    if (text == null) text = "";
                }
                if (_itemToSynch != null)
                {
                    _itemToSynch.Itemstack.Attributes.SetString("name", text);
                }

            }
            if (packetid == (int)EnumSignPacketId.CancelEdit)
            {
            }
        }

 

Link to comment
Share on other sites

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.