Jump to content

[1.15.2] Tile Entity Re-Creating on GUI Open


Jack Richard

Recommended Posts

Hi,

 

I'm having trouble with opening my GUI, as the tile entity (extending ITickableTileEntity, among others) will erase all stored variables, retrieved from NBT. So this isn't a problem with NBT. Also, this is a 1.15 problem.

I've tracked down the exact time that the variables reset, and it's when the GUI's screen is opened, createTileEntity() is triggered in the Block class, recreating the tile entity and overwriting the variables.

Is there a way to stop this?

 

Here's a snippet from my block's class.

@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
  return TileEntityTypes.TILE.get().create();
}

@Override
public boolean hasTileEntity(BlockState state) {
  return true;
}

 

Thanks for your help in advance, I'd be willing to send more code snippets and answer any questions.

Link to comment
Share on other sites

17 minutes ago, Jack Richard said:

I'm having trouble with opening my GUI, as the tile entity (extending ITickableTileEntity, among others) will erase all stored variables

It's like there are two sides of the game that need to be synchronized, hmmmmmmmmmmmmm.

 

The client and server will not be synchronized under normal conditions, you must specify which variable you would like to sync and when (most likely in your container).

Link to comment
Share on other sites

40 minutes ago, ChampionAsh5357 said:

It's like there are two sides of the game that need to be synchronized, hmmmmmmmmmmmmm.

 

The client and server will not be synchronized under normal conditions, you must specify which variable you would like to sync and when (most likely in your container).

Does it help to say when I add...

@Override
public void tick() {
	System.out.println(variable);
}

...I always get the result, whether or not world.isRemote()?

 

I use...

@Override
public CompoundNBT getUpdateTag() {
  CompoundNBT tagCompound = new CompoundNBT();
  tagCompound.putString("variable", variable);
  return tagCompound;
}

@Override
public void handleUpdateTag(CompoundNBT tag) {
  this.read(tag);
}

@Override
public void read(CompoundNBT compound)
{
  super.read(compound);
  this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
  ItemStackHelper.loadAllItems(compound, this.inventory);
  setVariable(compound.getString("variable"));
}

@Override
public CompoundNBT write(CompoundNBT compound)
{
  super.write(compound);
  ItemStackHelper.saveAllItems(compound, this.inventory);
  compound.putString("variable", getVariable());

  return compound;
}

to synchronize the data.

 

Thanks.

Link to comment
Share on other sites

22 minutes ago, Jack Richard said:

this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY); ItemStackHelper.loadAllItems(compound, this.inventory);

This looks like copy and paste of an IInventory class, use the IItemHandler instead. You should not use the vanilla method to create your inventory.

 

23 minutes ago, Jack Richard said:

@Override public CompoundNBT getUpdateTag() { CompoundNBT tagCompound = new CompoundNBT(); tagCompound.putString("variable", variable); return tagCompound; } @Override public void handleUpdateTag(CompoundNBT tag) { this.read(tag); }

Ah yes, synchronization on block update. Something completely unnecessary when it comes to GUI. Those are synced through slots. This should only be used if you have a TER present.

25 minutes ago, Jack Richard said:

...I always get the result, whether or not world.isRemote()?

Then you fell into a trap of confirmation bias. Just because you get the same result doesn't mean it was synced correctly. It just means you probably executed the same code on both sides when it should only be on one and then synced.

Link to comment
Share on other sites

7 minutes ago, ChampionAsh5357 said:

Ah yes, synchronization on block update. Something completely unnecessary when it comes to GUI. Those are synced through slots. This should only be used if you have a TER present.

Then you fell into a trap of confirmation bias. Just because you get the same result doesn't mean it was synced correctly. It just means you probably executed the same code on both sides when it should only be on one and then synced.

I forgot to mention I send Messages from the client to the server, so I am doing some syncing, I believe.

Link to comment
Share on other sites

1 hour ago, Jack Richard said:

I forgot to mention I send Messages from the client to the server, so I am doing some syncing, I believe.

Yes. Synchronization the wrong direction. Always good.

 

