ocraft / ocraft-s2client

StarCraft II Client - Java library supported on Windows, Linux and Mac designed for building scripted bots and research using the SC2API.
MIT License
55 stars 15 forks source link

BufferOverflowException when running the game for a short time. #4

Closed SimonPrins closed 6 years ago

SimonPrins commented 6 years ago

I have modified the 'Play the game' example to keep running the game and request an observation for each frame. After running for about 45 seconds the game crashes with the following exception:

ERROR com.github.ocraft.s2client.api.controller.S2Controller - S2Controller.onError
java.nio.BufferOverflowException: null
    at com.github.ocraft.s2client.api.vertx.VertxChannel.output(VertxChannel.java:99) ~[ocraft-s2client-api-0.1.0.jar:0.1.0]
    at com.github.ocraft.s2client.api.vertx.OnResponse.onNext(OnResponse.java:61) ~[ocraft-s2client-api-0.1.0.jar:0.1.0]
    at com.github.ocraft.s2client.api.vertx.OnResponse.onNext(OnResponse.java:33) ~[ocraft-s2client-api-0.1.0.jar:0.1.0]
    at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:64) ~[rxjava-2.1.3.jar:2.1.3]

There is a lot longer stack trace which I didn't add because I don't think it adds much more clarity. If necessary I can add it as well.

This is my code:

    S2Controller game = starcraft2Game().launch();
    S2Client client = starcraft2Client().connectTo(game).traced(true).start();

    client.request(createGame()
            .onBattlenetMap(BattlenetMap.of("Lava Flow"))
            .withPlayerSetup(participant(), computer(PROTOSS, Difficulty.MEDIUM)));

    client.responseStream()
            .takeWhile(Responses.isNot(ResponseLeaveGame.class))
            .subscribe(response -> {
                response.as(ResponseCreateGame.class).ifPresent(r -> client.request(joinGame().as(TERRAN)));
                response.as(ResponseJoinGame.class).ifPresent(r -> {
                   client.request(nextStep().withCount(1));
                });
                response.as(ResponseObservation.class).ifPresent(r -> {
                    client.request(nextStep().withCount(1));
                });
                response.as(ResponseStep.class).ifPresent(r -> {
                    client.request(observation());
                });
            });
        client.request(leaveGame());

        client.await();
ocraft commented 6 years ago

Ok, I got it. It's not exactly a bug in the code but default response queue buffer size in config file was set too low. In situation when you send so many request in a loop the chances that buffer will overflow are very high. I increased default buffer size and that should solve this issue.

Thank you for detecting and reporting this problem.