Как обрабатывать RPC в клиент-серверной игре PlayN? - PullRequest
9 голосов
/ 28 января 2012

Я бы хотел использовать PlayN для создания карточной игры клиент / сервер, например, Hearts.Хотя я в основном концентрируюсь на выводе HTML5, в идеале я бы хотел быть независимым от платформы вывода на случай, если в будущем я решу сделать Android-клиент.Как мне подходить к механизму RPC?

Вот варианты, о которых я подумал:

  1. Использовать JSON для RPC с методами get () / post () - написать сервлеткоторый принимает / возвращает JSON и заставляет использовать все версии клиентского кода.Это кажется выполнимым, но меня беспокоит многословие JSON.После того, как Hearts заработает, я бы хотел перейти к более сложным играм, и я обеспокоен тем, что JSON приведет к тому, что между клиентом и сервером будет передаваться множество сообщений намного большего размера, чем необходимо.На самом деле я не знаю, как работать с JSON в Java, но я предполагаю, что это выполнимо.Мои предположения в строке?Насколько хорошо Java работает с JSON?
  2. Продолжайте использовать GWT-RPC.Я могу сделать это, используя асинхронный интерфейс службы в своем конструкторе ядра (независимый от платформы), и в своем HTML main () я передаю асинхронный интерфейс GWT, сгенерированный GWT.create(MyService.class) (или, по крайней мере, оберткой вокруг него).Я понятия не имею, насколько хорошо это будет работать для не-HTML версий, хотя.Могу ли я использовать GWT-RPC из клиентского Java-кода напрямую?
  3. Использовать какую-либо другую форму RPC.Есть предложения?

1 Ответ

12 голосов
/ 29 января 2012

Для GWT RPC на платформах Java и Android в настоящее время я экспериментирую с использованием gwt-syncproxy для предоставления Java-клиенту доступа к методам GWT RPC, а также использую Guice, Gin и RoboGuice для соответствующих целей. платформы для внедрения соответствующих экземпляров асинхронных служб для созданного объекта Game.

В core / pom.xml для проекта PlayN я включаю следующие координаты зависимостей для поддержки DI из Gin / Guice / RoboGuice по мере необходимости:

<dependency>
  <groupId>javax.inject</groupId>
  <artifactId>javax.inject</artifactId>
  <version>1</version>
</dependency>

Затем я добавляю аннотации @Inject к любым полям внутри конкретной реализации Game:

public class TestGame implements Game {

    @Inject
    TestServiceAsync _testService;

    ...

}

В html / pom.xml я включаю координаты зависимости для Gin:

<dependency>
  <groupId>com.google.gwt.inject</groupId>
  <artifactId>gin</artifactId>
  <version>1.5.0</version>
</dependency>

И я создаю классы TestGameGinjector и TestGameModule:

TestGameGinjector.java

@GinModules(TestGameModule.class)
public interface TestGameGinjector extends Ginjector {
    TestGame getGame();
}

TestGameModule.java

public class TestGameModule extends AbstractGinModule {
    @Override
    protected void configure() {
    }
}

Поскольку на данный момент я только внедряю интерфейс TestServiceAsync, мне не нужно помещать какую-либо реализацию в метод TestGameModule.configure (); Джин управляет созданием AsyncServices для меня через GWT.create ().

Затем я добавил следующее в TestGame.gwt.xml

<inherits name='com.google.gwt.inject.Inject'/>

И, наконец, я внес следующие изменения в TestGameHtml.java

public class TestGameHtml extends HtmlGame {

    private final TestGameGinjector _injector = GWT.create(TestGameGinjector.class);

    @Override
    public void start() {
        HtmlPlatform platform = HtmlPlatform.register();
        platform.assetManager().setPathPrefix("test/");
        PlayN.run(_injector.getGame());
    }
}

И это в значительной степени охватывает платформу HTML5 для PlayN.

Для платформы Java я добавляю следующие координаты зависимостей в java / pom.xml:

<dependency>
  <groupId>com.gdevelop.gwt.syncrpc</groupId>
  <artifactId>gwt-syncproxy</artifactId>
  <version>0.4-SNAPSHOT</version>
</dependency>

<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>3.0-rc2</version>
</dependency>

Обратите внимание, что проект gwt-syncproxy в Google Code не содержит pom.xml. У меня есть mavenized версия gwt-syncproxy, разветвленная и доступная через git по адресу https://bitbucket.org/hatboyzero/gwt-syncproxy.git.. Вы сможете ее клонировать, запустите mvn clean package install , чтобы получить ее в ваш местный репозиторий Maven.

В любом случае, я создал TestGameModule.java для платформы Java следующим образом:

public class TestGameModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(TestServiceAsync.class).toProvider(TestServiceProvider.class);
    }

    public static class TestServiceProvider implements Provider<TestServiceAsync> {
        public TestServiceAsync get() {
            return (TestServiceAsync) SyncProxy.newProxyInstance(
                TestServiceAsync.class,
                Deployment.gwtWebPath(),  // URL to webapp -- http://127.0.0.1:8888/testgame
                "test"
            );
        }
    }
}

И я изменил TestGameJava.java следующим образом:

public class TestGameJava {

    public static void main(String[] args) {
        Injector _injector = Guice.createInjector(new TestGameModule());

        JavaPlatform platform = JavaPlatform.register();
        platform.assetManager().setPathPrefix("test/images");
        PlayN.run(_injector.getInstance(TestGame.class));
    }
}

Я прошел аналогичное упражнение с платформой Android и RoboGuice - не вдаваясь в огромные детали, соответствующие изменения / фрагменты выглядят следующим образом:

зависимости pom.xml

<dependency>
  <groupId>com.gdevelop.gwt.syncrpc</groupId>
  <artifactId>gwt-syncproxy</artifactId>
  <version>0.4-SNAPSHOT</version>
</dependency>

<dependency>
  <groupId>org.roboguice</groupId>
  <artifactId>roboguice</artifactId>
  <version>1.1.2</version>
</dependency>

<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>3.0-rc2</version>
  <classifier>no_aop</classifier>
</dependency>

TestGameApplication.java

public class TestGameApplication extends RoboApplication {
    @Override
    protected void addApplicationModules(List<Module> modules) {
        modules.add(new TestGameModule());
    }
}

TestGameModule.java

public class TestGameModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(TestServiceAsync.class).toProvider(TestServiceProvider.class);
    }

    public static class TestServiceProvider implements Provider<TestServiceAsync> {
        public TestServiceAsync get() {
            return (TestServiceAsync) SyncProxy.newProxyInstance(
                TestServiceAsync.class,
                Deployment.gwtWebPath(),  // URL to webapp -- http://127.0.0.1:8888/testgame
                "test"
            );
        }
    }
}

TestGameActivity.java

public class TestGameActivity extends GameActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    final Injector injector = ((RoboApplication) getApplication()).getInjector();
        injector.injectMembers(this);
        super.onCreate(savedInstanceState);
    }

    @Override
    public void main(){
        platform().assetManager().setPathPrefix("test/images");
        final Injector injector = ((RoboApplication) getApplication()).getInjector();
        PlayN.run(injector.getInstance(TestGame.class));
    }
}

Это краткое и грязное изложение того, как я запустил Gin / Guice / RoboGuice + GWT в моем проекте, и я убедился, что он прекрасно работает на платформах Java и HTML.

В любом случае, существует подход GWT для предоставления вызовов RPC на несколько платформ PlayN:).

...