I doubt you need to synchronize from the client->server as this probably just uses a standard inventory and primitives.  In that case, you only need to sync from server->client. Which, you are still neglecting to listen and do.

 

Please show your entire tile entity, block, container, and screen code. I am curious on what you're doing and how you're doing it since I'm pretty sure it's some variation of vanilla code which will not work in most cases.

Link to comment
Share on other sites

4 minutes ago, ChampionAsh5357 said:

Yes. Synchronization the wrong direction. Always good.

 

I doubt you need to synchronize from the client->server as this probably just uses a standard inventory and primitives.  In that case, you only need to sync from server->client. Which, you are still neglecting to listen and do.

 

Please show your entire tile entity, block, container, and screen code. I am curious on what you're doing and how you're doing it since I'm pretty sure it's some variation of vanilla code which will not work in most cases.

public class ServerContainer extends Container {

    public ServerTileEntity entity;

    public ServerContainer(final int windowId, final PlayerInventory playerInventory, final PacketBuffer data) {
        this(windowId, playerInventory, getTileEntity(playerInventory, data));
    }

    public ServerContainer(final int windowId, final PlayerInventory playerInventory,
                           final TileEntity tileEntity) {
        super(ContainerTypes.SERVER.get(), windowId);

        this.entity = (ServerTileEntity) tileEntity;

        int startX = 8;
        int startY = 84;
        int slotSizePlus2 = 18;

        for (int row = 0; row < 3; ++row) {
            for (int column = 0; column < 9; ++column) {
                this.addSlot(new Slot(playerInventory, 9 + (row * 9) + column, startX + (column * slotSizePlus2),
                        startY + (row * slotSizePlus2)));
            }
        }

        int hotbarY = 142;
        for (int column = 0; column < 9; ++column) {
            this.addSlot(new Slot(playerInventory, column, startX + (column * slotSizePlus2), hotbarY));
        }

        this.addSlot(new CustomSlot(entity, 0, 7, 35));
    }

    @Override
    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);
        if (slot != null && slot.getHasStack()) {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            if (index < 36) {
                if (!this.mergeItemStack(itemstack1, 36, this.inventorySlots.size(), true)) {
                    return ItemStack.EMPTY;
                }
            } else if (!this.mergeItemStack(itemstack1, 0, 36, false)) {
                return ItemStack.EMPTY;
            }

            if (itemstack1.isEmpty()) {
                slot.putStack(ItemStack.EMPTY);
            } else {
                slot.onSlotChanged();
            }
        }
        return itemstack;
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return true;
    }

    private static ServerTileEntity getTileEntity(final PlayerInventory playerInventory,
                                                 final PacketBuffer data) {
        Objects.requireNonNull(playerInventory, "playerInventory cannot be null");
        Objects.requireNonNull(data, "data cannot be null");
        final TileEntity tileAtPos = playerInventory.player.world.getTileEntity(data.readBlockPos());

        if (tileAtPos instanceof ServerTileEntity) {
            return (ServerTileEntity) tileAtPos;
        }
        throw new IllegalStateException("Tile entity is not correct! " + tileAtPos);
    }

}
@OnlyIn(Dist.CLIENT)
public class ServerScreen extends ContainerScreen<ServerContainer> {

    private static final ResourceLocation TEXTURES = new ResourceLocation("modid:textures/gui/server.png");
    private final PlayerInventory player;
    private ServerTileEntity entity;
    private TextFieldWidget carrierName;

    public ServerScreen(ServerContainer container, PlayerInventory player, ITextComponent title) {
        super(container, player, title);
        this.player = player;
        this.entity = getTileEntity(player, container);
        this.guiLeft = 0;
        this.guiTop = 0;
        this.xSize = 176;
        this.ySize = 166;
    }

