project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/GameConnection.java
changeset 10017 de822cd3df3a
parent 7588 27e5857da6af
equal deleted inserted replaced
10015:4feced261c68 10017:de822cd3df3a
    46 
    46 
    47 /**
    47 /**
    48  * This class handles both talking to the engine (IPC) for running a game, and
    48  * This class handles both talking to the engine (IPC) for running a game, and
    49  * coordinating with the netconn if it is a netgame, using the frontlib for the
    49  * coordinating with the netconn if it is a netgame, using the frontlib for the
    50  * actual IPC networking communication.
    50  * actual IPC networking communication.
    51  * 
    51  *
    52  * After creating the GameConnection object, it will communicate with the engine
    52  * After creating the GameConnection object, it will communicate with the engine
    53  * on its own thread. It shuts itself down as soon as the connection to the engine
    53  * on its own thread. It shuts itself down as soon as the connection to the engine
    54  * is lost.
    54  * is lost.
    55  */
    55  */
    56 public final class GameConnection {
    56 public final class GameConnection {
    57 	private static final Handler mainHandler = new Handler(Looper.getMainLooper());
    57     private static final Handler mainHandler = new Handler(Looper.getMainLooper());
    58 	
    58 
    59 	public final int port;
    59     public final int port;
    60 	private final HandlerThread thread;
    60     private final HandlerThread thread;
    61 	private final Handler handler;
    61     private final Handler handler;
    62 	private TickHandler tickHandler;
    62     private TickHandler tickHandler;
    63 	private final Netplay netplay; // ==null if not a netgame
    63     private final Netplay netplay; // ==null if not a netgame
    64 	private GameconnPtr conn;
    64     private GameconnPtr conn;
    65 	
    65 
    66 	private GameConnection(GameconnPtr conn, Netplay netplay) {
    66     private GameConnection(GameconnPtr conn, Netplay netplay) {
    67 		this.conn = conn;
    67         this.conn = conn;
    68 		this.port = Flib.INSTANCE.flib_gameconn_getport(conn);
    68         this.port = Flib.INSTANCE.flib_gameconn_getport(conn);
    69 		this.netplay = netplay;
    69         this.netplay = netplay;
    70 		this.thread = new HandlerThread("IPCThread");
    70         this.thread = new HandlerThread("IPCThread");
    71 		thread.start();
    71         thread.start();
    72 		this.handler = new Handler(thread.getLooper());
    72         this.handler = new Handler(thread.getLooper());
    73 	}
    73     }
    74 	
    74 
    75 	private void setupConnection() {
    75     private void setupConnection() {
    76 		tickHandler = new TickHandler(thread.getLooper(), 50, tickCb);
    76         tickHandler = new TickHandler(thread.getLooper(), 50, tickCb);
    77 		tickHandler.start();
    77         tickHandler.start();
    78 		
    78 
    79 		if(netplay != null) {
    79         if(netplay != null) {
    80 			mainHandler.post(new Runnable() {
    80             mainHandler.post(new Runnable() {
    81 				public void run() { 
    81                 public void run() {
    82 					netplay.registerGameMessageListener(gameMessageListener);
    82                     netplay.registerGameMessageListener(gameMessageListener);
    83 				}
    83                 }
    84 			});
    84             });
    85 			Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null);
    85             Flib.INSTANCE.flib_gameconn_onChat(conn, chatCb, null);
    86 			Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null);
    86             Flib.INSTANCE.flib_gameconn_onEngineMessage(conn, engineMessageCb, null);
    87 		}
    87         }
    88 		Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null);
    88         Flib.INSTANCE.flib_gameconn_onConnect(conn, connectCb, null);
    89 		Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null);
    89         Flib.INSTANCE.flib_gameconn_onDisconnect(conn, disconnectCb, null);
    90 		Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null);
    90         Flib.INSTANCE.flib_gameconn_onErrorMessage(conn, errorMessageCb, null);
    91 	}
    91     }
    92 	
    92 
    93 	/**
    93     /**
    94 	 * Start a new IPC server to communicate with the engine.
    94      * Start a new IPC server to communicate with the engine.
    95 	 * Performs networking operations, don't run on the UI thread.
    95      * Performs networking operations, don't run on the UI thread.
    96 	 * @throws ConnectException if we can't set up the IPC server
    96      * @throws ConnectException if we can't set up the IPC server
    97 	 */
    97      */
    98 	public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException {
    98     public static GameConnection forNetgame(final GameConfig config, Netplay netplay) throws ConnectException {
    99 		final String playerName = netplay.getPlayerName();
    99         final String playerName = netplay.getPlayerName();
   100 		GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true);
   100         GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create(playerName, GameSetupPtr.createJavaOwned(config), true);
   101 		if(conn == null) {
   101         if(conn == null) {
   102 			throw new ConnectException();
   102             throw new ConnectException();
   103 		}
   103         }
   104 		GameConnection result = new GameConnection(conn, netplay);
   104         GameConnection result = new GameConnection(conn, netplay);
   105 		result.setupConnection();
   105         result.setupConnection();
   106 		return result;
   106         return result;
   107 	}
   107     }
   108 	
   108 
   109 	/**
   109     /**
   110 	 * Start a new IPC server to communicate with the engine.
   110      * Start a new IPC server to communicate with the engine.
   111 	 * Performs networking operations, don't run on the UI thread.
   111      * Performs networking operations, don't run on the UI thread.
   112 	 * @throws ConnectException if we can't set up the IPC server
   112      * @throws ConnectException if we can't set up the IPC server
   113 	 */
   113      */
   114 	public static GameConnection forLocalGame(final GameConfig config) throws ConnectException {
   114     public static GameConnection forLocalGame(final GameConfig config) throws ConnectException {
   115 		GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false);
   115         GameconnPtr conn = Flib.INSTANCE.flib_gameconn_create("Player", GameSetupPtr.createJavaOwned(config), false);
   116 		if(conn == null) {
   116         if(conn == null) {
   117 			throw new ConnectException();
   117             throw new ConnectException();
   118 		}
   118         }
   119 		GameConnection result = new GameConnection(conn, null);
   119         GameConnection result = new GameConnection(conn, null);
   120 		result.setupConnection();
   120         result.setupConnection();
   121 		return result;
   121         return result;
   122 	}
   122     }
   123 	
   123 
   124 	private final Runnable tickCb = new Runnable() {
   124     private final Runnable tickCb = new Runnable() {
   125 		public void run() {
   125         public void run() {
   126 			Flib.INSTANCE.flib_gameconn_tick(conn);
   126             Flib.INSTANCE.flib_gameconn_tick(conn);
   127 		}
   127         }
   128 	};
   128     };
   129 	
   129 
   130 	// runs on the IPCThread
   130     // runs on the IPCThread
   131 	private void shutdown() {
   131     private void shutdown() {
   132 		tickHandler.stop();
   132         tickHandler.stop();
   133 		thread.quit();
   133         thread.quit();
   134 		Flib.INSTANCE.flib_gameconn_destroy(conn);
   134         Flib.INSTANCE.flib_gameconn_destroy(conn);
   135 		conn = null;
   135         conn = null;
   136 		if(netplay != null) {
   136         if(netplay != null) {
   137 			mainHandler.post(new Runnable() {
   137             mainHandler.post(new Runnable() {
   138 				public void run() {
   138                 public void run() {
   139 					netplay.unregisterGameMessageListener(gameMessageListener);
   139                     netplay.unregisterGameMessageListener(gameMessageListener);
   140 				}
   140                 }
   141 			});
   141             });
   142 		}
   142         }
   143 	}
   143     }
   144 	
   144 
   145 	// runs on the IPCThread
   145     // runs on the IPCThread
   146 	private final StrBoolCallback chatCb = new StrBoolCallback() {
   146     private final StrBoolCallback chatCb = new StrBoolCallback() {
   147 		public void callback(Pointer context, String message, boolean teamChat) {
   147         public void callback(Pointer context, String message, boolean teamChat) {
   148 			if(teamChat) {
   148             if(teamChat) {
   149 				netplay.sendTeamChat(message);
   149                 netplay.sendTeamChat(message);
   150 			} else {
   150             } else {
   151 				netplay.sendChat(message);
   151                 netplay.sendChat(message);
   152 			}
   152             }
   153 		}
   153         }
   154 	};
   154     };
   155 	
   155 
   156 	// runs on the IPCThread
   156     // runs on the IPCThread
   157 	private final VoidCallback connectCb = new VoidCallback() {
   157     private final VoidCallback connectCb = new VoidCallback() {
   158 		public void callback(Pointer context) {
   158         public void callback(Pointer context) {
   159 			Log.i("GameConnection", "Connected");
   159             Log.i("GameConnection", "Connected");
   160 		}
   160         }
   161 	};
   161     };
   162 	
   162 
   163 	// runs on the IPCThread
   163     // runs on the IPCThread
   164 	private final IntCallback disconnectCb = new IntCallback() {
   164     private final IntCallback disconnectCb = new IntCallback() {
   165 		public void callback(Pointer context, int reason) {
   165         public void callback(Pointer context, int reason) {
   166 			if(netplay != null) {
   166             if(netplay != null) {
   167 				netplay.sendRoundFinished(reason==Frontlib.GAME_END_FINISHED);
   167                 netplay.sendRoundFinished(reason==Frontlib.GAME_END_FINISHED);
   168 			}
   168             }
   169 			shutdown();
   169             shutdown();
   170 		}
   170         }
   171 	};
   171     };
   172 	
   172 
   173 	// runs on the IPCThread
   173     // runs on the IPCThread
   174 	private final BytesCallback engineMessageCb = new BytesCallback() {
   174     private final BytesCallback engineMessageCb = new BytesCallback() {
   175 		public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) {
   175         public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) {
   176 			netplay.sendEngineMessage(buffer.deref(size.intValue()));
   176             netplay.sendEngineMessage(buffer.deref(size.intValue()));
   177 		}
   177         }
   178 	};
   178     };
   179 	
   179 
   180 	// runs on the IPCThread
   180     // runs on the IPCThread
   181 	private final StrCallback errorMessageCb = new StrCallback() {
   181     private final StrCallback errorMessageCb = new StrCallback() {
   182 		public void callback(Pointer context, String message) {
   182         public void callback(Pointer context, String message) {
   183 			Log.e("GameConnection", message);
   183             Log.e("GameConnection", message);
   184 		}
   184         }
   185 	};
   185     };
   186 	
   186 
   187 	// runs on any thread
   187     // runs on any thread
   188 	private final GameMessageListener gameMessageListener = new GameMessageListener() {
   188     private final GameMessageListener gameMessageListener = new GameMessageListener() {
   189 		public void onNetDisconnected() {
   189         public void onNetDisconnected() {
   190 			handler.post(new Runnable() {
   190             handler.post(new Runnable() {
   191 				public void run() {
   191                 public void run() {
   192 					Flib.INSTANCE.flib_gameconn_send_quit(conn);
   192                     Flib.INSTANCE.flib_gameconn_send_quit(conn);
   193 				}
   193                 }
   194 			});
   194             });
   195 		}
   195         }
   196 		
   196 
   197 		public void onMessage(final int type, final String message) {
   197         public void onMessage(final int type, final String message) {
   198 			handler.post(new Runnable() {
   198             handler.post(new Runnable() {
   199 				public void run() {
   199                 public void run() {
   200 					Flib.INSTANCE.flib_gameconn_send_textmsg(conn, type, message);
   200                     Flib.INSTANCE.flib_gameconn_send_textmsg(conn, type, message);
   201 				}
   201                 }
   202 			});
   202             });
   203 		}
   203         }
   204 		
   204 
   205 		public void onEngineMessage(final byte[] em) {
   205         public void onEngineMessage(final byte[] em) {
   206 			handler.post(new Runnable() {
   206             handler.post(new Runnable() {
   207 				public void run() {
   207                 public void run() {
   208 					ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(em);
   208                     ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(em);
   209 					Flib.INSTANCE.flib_gameconn_send_enginemsg(conn, ptr, NativeSizeT.valueOf(em.length));
   209                     Flib.INSTANCE.flib_gameconn_send_enginemsg(conn, ptr, NativeSizeT.valueOf(em.length));
   210 				}
   210                 }
   211 			});
   211             });
   212 		}
   212         }
   213 		
   213 
   214 		public void onChatMessage(final String nick, final String message) {
   214         public void onChatMessage(final String nick, final String message) {
   215 			handler.post(new Runnable() {
   215             handler.post(new Runnable() {
   216 				public void run() {
   216                 public void run() {
   217 					Flib.INSTANCE.flib_gameconn_send_chatmsg(conn, nick, message);
   217                     Flib.INSTANCE.flib_gameconn_send_chatmsg(conn, nick, message);
   218 				}
   218                 }
   219 			});
   219             });
   220 		}
   220         }
   221 	};
   221     };
   222 }
   222 }