Cardinal Components API

Cardinal Components API

21M Downloads

Incorrect AutoSyncComponent

Sam-Chai opened this issue · 1 comments

commented

I write a interface that improve players balance and count if player is first join the server.

And I also wrote a GUI that mixin InventoryScreen.class improve a text component to show player's balance.
The problem is, when I first started Minecraft Client then join the server immediately, in player inventory screen player balance shows zero dollars, but in fact when I use a command to get server sides, then back me 100$. In fact this player have 100$ in playerdata.

And I restart the games, and now I join to a singleplayer, they run very perfectly. THE WEIRED THINGS is this:
I exit the singleplayer, and rejoin the multiplayer server, then the client side can sync 100$ to player's screen. And I try to modify player‘s balance, but everything sync perfectly.

Also, when I dead in server, and respawn the player, then everything can sync perfectly.

This is what confuses me, the unsync issue only happends on when I first join the server. When I exit and rejoin or dead on server, then everything comes back.

Below is my classes:

  • This is IPlayerEcoData interface
public interface IPlayerEcoData extends PlayerComponent {
    Double getMoney();
    Boolean getIsFirstJoin();
    void setMoney(Double money);
    void setIsFirstJoin(Boolean isFirstJoin);
}
  • And this is Player Eco Data class:
public class PlayerEcoData implements IPlayerEcoData, AutoSyncedComponent {
    private final Player provider;
    private Double playerMoney;
    private Boolean playerIsFirstJoin = true;
    public PlayerEcoData(Player provider) {
        this.provider = provider;
    }

    @Override
    public Double getMoney() {
        if (playerMoney == null) {
            return 0.00;
        }
        return playerMoney;
    }

    @Override
    public Boolean getIsFirstJoin() {
        return playerIsFirstJoin;
    }

    @Override
    public void setMoney(Double money) {
        this.playerMoney = money;
        CapabilityRegister.PLAYER_DATA.sync(this.provider);
    }

    @Override
    public void setIsFirstJoin(Boolean isFirstJoin) {
        this.playerIsFirstJoin = isFirstJoin;
        CapabilityRegister.PLAYER_DATA.sync(this.provider);
    }

    @Override
    public void readFromNbt(CompoundTag tag) {
        playerMoney = tag.getDouble("money");
        playerIsFirstJoin = tag.getBoolean("isFirstJoin");
    }

    @Override
    public void writeToNbt(CompoundTag tag) {
        if (playerMoney == null) {
            playerMoney = 0.00;
        }
        tag.putDouble("money", playerMoney);
        tag.putBoolean("isFirstJoin", playerIsFirstJoin);
    }

}
  • This is Registry:
public class CapabilityRegister implements EntityComponentInitializer {

    public static final ComponentKey<IPlayerEcoData> PLAYER_DATA = ComponentRegistry.getOrCreate(new ResourceLocation(Economic.MODID, "player_eco_data"), IPlayerEcoData.class);

    @Override
    public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) {
        registry.registerForPlayers(PLAYER_DATA, PlayerEcoData::new, RespawnCopyStrategy.ALWAYS_COPY);
    }
}
  • And this is my client side mixin to show player's balance:
@Environment(EnvType.CLIENT)
public class PlayerBalanceComponent {
    public static void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float delta) {
        Minecraft mc = Minecraft.getInstance();
        String balance = "Balance: " + CapabilityRegister.PLAYER_DATA.get(mc.player).getMoney();
        guiGraphics.drawString(mc.font, balance, guiGraphics.guiWidth() / 2 - mc.font.width(balance) / 2, 10, 0xFFFFFF);
    }
}

I don't know where is wrong. Everything follow CCA doc and testmods.

commented

Since your target interface does not directly implement AutoSyncedComponent, you need to tell the library about it yourself.

see the relevant wiki entry: https://ladysnake.org/wiki/cardinal-components-api/synchronization#a-note-on-registration