    @Override
    protected void init() {
        super.init();

        int x = (this.width - this.xSize) / 2;
        int y = (this.height - this.ySize) / 2;

        this.carrierName = new TextFieldWidget(font, x + 84, y + 11, 86, 18, "Carrier Name");
        this.carrierName.setMaxStringLength(13);
        this.carrierName.setEnableBackgroundDrawing(false);
        this.carrierName.setVisible(true);
        this.carrierName.setTextColor(16777215);
        this.carrierName.setText(this.entity.getCarrierName());
        System.out.println(this.entity.getCarrierName());
        System.out.println("Above set");
    }

    private static ServerTileEntity getTileEntity(final PlayerInventory playerInventory, final ServerContainer container) {
        Objects.requireNonNull(playerInventory, "playerInventory cannot be null");
        final TileEntity tileAtPos = playerInventory.player.world.getTileEntity(container.entity.getPos());

        if (tileAtPos instanceof ServerTileEntity) {
            return (ServerTileEntity) tileAtPos;
        }
        throw new IllegalStateException("Tile entity is not correct! " + tileAtPos);
    }

    @Override
    public void render(final int mouseX, final int mouseY, final float partialTicks) {
        this.renderBackground();
        this.carrierName.render(mouseX, mouseY, partialTicks);
        super.render(mouseX, mouseY, partialTicks);
        this.renderHoveredToolTip(mouseX, mouseY);
    }

    @Override
    public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
        this.carrierName.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
        return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
        this.getMinecraft().getTextureManager().bindTexture(TEXTURES);

        int x = (this.width - this.xSize) / 2;
        int y = (this.height - this.ySize) / 2;

        this.blit(x, y, 0, 0, 176, 166);
        this.font.drawString("Server", x + 10, y + 10, 16777215);

        this.entity.setCarrierName(carrierName.getText());
        ModClass.INSTANCE.sendToServer(new CarrierServerSync(carrierName.getText(), this.entity.getPos()));
    }

    @Override
    protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
        super.drawGuiContainerForegroundLayer(mouseX, mouseY);

        int x = (this.width - this.xSize) / 2;
        int y = (this.height - this.ySize) / 2;

        this.addButton(new Button(x + 30, y + 33, 50, 20, "Register", new Button.IPressable() {
            @Override
            public void onPress(Button p_onPress_1_) {
                System.out.println("pressed");
                if (!entity.getStackInSlot(0).isEmpty()) {
                    System.out.println("not empty");
                    if (entity.getStackInSlot(0).getStack().getTag() != null) {
                        System.out.println("not null");
                        CompoundNBT compoundNBT = entity.getStackInSlot(0).getTag().copy();
                        compoundNBT.putString("carrier", carrierName.getText());
                        entity.getStackInSlot(0).setTag(compoundNBT);
                    } else {
                        System.out.println("null");
                        CompoundNBT compoundNBT = new CompoundNBT();
                        compoundNBT.putString("carrier", carrierName.getText());
                        entity.getStackInSlot(0).getStack().setTag(compoundNBT);
                    }
                }
            }
        }));

        this.addButton(carrierName);
    }

}
public class ServerTileEntity extends TileEntity implements INamedContainerProvider, ITickableTileEntity, IInventory {

    private NonNullList<ItemStack> inventory = NonNullList.<ItemStack>withSize(1, ItemStack.EMPTY);
    private IItemHandlerModifiable items = createHandler();
    private LazyOptional<IItemHandlerModifiable> itemHandler = LazyOptional.of(() -> items);
    private String carrierName = "";

    public ServerTileEntity(TileEntityType<?> tileEntityTypeIn) {
        super(tileEntityTypeIn);
    }

    public ServerTileEntity(){
        super(TileEntityTypes.SERVER.get());
    }

    @Override
    public ITextComponent getDisplayName() {
        return new TranslationTextComponent("container.server");
    }

    @Override
    public Container createMenu(int p_createMenu_1_, PlayerInventory p_createMenu_2_, PlayerEntity p_createMenu_3_) {
        return new ServerContainer(p_createMenu_1_, p_createMenu_2_, this);
    }

    @Override
    public void tick() {
        
    }

