youngmonkeys / ezyfox-server

A socket server (include SSL) supports realtime application, realtime game, MMORPG, messaging, chat and streaming data with TCP, UDP and Websocket
Apache License 2.0
569 stars 98 forks source link

How to send a List<T> to the client #127

Closed Assambra closed 1 year ago

Assambra commented 1 year ago

I didnt find only one time a example how to use responseFactory.newArrayResponse(), but this example is nested with other functions so its to hard to figured out what i realy need to polish this values to send over the network.

I want to send a List with this values:

public class Character {
    @EzyId
    Long id;

    Long accountId;

    String name;
    String sex;
    String race;
    String model;
}
@EzyDoHandle(Commands.CHARACTER_LIST)
    public void characterList(EzyUser user)
    {
        logger.info("user {} request character list", user.getName());

        responseFactory.newArrayResponse()
                .command(Commands.CHARACTER_LIST)
                .data(
                        newArrayList(
                                characterService.getAllCharacters(user)
                        )
                )
                .user(user)
                .execute();
    }

What extra files i need (response, model, ModelToResponseConverter)and how have they to look, i tryed a lot but allways same error: Caused by: java.lang.IllegalArgumentException: has no writer for class com.assambra.game.common.entity.Character

Next question on the client side i use the following to reseive the data is this correct?

private void OnCharacterListResponse(EzyAppProxy proxy, EzyArray data)
    {
        if(data.isEmpty())
            GameManager.Instance.ChangeScene(Scenes.CreateCharacter);
        else
        {
            GameManager.Instance.ChangeScene(Scenes.SelectCharacter);
            for (int i = 0; i < data.size(); i++)
            {
                EzyObject item = data.get<EzyObject>(i);
                EzyArray character = item.get<EzyArray>("characters");

                CharacterInfo characterInfo = new CharacterInfo();
                characterInfo.id = character.get<long>(0);
                characterInfo.accountId = character.get<long>(1);
                characterInfo.name = character.get<string>(2);
                characterInfo.sex = character.get<string>(3);
                characterInfo.race = character.get<string>(4);
                characterInfo.model = character.get<string>(5);

                GameManager.Instance.characterInfos.Add(characterInfo);
            }
        }
    }
tvd12 commented 1 year ago

You need to add @EzyArrayBinding to Character, you can take a look docs here: https://youngmonkeys.org/ezyfox-library/guides/ezyfox-binding-marshal-unmarshal

Assambra commented 1 year ago

i've added

@Data
@EzyCollection
@EzyArrayBinding
public class Character {
    @EzyId
    Long id;

    Long accountId;

    String name;
    String sex;
    String race;
    String model;
}

but now i get some error without sending response if i only try to read the List from the database with:

List<Character> chars = characterService.getAllCharacters(user);

public List<Character> getAllCharacters(EzyUser user) {
        Account account = accountRepo.findByField("username", user.getName());

        return characterRepo.findListByField("accountId", account.getId());
    }

Error: Caused by: com.tvd12.ezyfox.binding.exception.EzyReadValueException: can't read value: {accountId=2, race=Humanoid, sex=female, name=Assambra, model=äsldkfälskdfälskdj, _id=1} to: com.assambra.game.common.entity.Character

Error: Caused by: java.lang.ClassCastException: com.tvd12.ezyfox.entity.EzyHashMap cannot be cast to com.tvd12.ezyfox.entity.EzyArray

tvd12 commented 1 year ago

Hmm, because you're using this class for the both mongodb entity and response, you should not do that, you need to remove @EzyArrayBinding from the class, create a new response class and convert from entity to response

Assambra commented 1 year ago

Thanks again and you can close the issue.

CharacterListModel:
@Getter
@Builder
@EzyArrayBinding
public class CharacterListModel {
    Long id;
    Long accountId;
    String name;
    String sex;
    String race;
    String model;
}

CharacterController:

@EzyDoHandle(Commands.CHARACTER_LIST)
    public void characterList(EzyUser user)
    {
        logger.info("user {} request character list", user.getName());

        responseFactory.newArrayResponse()
                .command(Commands.CHARACTER_LIST)
                .data(
                        convert(characterService.getAllCharacters(user))
                )
                .user(user)
                .execute();
    }

private CharacterListModel[] convert(List<Character> characters)
    {
        CharacterListModel[] chars = new CharacterListModel[characters.size()];

        int i=0;
        for (Character character : characters) {
            CharacterListModel characterListModel = CharacterListModel.builder()
                    .id(character.getId())
                    .accountId(character.getAccountId())
                    .name(character.getName())
                    .sex(character.getSex())
                    .race(character.getRace())
                    .model(character.getModel())
                    .build();

            chars[i] = characterListModel;
            i++;
        }
        return chars;
    }