如何在客户端-服务器 PlayN 游戏中处理 RPC?

发布于 2024-12-29 19:03:00 字数 579 浏览 3 评论 0原文

我想使用 PlayN 创建客户端/服务器纸牌游戏,例如红心大战。虽然我主要关注 HTML5 输出,但我希望与输出平台无关,以防我将来决定制作 Android 客户端。我应该如何处理RPC机制?

这些是我想到的选项:

  1. 将 JSON 用于具有 get()/post() 方法的 RPC - 编写一个接受/返回 JSON 的 servlet,并使所有版本的客户端代码都使用它。这似乎可行,但我担心 JSON 的冗长。一旦我让红心大战开始工作,我想转向更复杂的游戏,并且我担心 JSON 会导致大量超出必要的消息在客户端和服务器之间来回传递。我实际上不知道如何在 Java 中使用 JSON,但我认为这是可行的。我的假设符合吗? Java 与 JSON 的配合如何?
  2. 继续使用 GWT-RPC。我可以通过在核心(与平台无关)构造函数中采用异步服务接口来实现此目的,并在 HTML main() 中传入由 GWT.create(MyService.class) 生成的 GWT 异步接口 (或者至少有一个包装器)。我不知道这对于非 HTML 版本来说效果如何。我可以直接从客户端 Java 代码使用 GWT-RPC 吗?
  3. 使用其他形式的 RPC。有什么建议吗?

I'd like to use PlayN to create a client/server card game, e.g. Hearts. While I'm mostly focusing on the HTML5 output, I'd ideally like to be output-platform-agnostic in case I decide to make an Android client in the future. How should I approach the RPC mechanism?

These are the options I've thought of:

  1. Use JSON for RPCs with get()/post() methods - write a servlet that accepts/returns JSON, and make all versions of client code use that. This seems doable, but I'm concerned about JSON's verbosity. Once I get Hearts working I'd like to move on to more complex games, and I'm worried that JSON will result in a lot of much-larger-than-necessary messages being passed back and forth between client and server. I don't actually know how to work with JSON in Java, but I assume this is doable. Are my assumptions in-line? How well does Java work with JSON?
  2. Continue using GWT-RPC. I can do this by taking an asynchronous service interface in my core (platform-agnostic) constructor, and in my HTML main() I pass in the GWT Async interface generated by GWT.create(MyService.class) (or at least a wrapper around it). I have no idea how well this would work for non-HTML versions though. Is it possible for me to use GWT-RPC from client-side Java code directly?
  3. Use some other form of RPC. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

似最初 2025-01-05 19:03:00

对于 Java 和 Android 平台上的 GWT RPC,我目前正在尝试使用 gwt-syncproxy 提供 Java 客户端对 GWT RPC 方法的访问,并且我在各自的目标平台上使用 Guice、Gin 和 RoboGuice 进行注入实例化 Game 对象的适当异步服务实例。

在 PlayN 项目的 core/pom.xml 中,我包含以下依赖项坐标,以根据需要支持来自 Gin/Guice/RoboGuice 的 DI:

<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() 方法中放置任何实现; Gin 通过 GWT.create() 为我管理 AsyncServices 的实例化。

然后,我将以下内容添加到 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());
    }
}

,这几乎涵盖了 PlayN 的 HTML5 平台。

对于 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>

请注意,Google Code 上的 gwt-syncproxy 项目不包含 pom.xml。我有一个 mavenized 版本的 gwt-syncproxy 分支,可以通过 git 在 https 获取://bitbucket.org/hatboyzero/gwt-syncproxy.git。您应该能够克隆它,运行 mvn clean package install 将其放入本地 Maven 存储库。

无论如何,我为 Java 平台创建了一个 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"
            );
        }
    }
}

我修改了 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 方法可以向多个 PlayN 平台提供 RPC 调用:)。

For the GWT RPC on the Java and Android platforms, I'm currently experimenting with using gwt-syncproxy to provide Java client access to the GWT RPC methods, and I'm using Guice, Gin, and RoboGuice on their respective target platforms to inject the appropriate asynchronous service instances for the instantiated Game object.

In the core/pom.xml for a PlayN project, I include the following dependency coordinates to support DI from Gin/Guice/RoboGuice as needed:

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

Then I add @Inject annotations to any fields inside of the concrete Game implementation:

public class TestGame implements Game {

    @Inject
    TestServiceAsync _testService;

    ...

}

In the html/pom.xml, I include the dependency coordinates for Gin:

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

And I create TestGameGinjector and TestGameModule classes:

TestGameGinjector.java

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

TestGameModule.java

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

Since at the moment, I'm only injecting the TestServiceAsync interface, I don't need to put any implementation in the TestGameModule.configure() method; Gin manages instantiation of AsyncServices for me via GWT.create().

I then added the following to TestGame.gwt.xml

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

And finally, I made the following changes to 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());
    }
}

And this pretty much covers the HTML5 platform for PlayN.

For the Java platform, I add the following dependency coordinates to 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>

Do note that the gwt-syncproxy project on Google Code does not contain a pom.xml. I have a mavenized version of gwt-syncproxy forked and available via git at https://bitbucket.org/hatboyzero/gwt-syncproxy.git. You should be able to clone it, run mvn clean package install to get it into your local Maven repository.

Anyways, I created a TestGameModule.java for the Java platform as follows:

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"
            );
        }
    }
}

And I modified TestGameJava.java as follows:

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));
    }
}

I went through a similar exercise with the Android platform and RoboGuice -- without going into tremendous detail, the relevant changes/snippets are as follows:

pom.xml dependencies

<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));
    }
}

That's a quick and dirty rundown of how I got Gin/Guice/RoboGuice + GWT working in my project, and I have verified that it works on both Java and HTML platforms beautifully.

Anyways, there's the GWT approach to providing RPC calls to multiple PlayN platforms :).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文