    @Override
    public SUpdateTileEntityPacket getUpdatePacket() {
        CompoundNBT tagCompound = new CompoundNBT();
        tagCompound.putString("carrier", carrierName);
        this.write(tagCompound);
        SUpdateTileEntityPacket pack = new SUpdateTileEntityPacket(pos, 0, tagCompound);
        return pack;
    }

    @Override
    public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt) {
        this.read(pkt.getNbtCompound());
    }

    @Override
    public CompoundNBT getUpdateTag() {
        CompoundNBT tagCompound = new CompoundNBT();
        tagCompound.putString("carrier", carrierName);
        return tagCompound;
    }

    @Override
    public void handleUpdateTag(CompoundNBT tag) {
        this.read(tag);
    }

    public void setCarrierName(String carrierName) {
        this.carrierName = carrierName;
    }

    public String getCarrierName() {
        return this.carrierName;
    }

    @Override
    public int getSizeInventory() {
        return inventory.size();
    }

    @Override
    public boolean isEmpty() {
        for(ItemStack stack : this.inventory) {
            if(!stack.isEmpty()) return false;
        }
        return true;
    }

    @Override
    public ItemStack getStackInSlot(int index) {
        return inventory.get(index);
    }

    @Override
    public ItemStack decrStackSize(int index, int count) {
        return ItemStackHelper.getAndSplit(this.inventory, index, count);
    }

    @Override
    public void setInventorySlotContents(int index, ItemStack stack) {
        this.inventory.set(index, stack);
    }

    @Override
    public ItemStack removeStackFromSlot(int index) {
        return ItemStackHelper.getAndRemove(this.inventory, index);
    }

    @Override
    public boolean isUsableByPlayer(PlayerEntity player) {
        return true;
    }

    @Override
    public void clear() {
        this.inventory.clear();
    }

    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nonnull Direction side) {
        if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return itemHandler.cast();
        }
        return super.getCapability(cap, side);
    }

    @Override
    public void read(CompoundNBT compound)
    {
        super.read(compound);
        this.inventory = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);
        ItemStackHelper.loadAllItems(compound, this.inventory);
        setCarrierName(compound.getString("carrier"));
    }

    private IItemHandlerModifiable createHandler() {
        return new InvWrapper(this);
    }

    @Override
    public CompoundNBT write(CompoundNBT compound)
    {
        super.write(compound);
        ItemStackHelper.saveAllItems(compound, this.inventory);
        compound.putString("carrier", getCarrierName());

        return compound;
    }

}
public class Server extends Block {

    private static final VoxelShape SHAPE = Block.makeCuboidShape(0.0D, 0.0D, 0.0D, 16.0D, 32.0D, 16.0D);

    public static final DirectionProperty FACING = HorizontalBlock.HORIZONTAL_FACING;

    public Server(Properties properties) {
        super(properties);

        this.setDefaultState(this.getStateContainer().getBaseState().with(FACING, Direction.NORTH));
    }

    @Override
    public TileEntity createTileEntity(BlockState state, IBlockReader world) {
        return TileEntityTypes.SERVER.get().create();
    }

    @Override
    public boolean hasTileEntity(BlockState state) {
        return true;
    }

    @Override
    protected void fillStateContainer(StateContainer.Builder<Block, BlockState> builder) {
        builder.add(FACING);
    }

    @Override
    public BlockState getStateForPlacement(BlockItemUseContext context) {
        return this.getDefaultState().with(FACING, context.getPlacementHorizontalFacing().getOpposite());
    }

    @Override
    public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
        return SHAPE;
    }

    @Override
    public ActionResultType onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit) {
        TileEntity te = worldIn.getTileEntity(pos);
        if (te != null && te instanceof ServerTileEntity && !worldIn.isRemote) {
            NetworkHooks.openGui((ServerPlayerEntity) player, (ServerTileEntity) te, pos);
        }

        return super.onBlockActivated(state, worldIn, pos, player, handIn, hit);
    }

}

 

My goal is to get the data from the TextFieldWidget, and save it in NBT tags, and be able to retreive it later, putting the text back in the field.

Yes, I know; most of this code won't be the "recommended way" of doing any of this, I've been really trying though.

 

