76 |
76 |
77 import com.sun.jna.Pointer; |
77 import com.sun.jna.Pointer; |
78 |
78 |
79 /** |
79 /** |
80 * This class handles the actual communication with the networking library, running on a separate thread. |
80 * This class handles the actual communication with the networking library, running on a separate thread. |
81 * |
81 * |
82 * In order to process net messages, this class regularly runs a tick() function on the frontlib. This |
82 * In order to process net messages, this class regularly runs a tick() function on the frontlib. This |
83 * usually happens several times per second, but it can be slowed down a lot if no fast reaction to |
83 * usually happens several times per second, but it can be slowed down a lot if no fast reaction to |
84 * events is required (e.g. to conserve battery if the application is in the background). |
84 * events is required (e.g. to conserve battery if the application is in the background). |
85 */ |
85 */ |
86 class ThreadedNetConnection { |
86 class ThreadedNetConnection { |
87 private static final long TICK_INTERVAL_FAST = 100; |
87 private static final long TICK_INTERVAL_FAST = 100; |
88 private static final long TICK_INTERVAL_SLOW = 5000; |
88 private static final long TICK_INTERVAL_SLOW = 5000; |
89 private static final Frontlib FLIB = Flib.INSTANCE; |
89 private static final Frontlib FLIB = Flib.INSTANCE; |
90 |
90 |
91 public final ToNetHandler toNetHandler; |
91 public final ToNetHandler toNetHandler; |
92 |
92 |
93 private final Context appContext; |
93 private final Context appContext; |
94 private final FromNetHandler fromNetHandler; |
94 private final FromNetHandler fromNetHandler; |
95 private final TickHandler tickHandler; |
95 private final TickHandler tickHandler; |
96 |
96 |
97 /** |
97 /** |
98 * conn can only be null while connecting (the first thing in the thread), and directly after disconnecting, |
98 * conn can only be null while connecting (the first thing in the thread), and directly after disconnecting, |
99 * in the same message (the looper is shut down on disconnect, so there will be no messages after that). |
99 * in the same message (the looper is shut down on disconnect, so there will be no messages after that). |
100 */ |
100 */ |
101 private NetconnPtr conn; |
101 private NetconnPtr conn; |
102 private String playerName; |
102 private String playerName; |
103 |
103 |
104 private ThreadedNetConnection(Context appContext, FromNetHandler fromNetHandler) { |
104 private ThreadedNetConnection(Context appContext, FromNetHandler fromNetHandler) { |
105 this.appContext = appContext; |
105 this.appContext = appContext; |
106 this.fromNetHandler = fromNetHandler; |
106 this.fromNetHandler = fromNetHandler; |
107 |
107 |
108 HandlerThread thread = new HandlerThread("NetThread"); |
108 HandlerThread thread = new HandlerThread("NetThread"); |
109 thread.start(); |
109 thread.start(); |
110 toNetHandler = new ToNetHandler(thread.getLooper()); |
110 toNetHandler = new ToNetHandler(thread.getLooper()); |
111 tickHandler = new TickHandler(thread.getLooper(), TICK_INTERVAL_FAST, tickCb); |
111 tickHandler = new TickHandler(thread.getLooper(), TICK_INTERVAL_FAST, tickCb); |
112 } |
112 } |
113 |
113 |
114 private void connect(final String name, final String host, final int port) { |
114 private void connect(final String name, final String host, final int port) { |
115 toNetHandler.post(new Runnable() { |
115 toNetHandler.post(new Runnable() { |
116 public void run() { |
116 public void run() { |
117 playerName = name == null ? "Player" : name; |
117 playerName = name == null ? "Player" : name; |
118 File dataPath; |
118 File dataPath; |
119 try { |
119 try { |
120 dataPath = FileUtils.getDataPathFile(appContext); |
120 dataPath = FileUtils.getDataPathFile(appContext); |
121 } catch (FileNotFoundException e) { |
121 } catch (FileNotFoundException e) { |
122 shutdown(true, appContext.getString(R.string.sdcard_not_mounted)); |
122 shutdown(true, appContext.getString(R.string.sdcard_not_mounted)); |
123 return; |
123 return; |
124 } |
124 } |
125 conn = FLIB.flib_netconn_create(playerName, dataPath.getAbsolutePath()+"/", host, port); |
125 conn = FLIB.flib_netconn_create(playerName, dataPath.getAbsolutePath()+"/", host, port); |
126 if(conn == null) { |
126 if(conn == null) { |
127 shutdown(true, appContext.getString(R.string.error_connection_failed)); |
127 shutdown(true, appContext.getString(R.string.error_connection_failed)); |
128 return; |
128 return; |
129 } |
129 } |
130 |
130 |
131 FLIB.flib_netconn_onSchemeChanged(conn, cfgSchemeCb, null); |
131 FLIB.flib_netconn_onSchemeChanged(conn, cfgSchemeCb, null); |
132 FLIB.flib_netconn_onClientFlags(conn, clientFlagsCb, null); |
132 FLIB.flib_netconn_onClientFlags(conn, clientFlagsCb, null); |
133 FLIB.flib_netconn_onChat(conn, chatCb, null); |
133 FLIB.flib_netconn_onChat(conn, chatCb, null); |
134 FLIB.flib_netconn_onConnected(conn, connectedCb, null); |
134 FLIB.flib_netconn_onConnected(conn, connectedCb, null); |
135 FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null); |
135 FLIB.flib_netconn_onDisconnected(conn, disconnectCb, null); |
136 FLIB.flib_netconn_onEngineMessage(conn, engineMessageCb, null); |
136 FLIB.flib_netconn_onEngineMessage(conn, engineMessageCb, null); |
137 FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null); |
137 FLIB.flib_netconn_onEnterRoom(conn, enterRoomCb, null); |
138 FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null); |
138 FLIB.flib_netconn_onHogCountChanged(conn, hogCountChangedCb, null); |
139 FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null); |
139 FLIB.flib_netconn_onLeaveRoom(conn, leaveRoomCb, null); |
140 FLIB.flib_netconn_onLobbyJoin(conn, lobbyJoinCb, null); |
140 FLIB.flib_netconn_onLobbyJoin(conn, lobbyJoinCb, null); |
141 FLIB.flib_netconn_onLobbyLeave(conn, lobbyLeaveCb, null); |
141 FLIB.flib_netconn_onLobbyLeave(conn, lobbyLeaveCb, null); |
142 FLIB.flib_netconn_onMapChanged(conn, mapChangedCb, null); |
142 FLIB.flib_netconn_onMapChanged(conn, mapChangedCb, null); |
143 FLIB.flib_netconn_onMessage(conn, messageCb, null); |
143 FLIB.flib_netconn_onMessage(conn, messageCb, null); |
144 FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null); |
144 FLIB.flib_netconn_onPasswordRequest(conn, passwordRequestCb, null); |
145 FLIB.flib_netconn_onRoomAdd(conn, roomAddCb, null); |
145 FLIB.flib_netconn_onRoomAdd(conn, roomAddCb, null); |
146 FLIB.flib_netconn_onRoomDelete(conn, roomDeleteCb, null); |
146 FLIB.flib_netconn_onRoomDelete(conn, roomDeleteCb, null); |
147 FLIB.flib_netconn_onRoomJoin(conn, roomJoinCb, null); |
147 FLIB.flib_netconn_onRoomJoin(conn, roomJoinCb, null); |
148 FLIB.flib_netconn_onRoomLeave(conn, roomLeaveCb, null); |
148 FLIB.flib_netconn_onRoomLeave(conn, roomLeaveCb, null); |
149 FLIB.flib_netconn_onRoomlist(conn, roomlistCb, null); |
149 FLIB.flib_netconn_onRoomlist(conn, roomlistCb, null); |
150 FLIB.flib_netconn_onRoomUpdate(conn, roomUpdateCb, null); |
150 FLIB.flib_netconn_onRoomUpdate(conn, roomUpdateCb, null); |
151 FLIB.flib_netconn_onRunGame(conn, runGameCb, null); |
151 FLIB.flib_netconn_onRunGame(conn, runGameCb, null); |
152 FLIB.flib_netconn_onScriptChanged(conn, scriptChangedCb, null); |
152 FLIB.flib_netconn_onScriptChanged(conn, scriptChangedCb, null); |
153 // FLIB.flib_netconn_onServerVar(conn, serverVarCb, null); |
153 // FLIB.flib_netconn_onServerVar(conn, serverVarCb, null); |
154 FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null); |
154 FLIB.flib_netconn_onTeamAccepted(conn, teamAcceptedCb, null); |
155 FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null); |
155 FLIB.flib_netconn_onTeamAdd(conn, teamAddedCb, null); |
156 FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null); |
156 FLIB.flib_netconn_onTeamColorChanged(conn, teamColorChangedCb, null); |
157 FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null); |
157 FLIB.flib_netconn_onTeamDelete(conn, teamDeletedCb, null); |
158 FLIB.flib_netconn_onWeaponsetChanged(conn, weaponsetChangedCb, null); |
158 FLIB.flib_netconn_onWeaponsetChanged(conn, weaponsetChangedCb, null); |
159 |
159 |
160 tickHandler.start(); |
160 tickHandler.start(); |
161 } |
161 } |
162 }); |
162 }); |
163 } |
163 } |
164 |
164 |
165 public static ThreadedNetConnection startConnection(Context appContext, FromNetHandler fromNetHandler, String playerName, String host, int port) { |
165 public static ThreadedNetConnection startConnection(Context appContext, FromNetHandler fromNetHandler, String playerName, String host, int port) { |
166 ThreadedNetConnection result = new ThreadedNetConnection(appContext, fromNetHandler); |
166 ThreadedNetConnection result = new ThreadedNetConnection(appContext, fromNetHandler); |
167 result.connect(playerName, host, port); |
167 result.connect(playerName, host, port); |
168 return result; |
168 return result; |
169 } |
169 } |
170 |
170 |
171 public void setFastTickRate(boolean fastTickRate) { |
171 public void setFastTickRate(boolean fastTickRate) { |
172 tickHandler.setInterval(fastTickRate ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW); |
172 tickHandler.setInterval(fastTickRate ? TICK_INTERVAL_FAST : TICK_INTERVAL_SLOW); |
173 } |
173 } |
174 |
174 |
175 private final Runnable tickCb = new Runnable() { |
175 private final Runnable tickCb = new Runnable() { |
176 public void run() { |
176 public void run() { |
177 FLIB.flib_netconn_tick(conn); |
177 FLIB.flib_netconn_tick(conn); |
178 } |
178 } |
179 }; |
179 }; |
180 |
180 |
181 private final SchemeCallback cfgSchemeCb = new SchemeCallback() { |
181 private final SchemeCallback cfgSchemeCb = new SchemeCallback() { |
182 public void callback(Pointer context, SchemePtr schemePtr) { |
182 public void callback(Pointer context, SchemePtr schemePtr) { |
183 sendFromNet(MSG_SCHEME_CHANGED, schemePtr.deref()); |
183 sendFromNet(MSG_SCHEME_CHANGED, schemePtr.deref()); |
184 } |
184 } |
185 }; |
185 }; |
186 |
186 |
187 private final MapIntCallback mapChangedCb = new MapIntCallback() { |
187 private final MapIntCallback mapChangedCb = new MapIntCallback() { |
188 public void callback(Pointer context, MapRecipePtr mapPtr, int updateType) { |
188 public void callback(Pointer context, MapRecipePtr mapPtr, int updateType) { |
189 sendFromNet(MSG_MAP_CHANGED, updateType, mapPtr.deref()); |
189 sendFromNet(MSG_MAP_CHANGED, updateType, mapPtr.deref()); |
190 } |
190 } |
191 }; |
191 }; |
192 |
192 |
193 private final StrCallback scriptChangedCb = new StrCallback() { |
193 private final StrCallback scriptChangedCb = new StrCallback() { |
194 public void callback(Pointer context, String script) { |
194 public void callback(Pointer context, String script) { |
195 sendFromNet(MSG_SCRIPT_CHANGED, script); |
195 sendFromNet(MSG_SCRIPT_CHANGED, script); |
196 } |
196 } |
197 }; |
197 }; |
198 |
198 |
199 private final WeaponsetCallback weaponsetChangedCb = new WeaponsetCallback() { |
199 private final WeaponsetCallback weaponsetChangedCb = new WeaponsetCallback() { |
200 public void callback(Pointer context, WeaponsetPtr weaponsetPtr) { |
200 public void callback(Pointer context, WeaponsetPtr weaponsetPtr) { |
201 sendFromNet(MSG_WEAPONSET_CHANGED, weaponsetPtr.deref()); |
201 sendFromNet(MSG_WEAPONSET_CHANGED, weaponsetPtr.deref()); |
202 } |
202 } |
203 }; |
203 }; |
204 |
204 |
205 private final StrCallback lobbyJoinCb = new StrCallback() { |
205 private final StrCallback lobbyJoinCb = new StrCallback() { |
206 public void callback(Pointer context, String name) { |
206 public void callback(Pointer context, String name) { |
207 sendFromNet(MSG_LOBBY_JOIN, name); |
207 sendFromNet(MSG_LOBBY_JOIN, name); |
208 } |
208 } |
209 }; |
209 }; |
210 |
210 |
211 private final StrStrCallback lobbyLeaveCb = new StrStrCallback() { |
211 private final StrStrCallback lobbyLeaveCb = new StrStrCallback() { |
212 public void callback(Pointer context, String name, String msg) { |
212 public void callback(Pointer context, String name, String msg) { |
213 sendFromNet(MSG_LOBBY_LEAVE, Pair.create(name, msg)); |
213 sendFromNet(MSG_LOBBY_LEAVE, Pair.create(name, msg)); |
214 } |
214 } |
215 }; |
215 }; |
216 |
216 |
217 private final StrCallback roomJoinCb = new StrCallback() { |
217 private final StrCallback roomJoinCb = new StrCallback() { |
218 public void callback(Pointer context, String name) { |
218 public void callback(Pointer context, String name) { |
219 sendFromNet(MSG_ROOM_JOIN, name); |
219 sendFromNet(MSG_ROOM_JOIN, name); |
220 } |
220 } |
221 }; |
221 }; |
222 |
222 |
223 private final StrStrCallback roomLeaveCb = new StrStrCallback() { |
223 private final StrStrCallback roomLeaveCb = new StrStrCallback() { |
224 public void callback(Pointer context, String name, String message) { |
224 public void callback(Pointer context, String name, String message) { |
225 sendFromNet(MSG_ROOM_LEAVE, Pair.create(name, message)); |
225 sendFromNet(MSG_ROOM_LEAVE, Pair.create(name, message)); |
226 } |
226 } |
227 }; |
227 }; |
228 |
228 |
229 private final StrStrBoolCallback clientFlagsCb = new StrStrBoolCallback() { |
229 private final StrStrBoolCallback clientFlagsCb = new StrStrBoolCallback() { |
230 public void callback(Pointer context, String nick, String flags, boolean newFlagsState) { |
230 public void callback(Pointer context, String nick, String flags, boolean newFlagsState) { |
231 sendFromNet(MSG_CLIENT_FLAGS, new ClientFlagsUpdate(nick, flags, newFlagsState)); |
231 sendFromNet(MSG_CLIENT_FLAGS, new ClientFlagsUpdate(nick, flags, newFlagsState)); |
232 } |
232 } |
233 }; |
233 }; |
234 |
234 |
235 private final StrStrCallback chatCb = new StrStrCallback() { |
235 private final StrStrCallback chatCb = new StrStrCallback() { |
236 public void callback(Pointer context, String name, String msg) { |
236 public void callback(Pointer context, String name, String msg) { |
237 sendFromNet(MSG_CHAT, Pair.create(name, msg)); |
237 sendFromNet(MSG_CHAT, Pair.create(name, msg)); |
238 } |
238 } |
239 }; |
239 }; |
240 |
240 |
241 private final IntStrCallback messageCb = new IntStrCallback() { |
241 private final IntStrCallback messageCb = new IntStrCallback() { |
242 public void callback(Pointer context, int type, String msg) { |
242 public void callback(Pointer context, int type, String msg) { |
243 sendFromNet(MSG_MESSAGE, type, msg); |
243 sendFromNet(MSG_MESSAGE, type, msg); |
244 } |
244 } |
245 }; |
245 }; |
246 |
246 |
247 private final RoomCallback roomAddCb = new RoomCallback() { |
247 private final RoomCallback roomAddCb = new RoomCallback() { |
248 public void callback(Pointer context, RoomPtr roomPtr) { |
248 public void callback(Pointer context, RoomPtr roomPtr) { |
249 sendFromNet(MSG_ROOM_ADD, roomPtr.deref()); |
249 sendFromNet(MSG_ROOM_ADD, roomPtr.deref()); |
250 } |
250 } |
251 }; |
251 }; |
252 |
252 |
253 private final StrRoomCallback roomUpdateCb = new StrRoomCallback() { |
253 private final StrRoomCallback roomUpdateCb = new StrRoomCallback() { |
254 public void callback(Pointer context, String name, RoomPtr roomPtr) { |
254 public void callback(Pointer context, String name, RoomPtr roomPtr) { |
255 sendFromNet(MSG_ROOM_UPDATE, Pair.create(name, roomPtr.deref())); |
255 sendFromNet(MSG_ROOM_UPDATE, Pair.create(name, roomPtr.deref())); |
256 } |
256 } |
257 }; |
257 }; |
258 |
258 |
259 private final StrCallback roomDeleteCb = new StrCallback() { |
259 private final StrCallback roomDeleteCb = new StrCallback() { |
260 public void callback(Pointer context, final String name) { |
260 public void callback(Pointer context, final String name) { |
261 sendFromNet(MSG_ROOM_DELETE, name); |
261 sendFromNet(MSG_ROOM_DELETE, name); |
262 } |
262 } |
263 }; |
263 }; |
264 |
264 |
265 private final RoomListCallback roomlistCb = new RoomListCallback() { |
265 private final RoomListCallback roomlistCb = new RoomListCallback() { |
266 public void callback(Pointer context, RoomArrayPtr arg1, int count) { |
266 public void callback(Pointer context, RoomArrayPtr arg1, int count) { |
267 sendFromNet(MSG_ROOMLIST, arg1.getRooms(count)); |
267 sendFromNet(MSG_ROOMLIST, arg1.getRooms(count)); |
268 } |
268 } |
269 }; |
269 }; |
270 |
270 |
271 private final VoidCallback connectedCb = new VoidCallback() { |
271 private final VoidCallback connectedCb = new VoidCallback() { |
272 public void callback(Pointer context) { |
272 public void callback(Pointer context) { |
273 FLIB.flib_netconn_send_request_roomlist(conn); |
273 FLIB.flib_netconn_send_request_roomlist(conn); |
274 playerName = FLIB.flib_netconn_get_playername(conn); |
274 playerName = FLIB.flib_netconn_get_playername(conn); |
275 sendFromNet(MSG_CONNECTED, playerName); |
275 sendFromNet(MSG_CONNECTED, playerName); |
276 } |
276 } |
277 }; |
277 }; |
278 |
278 |
279 private final StrCallback passwordRequestCb = new StrCallback() { |
279 private final StrCallback passwordRequestCb = new StrCallback() { |
280 public void callback(Pointer context, String nickname) { |
280 public void callback(Pointer context, String nickname) { |
281 sendFromNet(MSG_PASSWORD_REQUEST, playerName); |
281 sendFromNet(MSG_PASSWORD_REQUEST, playerName); |
282 } |
282 } |
283 }; |
283 }; |
284 |
284 |
285 private final BoolCallback enterRoomCb = new BoolCallback() { |
285 private final BoolCallback enterRoomCb = new BoolCallback() { |
286 public void callback(Pointer context, boolean isChief) { |
286 public void callback(Pointer context, boolean isChief) { |
287 sendFromNet(MSG_ENTER_ROOM_FROM_LOBBY, isChief); |
287 sendFromNet(MSG_ENTER_ROOM_FROM_LOBBY, isChief); |
288 } |
288 } |
289 }; |
289 }; |
290 |
290 |
291 private final IntStrCallback leaveRoomCb = new IntStrCallback() { |
291 private final IntStrCallback leaveRoomCb = new IntStrCallback() { |
292 public void callback(Pointer context, int reason, String message) { |
292 public void callback(Pointer context, int reason, String message) { |
293 sendFromNet(MSG_LEAVE_ROOM, reason, message); |
293 sendFromNet(MSG_LEAVE_ROOM, reason, message); |
294 } |
294 } |
295 }; |
295 }; |
296 |
296 |
297 private final TeamCallback teamAddedCb = new TeamCallback() { |
297 private final TeamCallback teamAddedCb = new TeamCallback() { |
298 public void callback(Pointer context, TeamPtr team) { |
298 public void callback(Pointer context, TeamPtr team) { |
299 sendFromNet(MSG_TEAM_ADDED, team.deref()); |
299 sendFromNet(MSG_TEAM_ADDED, team.deref()); |
300 } |
300 } |
301 }; |
301 }; |
302 |
302 |
303 private final StrCallback teamDeletedCb = new StrCallback() { |
303 private final StrCallback teamDeletedCb = new StrCallback() { |
304 public void callback(Pointer context, String teamName) { |
304 public void callback(Pointer context, String teamName) { |
305 sendFromNet(MSG_TEAM_DELETED, teamName); |
305 sendFromNet(MSG_TEAM_DELETED, teamName); |
306 } |
306 } |
307 }; |
307 }; |
308 |
308 |
309 private final StrCallback teamAcceptedCb = new StrCallback() { |
309 private final StrCallback teamAcceptedCb = new StrCallback() { |
310 public void callback(Pointer context, String teamName) { |
310 public void callback(Pointer context, String teamName) { |
311 sendFromNet(MSG_TEAM_ACCEPTED, teamName); |
311 sendFromNet(MSG_TEAM_ACCEPTED, teamName); |
312 } |
312 } |
313 }; |
313 }; |
314 |
314 |
315 private final StrIntCallback teamColorChangedCb = new StrIntCallback() { |
315 private final StrIntCallback teamColorChangedCb = new StrIntCallback() { |
316 public void callback(Pointer context, String teamName, int colorIndex) { |
316 public void callback(Pointer context, String teamName, int colorIndex) { |
317 sendFromNet(MSG_TEAM_COLOR_CHANGED, colorIndex, teamName); |
317 sendFromNet(MSG_TEAM_COLOR_CHANGED, colorIndex, teamName); |
318 } |
318 } |
319 }; |
319 }; |
320 |
320 |
321 private final StrIntCallback hogCountChangedCb = new StrIntCallback() { |
321 private final StrIntCallback hogCountChangedCb = new StrIntCallback() { |
322 public void callback(Pointer context, String teamName, int hogCount) { |
322 public void callback(Pointer context, String teamName, int hogCount) { |
323 sendFromNet(MSG_HOG_COUNT_CHANGED, hogCount, teamName); |
323 sendFromNet(MSG_HOG_COUNT_CHANGED, hogCount, teamName); |
324 } |
324 } |
325 }; |
325 }; |
326 |
326 |
327 private final BytesCallback engineMessageCb = new BytesCallback() { |
327 private final BytesCallback engineMessageCb = new BytesCallback() { |
328 public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { |
328 public void callback(Pointer context, ByteArrayPtr buffer, NativeSizeT size) { |
329 sendFromNet(MSG_ENGINE_MESSAGE, buffer.deref(size.intValue())); |
329 sendFromNet(MSG_ENGINE_MESSAGE, buffer.deref(size.intValue())); |
330 } |
330 } |
331 }; |
331 }; |
332 |
332 |
333 private final VoidCallback runGameCb = new VoidCallback() { |
333 private final VoidCallback runGameCb = new VoidCallback() { |
334 public void callback(Pointer context) { |
334 public void callback(Pointer context) { |
335 GameSetupPtr configPtr = FLIB.flib_netconn_create_gamesetup(conn); |
335 GameSetupPtr configPtr = FLIB.flib_netconn_create_gamesetup(conn); |
336 sendFromNet(MSG_RUN_GAME, configPtr.deref()); |
336 sendFromNet(MSG_RUN_GAME, configPtr.deref()); |
337 FLIB.flib_gamesetup_destroy(configPtr); |
337 FLIB.flib_gamesetup_destroy(configPtr); |
338 } |
338 } |
339 }; |
339 }; |
340 |
340 |
341 private void shutdown(boolean error, String message) { |
341 private void shutdown(boolean error, String message) { |
342 if(conn != null) { |
342 if(conn != null) { |
343 FLIB.flib_netconn_destroy(conn); |
343 FLIB.flib_netconn_destroy(conn); |
344 conn = null; |
344 conn = null; |
345 } |
345 } |
346 tickHandler.stop(); |
346 tickHandler.stop(); |
347 toNetHandler.getLooper().quit(); |
347 toNetHandler.getLooper().quit(); |
348 sendFromNet(MSG_DISCONNECTED, Pair.create(error, message)); |
348 sendFromNet(MSG_DISCONNECTED, Pair.create(error, message)); |
349 } |
349 } |
350 |
350 |
351 private final IntStrCallback disconnectCb = new IntStrCallback() { |
351 private final IntStrCallback disconnectCb = new IntStrCallback() { |
352 public void callback(Pointer context, int reason, String message) { |
352 public void callback(Pointer context, int reason, String message) { |
353 Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL; |
353 Boolean error = reason != Frontlib.NETCONN_DISCONNECT_NORMAL; |
354 String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message); |
354 String messageForUser = createDisconnectUserMessage(appContext.getResources(), reason, message); |
355 shutdown(error, messageForUser); |
355 shutdown(error, messageForUser); |
356 } |
356 } |
357 }; |
357 }; |
358 |
358 |
359 private static String createDisconnectUserMessage(Resources res, int reason, String message) { |
359 private static String createDisconnectUserMessage(Resources res, int reason, String message) { |
360 switch(reason) { |
360 switch(reason) { |
361 case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED: |
361 case Frontlib.NETCONN_DISCONNECT_AUTH_FAILED: |
362 return res.getString(R.string.error_auth_failed); |
362 return res.getString(R.string.error_auth_failed); |
363 case Frontlib.NETCONN_DISCONNECT_CONNLOST: |
363 case Frontlib.NETCONN_DISCONNECT_CONNLOST: |
364 return res.getString(R.string.error_connection_lost); |
364 return res.getString(R.string.error_connection_lost); |
365 case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR: |
365 case Frontlib.NETCONN_DISCONNECT_INTERNAL_ERROR: |
366 return res.getString(R.string.error_unexpected, message); |
366 return res.getString(R.string.error_unexpected, message); |
367 case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD: |
367 case Frontlib.NETCONN_DISCONNECT_SERVER_TOO_OLD: |
368 return res.getString(R.string.error_server_too_old); |
368 return res.getString(R.string.error_server_too_old); |
369 default: |
369 default: |
370 return message; |
370 return message; |
371 } |
371 } |
372 } |
372 } |
373 |
373 |
374 private boolean sendFromNet(FromNetMsgType what, Object obj) { |
374 private boolean sendFromNet(FromNetMsgType what, Object obj) { |
375 return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), obj)); |
375 return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), obj)); |
376 } |
376 } |
377 |
377 |
378 private boolean sendFromNet(FromNetMsgType what, int arg1, Object obj) { |
378 private boolean sendFromNet(FromNetMsgType what, int arg1, Object obj) { |
379 return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), arg1, 0, obj)); |
379 return fromNetHandler.sendMessage(fromNetHandler.obtainMessage(what.ordinal(), arg1, 0, obj)); |
380 } |
380 } |
381 |
381 |
382 static enum ToNetMsgType { |
382 static enum ToNetMsgType { |
383 MSG_SEND_NICK, |
383 MSG_SEND_NICK, |
384 MSG_SEND_PASSWORD, |
384 MSG_SEND_PASSWORD, |
385 MSG_SEND_QUIT, |
385 MSG_SEND_QUIT, |
386 MSG_SEND_ROOMLIST_REQUEST, |
386 MSG_SEND_ROOMLIST_REQUEST, |
387 MSG_SEND_PLAYER_INFO_REQUEST, |
387 MSG_SEND_PLAYER_INFO_REQUEST, |
388 MSG_SEND_CHAT, |
388 MSG_SEND_CHAT, |
389 MSG_SEND_TEAMCHAT, |
389 MSG_SEND_TEAMCHAT, |
390 MSG_SEND_FOLLOW_PLAYER, |
390 MSG_SEND_FOLLOW_PLAYER, |
391 MSG_SEND_JOIN_ROOM, |
391 MSG_SEND_JOIN_ROOM, |
392 MSG_SEND_CREATE_ROOM, |
392 MSG_SEND_CREATE_ROOM, |
393 MSG_SEND_LEAVE_ROOM, |
393 MSG_SEND_LEAVE_ROOM, |
394 MSG_SEND_KICK, |
394 MSG_SEND_KICK, |
395 MSG_SEND_ADD_TEAM, |
395 MSG_SEND_ADD_TEAM, |
396 MSG_SEND_REMOVE_TEAM, |
396 MSG_SEND_REMOVE_TEAM, |
397 MSG_DISCONNECT, |
397 MSG_DISCONNECT, |
398 MSG_SEND_TEAM_COLOR_INDEX, |
398 MSG_SEND_TEAM_COLOR_INDEX, |
399 MSG_SEND_TEAM_HOG_COUNT, |
399 MSG_SEND_TEAM_HOG_COUNT, |
400 MSG_SEND_ENGINE_MESSAGE, |
400 MSG_SEND_ENGINE_MESSAGE, |
401 MSG_SEND_ROUND_FINISHED, |
401 MSG_SEND_ROUND_FINISHED, |
402 MSG_SEND_TOGGLE_READY, |
402 MSG_SEND_TOGGLE_READY, |
403 MSG_SEND_START_GAME, |
403 MSG_SEND_START_GAME, |
404 MSG_SEND_WEAPONSET, |
404 MSG_SEND_WEAPONSET, |
405 MSG_SEND_MAP, |
405 MSG_SEND_MAP, |
406 MSG_SEND_MAP_NAME, |
406 MSG_SEND_MAP_NAME, |
407 MSG_SEND_MAP_GENERATOR, |
407 MSG_SEND_MAP_GENERATOR, |
408 MSG_SEND_MAP_TEMPLATE, |
408 MSG_SEND_MAP_TEMPLATE, |
409 MSG_SEND_MAZE_SIZE, |
409 MSG_SEND_MAZE_SIZE, |
410 MSG_SEND_MAP_SEED, |
410 MSG_SEND_MAP_SEED, |
411 MSG_SEND_MAP_THEME, |
411 MSG_SEND_MAP_THEME, |
412 MSG_SEND_MAP_DRAWDATA, |
412 MSG_SEND_MAP_DRAWDATA, |
413 MSG_SEND_GAMESTYLE, |
413 MSG_SEND_GAMESTYLE, |
414 MSG_SEND_SCHEME; |
414 MSG_SEND_SCHEME; |
415 |
415 |
416 static final List<ThreadedNetConnection.ToNetMsgType> values = Collections.unmodifiableList(Arrays.asList(ToNetMsgType.values())); |
416 static final List<ThreadedNetConnection.ToNetMsgType> values = Collections.unmodifiableList(Arrays.asList(ToNetMsgType.values())); |
417 } |
417 } |
418 |
418 |
419 /** |
419 /** |
420 * Processes messages to the networking system. Runs on a non-main thread. |
420 * Processes messages to the networking system. Runs on a non-main thread. |
421 */ |
421 */ |
422 @SuppressLint("HandlerLeak") |
422 @SuppressLint("HandlerLeak") |
423 public final class ToNetHandler extends Handler { |
423 public final class ToNetHandler extends Handler { |
424 |
424 |
425 public ToNetHandler(Looper looper) { |
425 public ToNetHandler(Looper looper) { |
426 super(looper); |
426 super(looper); |
427 } |
427 } |
428 |
428 |
429 @Override |
429 @Override |
430 public void handleMessage(Message msg) { |
430 public void handleMessage(Message msg) { |
431 switch(ToNetMsgType.values.get(msg.what)) { |
431 switch(ToNetMsgType.values.get(msg.what)) { |
432 case MSG_SEND_NICK: { |
432 case MSG_SEND_NICK: { |
433 FLIB.flib_netconn_send_nick(conn, (String)msg.obj); |
433 FLIB.flib_netconn_send_nick(conn, (String)msg.obj); |
434 break; |
434 break; |
435 } |
435 } |
436 case MSG_SEND_PASSWORD: { |
436 case MSG_SEND_PASSWORD: { |
437 FLIB.flib_netconn_send_password(conn, (String)msg.obj); |
437 FLIB.flib_netconn_send_password(conn, (String)msg.obj); |
438 break; |
438 break; |
439 } |
439 } |
440 case MSG_SEND_QUIT: { |
440 case MSG_SEND_QUIT: { |
441 FLIB.flib_netconn_send_quit(conn, (String)msg.obj); |
441 FLIB.flib_netconn_send_quit(conn, (String)msg.obj); |
442 break; |
442 break; |
443 } |
443 } |
444 case MSG_SEND_ROOMLIST_REQUEST: { |
444 case MSG_SEND_ROOMLIST_REQUEST: { |
445 FLIB.flib_netconn_send_request_roomlist(conn); |
445 FLIB.flib_netconn_send_request_roomlist(conn); |
446 break; |
446 break; |
447 } |
447 } |
448 case MSG_SEND_PLAYER_INFO_REQUEST: { |
448 case MSG_SEND_PLAYER_INFO_REQUEST: { |
449 FLIB.flib_netconn_send_playerInfo(conn, (String)msg.obj); |
449 FLIB.flib_netconn_send_playerInfo(conn, (String)msg.obj); |
450 break; |
450 break; |
451 } |
451 } |
452 case MSG_SEND_CHAT: { |
452 case MSG_SEND_CHAT: { |
453 if(FLIB.flib_netconn_send_chat(conn, (String)msg.obj) == 0) { |
453 if(FLIB.flib_netconn_send_chat(conn, (String)msg.obj) == 0) { |
454 sendFromNet(MSG_CHAT, Pair.create(playerName, (String)msg.obj)); |
454 sendFromNet(MSG_CHAT, Pair.create(playerName, (String)msg.obj)); |
455 } |
455 } |
456 break; |
456 break; |
457 } |
457 } |
458 case MSG_SEND_TEAMCHAT: { |
458 case MSG_SEND_TEAMCHAT: { |
459 FLIB.flib_netconn_send_teamchat(conn, (String)msg.obj); |
459 FLIB.flib_netconn_send_teamchat(conn, (String)msg.obj); |
460 break; |
460 break; |
461 } |
461 } |
462 case MSG_SEND_FOLLOW_PLAYER: { |
462 case MSG_SEND_FOLLOW_PLAYER: { |
463 FLIB.flib_netconn_send_playerFollow(conn, (String)msg.obj); |
463 FLIB.flib_netconn_send_playerFollow(conn, (String)msg.obj); |
464 break; |
464 break; |
465 } |
465 } |
466 case MSG_SEND_JOIN_ROOM: { |
466 case MSG_SEND_JOIN_ROOM: { |
467 FLIB.flib_netconn_send_joinRoom(conn, (String)msg.obj); |
467 FLIB.flib_netconn_send_joinRoom(conn, (String)msg.obj); |
468 break; |
468 break; |
469 } |
469 } |
470 case MSG_SEND_CREATE_ROOM: { |
470 case MSG_SEND_CREATE_ROOM: { |
471 FLIB.flib_netconn_send_createRoom(conn, (String)msg.obj); |
471 FLIB.flib_netconn_send_createRoom(conn, (String)msg.obj); |
472 break; |
472 break; |
473 } |
473 } |
474 case MSG_SEND_LEAVE_ROOM: { |
474 case MSG_SEND_LEAVE_ROOM: { |
475 if(FLIB.flib_netconn_send_leaveRoom(conn, (String)msg.obj) == 0) { |
475 if(FLIB.flib_netconn_send_leaveRoom(conn, (String)msg.obj) == 0) { |
476 sendFromNet(MSG_LEAVE_ROOM, -1, ""); |
476 sendFromNet(MSG_LEAVE_ROOM, -1, ""); |
477 } |
477 } |
478 break; |
478 break; |
479 } |
479 } |
480 case MSG_SEND_KICK: { |
480 case MSG_SEND_KICK: { |
481 FLIB.flib_netconn_send_kick(conn, (String)msg.obj); |
481 FLIB.flib_netconn_send_kick(conn, (String)msg.obj); |
482 break; |
482 break; |
483 } |
483 } |
484 case MSG_SEND_ADD_TEAM: { |
484 case MSG_SEND_ADD_TEAM: { |
485 FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((TeamInGame)msg.obj)); |
485 FLIB.flib_netconn_send_addTeam(conn, TeamPtr.createJavaOwned((TeamInGame)msg.obj)); |
486 break; |
486 break; |
487 } |
487 } |
488 case MSG_SEND_REMOVE_TEAM: { |
488 case MSG_SEND_REMOVE_TEAM: { |
489 if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) { |
489 if(FLIB.flib_netconn_send_removeTeam(conn, (String)msg.obj)==0) { |
490 sendFromNet(MSG_TEAM_DELETED, msg.obj); |
490 sendFromNet(MSG_TEAM_DELETED, msg.obj); |
491 } |
491 } |
492 break; |
492 break; |
493 } |
493 } |
494 case MSG_DISCONNECT: { |
494 case MSG_DISCONNECT: { |
495 FLIB.flib_netconn_send_quit(conn, (String)msg.obj); |
495 FLIB.flib_netconn_send_quit(conn, (String)msg.obj); |
496 shutdown(false, "User quit"); |
496 shutdown(false, "User quit"); |
497 break; |
497 break; |
498 } |
498 } |
499 case MSG_SEND_TEAM_COLOR_INDEX: { |
499 case MSG_SEND_TEAM_COLOR_INDEX: { |
500 FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1); |
500 FLIB.flib_netconn_send_teamColor(conn, (String)msg.obj, msg.arg1); |
501 break; |
501 break; |
502 } |
502 } |
503 case MSG_SEND_TEAM_HOG_COUNT: { |
503 case MSG_SEND_TEAM_HOG_COUNT: { |
504 FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1); |
504 FLIB.flib_netconn_send_teamHogCount(conn, (String)msg.obj, msg.arg1); |
505 break; |
505 break; |
506 } |
506 } |
507 case MSG_SEND_ENGINE_MESSAGE: { |
507 case MSG_SEND_ENGINE_MESSAGE: { |
508 byte[] message = (byte[])msg.obj; |
508 byte[] message = (byte[])msg.obj; |
509 ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); |
509 ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); |
510 FLIB.flib_netconn_send_engineMessage(conn, ptr, NativeSizeT.valueOf(message.length)); |
510 FLIB.flib_netconn_send_engineMessage(conn, ptr, NativeSizeT.valueOf(message.length)); |
511 break; |
511 break; |
512 } |
512 } |
513 case MSG_SEND_ROUND_FINISHED: { |
513 case MSG_SEND_ROUND_FINISHED: { |
514 FLIB.flib_netconn_send_roundfinished(conn, (Boolean)msg.obj); |
514 FLIB.flib_netconn_send_roundfinished(conn, (Boolean)msg.obj); |
515 break; |
515 break; |
516 } |
516 } |
517 case MSG_SEND_TOGGLE_READY: { |
517 case MSG_SEND_TOGGLE_READY: { |
518 FLIB.flib_netconn_send_toggleReady(conn); |
518 FLIB.flib_netconn_send_toggleReady(conn); |
519 break; |
519 break; |
520 } |
520 } |
521 case MSG_SEND_START_GAME: { |
521 case MSG_SEND_START_GAME: { |
522 FLIB.flib_netconn_send_startGame(conn); |
522 FLIB.flib_netconn_send_startGame(conn); |
523 break; |
523 break; |
524 } |
524 } |
525 case MSG_SEND_WEAPONSET: { |
525 case MSG_SEND_WEAPONSET: { |
526 FLIB.flib_netconn_send_weaponset(conn, WeaponsetPtr.createJavaOwned((Weaponset)msg.obj)); |
526 FLIB.flib_netconn_send_weaponset(conn, WeaponsetPtr.createJavaOwned((Weaponset)msg.obj)); |
527 break; |
527 break; |
528 } |
528 } |
529 case MSG_SEND_MAP: { |
529 case MSG_SEND_MAP: { |
530 FLIB.flib_netconn_send_map(conn, MapRecipePtr.createJavaOwned((MapRecipe)msg.obj)); |
530 FLIB.flib_netconn_send_map(conn, MapRecipePtr.createJavaOwned((MapRecipe)msg.obj)); |
531 break; |
531 break; |
532 } |
532 } |
533 case MSG_SEND_MAP_NAME: { |
533 case MSG_SEND_MAP_NAME: { |
534 FLIB.flib_netconn_send_mapName(conn, (String)msg.obj); |
534 FLIB.flib_netconn_send_mapName(conn, (String)msg.obj); |
535 break; |
535 break; |
536 } |
536 } |
537 case MSG_SEND_MAP_GENERATOR: { |
537 case MSG_SEND_MAP_GENERATOR: { |
538 FLIB.flib_netconn_send_mapGen(conn, msg.arg1); |
538 FLIB.flib_netconn_send_mapGen(conn, msg.arg1); |
539 break; |
539 break; |
540 } |
540 } |
541 case MSG_SEND_MAP_TEMPLATE: { |
541 case MSG_SEND_MAP_TEMPLATE: { |
542 FLIB.flib_netconn_send_mapTemplate(conn, msg.arg1); |
542 FLIB.flib_netconn_send_mapTemplate(conn, msg.arg1); |
543 break; |
543 break; |
544 } |
544 } |
545 case MSG_SEND_MAZE_SIZE: { |
545 case MSG_SEND_MAZE_SIZE: { |
546 FLIB.flib_netconn_send_mapMazeSize(conn, msg.arg1); |
546 FLIB.flib_netconn_send_mapMazeSize(conn, msg.arg1); |
547 break; |
547 break; |
548 } |
548 } |
549 case MSG_SEND_MAP_SEED: { |
549 case MSG_SEND_MAP_SEED: { |
550 FLIB.flib_netconn_send_mapSeed(conn, (String) msg.obj); |
550 FLIB.flib_netconn_send_mapSeed(conn, (String) msg.obj); |
551 break; |
551 break; |
552 } |
552 } |
553 case MSG_SEND_MAP_THEME: { |
553 case MSG_SEND_MAP_THEME: { |
554 FLIB.flib_netconn_send_mapTheme(conn, (String) msg.obj); |
554 FLIB.flib_netconn_send_mapTheme(conn, (String) msg.obj); |
555 break; |
555 break; |
556 } |
556 } |
557 case MSG_SEND_MAP_DRAWDATA: { |
557 case MSG_SEND_MAP_DRAWDATA: { |
558 byte[] message = (byte[])msg.obj; |
558 byte[] message = (byte[])msg.obj; |
559 ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); |
559 ByteArrayPtr ptr = ByteArrayPtr.createJavaOwned(message); |
560 FLIB.flib_netconn_send_mapDrawdata(conn, ptr, NativeSizeT.valueOf(message.length)); |
560 FLIB.flib_netconn_send_mapDrawdata(conn, ptr, NativeSizeT.valueOf(message.length)); |
561 break; |
561 break; |
562 } |
562 } |
563 case MSG_SEND_GAMESTYLE: { |
563 case MSG_SEND_GAMESTYLE: { |
564 FLIB.flib_netconn_send_script(conn, (String) msg.obj); |
564 FLIB.flib_netconn_send_script(conn, (String) msg.obj); |
565 break; |
565 break; |
566 } |
566 } |
567 case MSG_SEND_SCHEME: { |
567 case MSG_SEND_SCHEME: { |
568 FLIB.flib_netconn_send_scheme(conn, SchemePtr.createJavaOwned((Scheme) msg.obj)); |
568 FLIB.flib_netconn_send_scheme(conn, SchemePtr.createJavaOwned((Scheme) msg.obj)); |
569 break; |
569 break; |
570 } |
570 } |
571 default: { |
571 default: { |
572 Log.e("ToNetHandler", "Unknown message type: "+msg.what); |
572 Log.e("ToNetHandler", "Unknown message type: "+msg.what); |
573 break; |
573 break; |
574 } |
574 } |
575 } |
575 } |
576 } |
576 } |
577 } |
577 } |
578 } |
578 } |