--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Mon Aug 20 20:16:37 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java Mon Aug 20 20:19:35 2012 +0200
@@ -1,5 +1,26 @@
+/*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (C) 2012 Simeon Maxein <smaxein@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
package org.hedgewars.hedgeroid;
+import java.net.ConnectException;
+
import org.hedgewars.hedgeroid.Datastructures.GameConfig;
import org.hedgewars.hedgeroid.frontlib.Flib;
import org.hedgewars.hedgeroid.frontlib.Frontlib;
@@ -23,106 +44,95 @@
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
+/**
+ * This class handles both talking to the engine (IPC) for running a game, and
+ * coordinating with the netconn if it is a netgame, using the frontlib for the
+ * actual IPC networking communication.
+ *
+ * After creating the GameConnection object, it will communicate with the engine
+ * on its own thread. It shuts itself down as soon as the connection to the engine
+ * is lost.
+ */
public final class GameConnection {
private static final Handler mainHandler = new Handler(Looper.getMainLooper());
+ public final int port;
private final HandlerThread thread;
private final Handler handler;
- private final TickHandler tickHandler;
+ private TickHandler tickHandler;
private final Netplay netplay; // ==null if not a netgame
private GameconnPtr conn;
-
- /**
- * The actual connection has to be set up on a separate thread because networking
- * is not allowed on the UI thread, so the port can't be queried immediately after
- * creating the GameConnection object. Instead, one of these interface methods is
- * called once we know which port we are listening on (or once we fail to set this up).
- * Methods will be called on the UI thread.
- */
- public static interface Listener {
- /**
- * We are listening for the engine at $port, go start the engine.
- */
- void gameConnectionReady(int port);
-
- /**
- * The connection has stopped, either because the game has ended or was interrupted,
- * or maybe we failed to create the connection at all (in that case gameConnectionReady wasn't called).
- */
- void gameConnectionDisconnected(int reason);
+
+ private GameConnection(GameconnPtr conn, Netplay netplay) {
+ this.conn = conn;
+ this.port = Flib.INSTANCE.flib_gameconn_getport(conn);
+ this.netplay = netplay;
+ this.thread = new HandlerThread("IPCThread");
+ thread.start();
+ this.handler = new Handler(thread.getLooper());
}
- private GameConnection(Netplay netplay) {
- this.netplay = netplay;
- thread = new HandlerThread("IPCThread");
- thread.start();
- handler = new Handler(thread.getLooper());
- tickHandler = new TickHandler(thread.getLooper(), 50, new Runnable() {
- public void run() {
- if(conn != null) {
- Flib.INSTANCE.flib_gameconn_tick(conn);
+ private void setupConnection() {
+ tickHandler = new TickHandler(thread.getLooper(), 50, tickCb);
+ tickHandler.start();
+
+ if(netplay != null) {
+ mainHandler.post(new Runnable() {
+ public void run() {
+ netplay.registerGameMessageListener(gameMessageListener);
}
- }
- });
- tickHandler.start();
+ });
+ Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null);
+ Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null);
+ }
+ Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null);
+ Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null);
+ Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null);
}
- public static GameConnection forNetgame(final GameConfig config, Netplay netplay, final Listener listener) {
- final GameConnection result = new GameConnection(netplay);
+ /**
+ * Start a new IPC server to communicate with the engine.
+ * Performs networking operations, don't run on the UI thread.
+ * @throws ConnectException if we can't set up the IPC server
+ */
+ public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException {
final String playerName = netplay.getPlayerName();
- result.handler.post(new Runnable() {
- public void run() {
- GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true);
- result.setupConnection(conn, true, listener);
- }
- });
+ GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true);
+ if(conn == null) {
+ throw new ConnectException();
+ }
+ GameConnection result = new GameConnection(conn, netplay);
+ result.setupConnection();
return result;
}
- public static GameConnection forLocalGame(final GameConfig config, final Listener listener) {
- final GameConnection result = new GameConnection(null);
- result.handler.post(new Runnable() {
- public void run() {
- GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false);
- result.setupConnection(conn, false, listener);
- }
- });
+ /**
+ * Start a new IPC server to communicate with the engine.
+ * Performs networking operations, don't run on the UI thread.
+ * @throws ConnectException if we can't set up the IPC server
+ */
+ public static GameConnection forLocalGame(final GameConfig config) throws ConnectException {
+ GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false);
+ if(conn == null) {
+ throw new ConnectException();
+ }
+ GameConnection result = new GameConnection(conn, null);
+ result.setupConnection();
return result;
}
- // runs on the IPCThread
- private void setupConnection(GameconnPtr conn, final boolean netgame, final Listener listener) {
- if(conn == null) {
- mainHandler.post(new Runnable() {
- public void run() { listener.gameConnectionDisconnected(Frontlib.GAME_END_ERROR); }
- });
- shutdown();
- } else {
- this.conn = conn;
- final int port = Flib.INSTANCE.flib_gameconn_getport(conn);
- mainHandler.post(new Runnable() {
- public void run() {
- listener.gameConnectionReady(port);
- if(netgame) {
- netplay.registerGameMessageListener(gameMessageListener);
- }
- }
- });
- Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null);
- Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null);
- Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null);
- if(netgame) {
- Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null);
- Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null);
- }
+ private final Runnable tickCb = new Runnable() {
+ public void run() {
+ Flib.INSTANCE.flib_gameconn_tick(conn);
}
- }
+ };
// runs on the IPCThread
private void shutdown() {
tickHandler.stop();
thread.quit();
Flib.INSTANCE.flib_gameconn_destroy(conn);
+ conn = null;
if(netplay != null) {
mainHandler.post(new Runnable() {
public void run() {
@@ -179,7 +189,7 @@
public void onNetDisconnected() {
handler.post(new Runnable() {
public void run() {
- shutdown();
+ Flib.INSTANCE.flib_gameconn_send_quit(conn);
}
});
}