Let me know if you need any more information.

Thanks.

Link to comment
Share on other sites

3 minutes ago, Jack Richard said:

TileEntity implements INamedContainerProvider, ITickableTileEntity, IInventory

You are using IInventory. Go and fix that and properly attach it with capabilities. But I won't be so stingy since you have been trying and cooperating so apologies for my agressiveness.

 

As a precursor, try to avoid using Server or Client in your names, it confuses everyone.

7 minutes ago, Jack Richard said:

tagCompound.putString("carrier", carrierName); this.write(tagCompound);

You're writing the carrier name twice?

9 minutes ago, Jack Richard said:

ModClass.INSTANCE.sendToServer(new CarrierServerSync(carrierName.getText(), this.entity.getPos()));

You're doing this every tick, only send it when the button is pressed.

9 minutes ago, Jack Richard said:

if (entity.getStackInSlot(0).getStack().getTag() != null) { System.out.println("not null"); CompoundNBT compoundNBT = entity.getStackInSlot(0).getTag().copy(); compoundNBT.putString("carrier", carrierName.getText()); entity.getStackInSlot(0).setTag(compoundNBT); } else { System.out.println("null"); CompoundNBT compoundNBT = new CompoundNBT(); compoundNBT.putString("carrier", carrierName.getText()); entity.getStackInSlot(0).getStack().setTag(compoundNBT); }

This should not really be handled on the client once again. This is not necessary if you send the information to the server. You will need to resync the values anyways whenever the inventory is opened regardless.

Finally, if your container is not registered using IForgeContainerType, then the packet information will never be sent to the client. You should also store the block pos and not the te itself. That's rather pointless to do as all it's used for sending the position back to the server. The tile entity will still not store the position anyways.

Link to comment
Share on other sites

1 minute ago, ChampionAsh5357 said:

You are using IInventory. Go and fix that and properly attach it with capabilities. But I won't be so stingy since you have been trying and cooperating so apologies for my agressiveness.

I understand that IInventory is not accepted, so I'll be working to fix that soon. No problem, I'm just happy with whatever you're able to contribute. 

 

2 minutes ago, ChampionAsh5357 said:

As a precursor, try to avoid using Server or Client in your names, it confuses everyone.

Yeah, that wasn't the best choice.

 

3 minutes ago, ChampionAsh5357 said:

You're writing the carrier name twice?

I guess so. I was a little confused once functions like getUpdatePacket() and onDataPacket() were used.

 

4 minutes ago, ChampionAsh5357 said:

You're doing this every tick, only send it when the button is pressed.

This should not really be handled on the client once again. This is not necessary if you send the information to the server. You will need to resync the values anyways whenever the inventory is opened regardless.

I'm sending the data every tick, the button writes the data to an item in the one slot of the GUI. Here's the code for the .sendtoServer() handler:

public static void handle(CarrierServerSync msg, Supplier<NetworkEvent.Context> ctx) {
        ctx.get().enqueueWork(() -> {
            PlayerEntity sender = ctx.get().getSender();
            ServerTileEntity server = getTileEntity(sender.inventory, msg.tileEntity);
            server.setCarrierName(msg.data);
        });
        ctx.get().setPacketHandled(true);
    }

    private static ServerTileEntity getTileEntity(final PlayerInventory playerInventory, final BlockPos tileEntity) {
        Objects.requireNonNull(playerInventory, "playerInventory cannot be null");
        final TileEntity tileAtPos = playerInventory.player.world.getTileEntity(tileEntity);

        if (tileAtPos instanceof ServerTileEntity) {
            return (ServerTileEntity) tileAtPos;
        }
        throw new IllegalStateException("Tile entity is not correct! " + tileAtPos);
    }

This is probably not the best way to do this...

 

9 minutes ago, ChampionAsh5357 said:

This should not really be handled on the client once again. This is not necessary if you send the information to the server. You will need to resync the values anyways whenever the inventory is opened regardless.

Finally, if your container is not registered using IForgeContainerType, then the packet information will never be sent to the client. You should also store the block pos and not the te itself. That's rather pointless to do as all it's used for sending the position back to the server. The tile entity will still not store the position anyways.

Luckily, I do have my container, messages, and tile entity registered. 

Looping back to my original theory, is Block#createTileEntity() run when you open a GUI?

 

Thanks again.

Link to comment
Share on other sites

7 minutes ago, Jack Richard said:

I'm sending the data every tick, the button writes the data to an item in the one slot of the GUI. Here's the code for the .sendtoServer() handler:

That still makes no sense. You're just bottlenecking the network. The data doesn't change until you send it. Also, the button shouldn't be the one doing it. It should be handled on the server once again. NOTHING should be handled on the client itself. It all gets synchronized via the gui. Only thing that doesn't is the string which should be what you send on button click.

8 minutes ago, Jack Richard said:

Luckily, I do have my container, messages, and tile entity registered. 

You missed the part where I said IForgeContainerType. Doesn't matter if their registered. If it's not using the correct type it won't send the packet.

9 minutes ago, Jack Richard said:

Looping back to my original theory, is Block#createTileEntity() run when you open a GUI?

Not being rude, the original theory is wrong. The client doesn't hold data from the server. It will be reinitialized since it's pulling information from the empty client container.

Link to comment
Share on other sites

7 minutes ago, ChampionAsh5357 said:

That still makes no sense. You're just bottlenecking the network. The data doesn't change until you send it. Also, the button shouldn't be the one doing it. It should be handled on the server once again. NOTHING should be handled on the client itself. It all gets synchronized via the gui. Only thing that doesn't is the string which should be what you send on button click.

You missed the part where I said IForgeContainerType. Doesn't matter if their registered. If it's not using the correct type it won't send the packet.

Not being rude, the original theory is wrong. The client doesn't hold data from the server. It will be reinitialized since it's pulling information from the empty client container.

I know, it's very confusing, and frankly, I might just rework the GUI if I can't get this to work, anyway.

Is it possible to get data from the Screen class to the TileEntity class? 

 

Also, should I implement IForgeContainerType in my Container class?

I understand, the original theory was a little far-fetched. So an empty client container could be it? Just trying to understand.

 

Thanks again.

Link to comment
Share on other sites

10 minutes ago, Jack Richard said:

Is it possible to get data from the Screen class to the TileEntity class? 

Yes, that's the use of a packet through the network. But that should only be sent as needed as otherwise you just bottleneck the network creating more issues.

11 minutes ago, Jack Richard said:

Also, should I implement IForgeContainerType in my Container class?

No, that should be used in your registry instance for your ContainerType.

12 minutes ago, Jack Richard said:

So an empty client container could be it? Just trying to understand.

Imagine it like this. You have two instances, a server and the client. The server creates a container with a specific window id. The client creates a container with the same window id and a screen that can get information from the container. The server container sends default information to the client container which is read by the screen. A client screen clicks something, which gets sent as a packet to the server container, which updates the client container, which updates the screen. Note that the client creates a new instance of the container on open so the information needs to be synced. By default, only slots and tracked integers are synced. If you want to handle something else, you need to send it yourself.

Link to comment
Share on other sites

16 minutes ago, ChampionAsh5357 said:

Yes, that's the use of a packet through the network. But that should only be sent as needed as otherwise you just bottleneck the network creating more issues.

No, that should be used in your registry instance for your ContainerType.

Got it, and got it.

 

16 minutes ago, ChampionAsh5357 said:

Imagine it like this. You have two instances, a server and the client. The server creates a container with a specific window id. The client creates a container with the same window id and a screen that can get information from the container. The server container sends default information to the client container which is read by the screen. A client screen clicks something, which gets sent as a packet to the server container, which updates the client container, which updates the screen. Note that the client creates a new instance of the container on open so the information needs to be synced. By default, only slots and tracked integers are synced. If you want to handle something else, you need to send it yourself.

Thanks for explaining it to me, I'll try to wrap my head around that, and send an update soon.

 

Thank you!

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.