📄 community.java
字号:
* thread from the one that sends the gameStart command, * since gameStart itself blocks for up to 30 or so seconds * (depending on SNAP Server defaults.) * <p> * gameStartCancel() is the only SNAP command that may be * sent out in parallel to any other SNAP commands [with * the exception of the retrieveAllEvents() command, which * is typically called behind the scenes by the SNAP * EventListener thread inside ServerComm.] If any other * SNAP commands are executed in parallel in this fashion, * they will result in a "755 CommandInProgress" error. * * @param cmd ItemList containing command parameters * (primarily, the command listener.) */ protected boolean handleGameStartCancel( ItemList cmd) { if ("gameStartCancel".equals(cmd.getString("cmd"))) { AsyncCommandListener listener = (AsyncCommandListener)cmd.getItem("listener"); Thread gscThread = new Thread() { public void run() { comm.gameStartCancel();// System.out.println("Canceled game start!"); } }; gscThread.start(); waitingForGame = false; return true; } return false; } /** * Cancels "non-critical" game commands by removing them from the * outgoing SNAP command queue. Non-critical commands are player * position updates and heartbeat notifications. This method is * called when a game state transition message must go out (e.g., * if a player has reached the end of the maze) -- typically it's * better to let this command supercede all queued up movement * commands and get out to the opponent immediately. */ public synchronized void cancelNonCriticalCmds() { ItemList il; for (int i=0; i<cmdList.size(); i++) { il = (ItemList)cmdList.elementAt(i); if (il.getString(NON_CRITICAL) != null) { cmdList.removeElementAt(i--); } } } /** * SnapEventListener callback. All SNAP Mobile server errors are * received here, both synchronous and asynchronous errors. * This method saves server errors, to be checked for later in the * main event loop that submits commands. Some Views handle their * own errors (via commandCompleted() implementations), but unhandled * errors eventually get displayed in generic error dialogs by * Community (in the run() method). * <p> * Note: only errors of type SEVERITY_NON_FATAL are handled by * individual Views. All other severity levels are handled * generically, in this method. * * @param error Error number to process * @param msg Error Message * @param severity Severity of the Error Message */ public void processServerError(int error, String msg, int severity) {// System.out.println("Community.processServerError(), error = " + error + ", msg = " + msg + ", severity = " + severity); synchronized (this) { lastError = msg + " " + error; lastErrorSeverity = severity; } //---------------------------------------------------------------- // Fatal error -- SessionIDs already invalidated on server. // User must go back to main menu and re-log in. if (severity == SEVERITY_FATAL) { System.out.println("call showError() from processServerError() FATAL"); setLoginInfo( null, null, null, null); if (mazeRacer.isPlaying()) mazeRacer.gameOver(false); synchronized (this) { cmdList.removeAllElements(); } showError( msg, Community.WELCOME, Dialog.ALERT_FATAL); } //---------------------------------------------------------------- // Requires log out error. App must send a logout command as // soon as possible go back to the main menu, and re-log in. else if (severity == SEVERITY_REQUIRES_LOGOUT) { System.out.println("call showError() from processServerError() REQUIRES_LOGOUT"); if (mazeRacer.isPlaying()) mazeRacer.gameOver(false); synchronized (this) { cmdList.removeAllElements(); } if (error == 901) { if (msg==null) msg = "You may be logged in twice! (901)"; } if (isLoggedIn()) { showError( msg, Community.REALLY_LOGOUT, Dialog.ALERT_LOGOUT); } else { showError( msg, Community.WELCOME, Dialog.ALERT); } } //---------------------------------------------------------------- // Transport error. Last request assumed to fail to complete its // round-trip to the server, and should be safe to attempt again. // Session state on server stays valid, this is strictly a client- // side or network error. else if (severity == SEVERITY_TRANSPORT) { System.out.println("call showError() from processServerError() TRANSPORT"); showError( msg + " - A connection error may have occurred. " + "Please check your signal strength. "); } //---------------------------------------------------------------- // Warning from underlying ServerComm networking code that there // may be some slowdown in network performance. Network signal // may have been lost, or may soon. No action required, but can // be smart to warn users to make sure they are in a full-signal // area before continuing. else if (severity == SEVERITY_TRANSPORT_WARNING) { // ALL listener thread errors get reported as SEVERITY_TRANSPORT_WARNING System.out.println("call showError() from processServerError() TRANSPORT_WARNING"); if (!getView().getName().equals("Network Warning")) { showDialog("Network Warning", "" + msg + "(" + error + ") - Network currently is slow " + "or not responding", null, Community.BACK, Dialog.ALERT); } } //---------------------------------------------------------------- // Error code specific to the last command sent, but a valid error // condition that has no effect on the user's server session. // Some nonfatal errors are handled in context-dependent ways by // individual Views, some are displayed in a "generic" dialog by // Community. else if (severity == SEVERITY_NON_FATAL) { // System.out.println("call showError() from processServerError() NON_FATAL: " + lastError); // Give the current View (if it implements AsyncCommandListener, // and is registered as the listener for the current command) the // opportunity to show its own error-code-specific error screen in // the case of nonfatal errors. // If there is no listener, or if the listener does not handle the // error, then Community will pop up a generic error dialog in its // run() method where commands are dispatched to the SNAP servers. if (asyncListener != null) { asyncListener.commandCompleted( asyncCommand, lastError, severity, new ItemList()); } } } /** * SnapEventListener callback. Handles all incoming asynchronous * events and messages from the SNAP Mobile servers, and deals * with them or delegates them to various parts of the app as * necessary. * * @param list Vector of ItemLists, each element is a separate * SNAP message, event, or callback. */ public void processEvents(Vector list) { ItemList il; String from, msg, gameRoom; byte[] data; String event = ""; //System.out.println("Community.processEvents()"); try { for (int i=0; i<list.size(); i++) { //System.out.println(" " + i); il = (ItemList)list.elementAt(i); switch(il.getInteger("id")) { // Buddy messages case ItemList.IMPS_IM_MESSAGE: //System.out.println("got imps message"); from = clipName(il.getString("fromName")); msg = il.getString("message"); // Challenge requests are just specially formatted // buddy messages. if (msg.startsWith(CHALLENGE_PREFIX)) { gameRoom = msg.substring(CHALLENGE_PREFIX.length()); //System.out.println("got challenge message, game room is " + gameRoom); showDialog( "Challenge", "Player '" + from + "' is challenging you to a game. Accept?", gameRoom, null, Dialog.YES_NO ); } else { View view = findView(CHAT); if (view instanceof Chat) { Chat chat = (Chat)view; chat.addBuddyMessage(from, msg); } else { buddyList.addChat(from, msg); } } break; // Presence updates for friends (online/offline, availability) case ItemList.IMPS_IM_PRESENCE: handlePresenceUpdate( il); break; // Incoming request to be friends (from someone who // is not already a friend.) case ItemList.IMPS_BUDDY_REQ: from = clipName(il.getString("fromUserName")); msg = il.getString("message"); showDialog("Friend Request", "From " + from + ". Accept?", from, null, Dialog.YES_NO); break; // Previous friend request of ours was either accepted // or rejected case ItemList.IMPS_BUDDY_ACC_REJ: int accepted = il.getInteger("accepted"); from = clipName(il.getString("fromUserName")); if (accepted != 0) buddyList.add(new Buddy(from, Buddy.ONLINE_AVAILABLE)); showDialog( "Note", "'" + from + "' " + (accepted != 0 ? "accepted" : "rejected") + " buddy request.", null, null, Dialog.ALERT); break; // We've been removed from one of our friends' // friends list. case ItemList.IMPS_BUDDY_REVOKED: from = clipName(il.getString("fromUserName")); showDialog("Note", "'" + from + "' is no longer your buddy.", null, null, Dialog.ALERT); buddyList.remove(from); break; // Incoming game packet from our opponent in the // MazeRacer game. case ItemList.GAME_PACKET: from = clipName(il.getString("from")); //System.out.println(" received game packet from " + from); data = il.getByteArray("gameData"); mazeRacer.gameDataReceived(from, data); break; } } } catch (Exception e) { System.out.println("Exception in Community.handleEvents()!"); e.printStackTrace(); } } /** * Called when ServerComm completes a call for which we were a listener. * (either successfully, or with errors from the servers.) * * @param cmd Name of command ("extendedLogin", etc.) * @param errorMessage Error String returned by servers in case of error * @param results ItemList containing results of successful commands. */ public boolean commandCompleted(String cmd, String errorMessage, int errorSeverity, ItemList results) {// System.out.println("Community.commandCompleted(): " + cmd); removeView(PENDING_GAMESTART); // If command was succesful: if (errorMessage == null) { // If we just logged in, set our various SNAP session IDs, // and our buddy list. if (cmd.equals("extendedLogin")) { System.out.println("ItemList.toString(): {\n"+results.toString()+"}"); setLoginInfo( results); setMOTD( results); buddyList.set( results.getList("buddyList")); if(results.getList("messageList")!=null && results.getList("messageList").size()>0) { switchToView( Community.MOTD); } else { switchToView( Community.HOME); } return true; } // If we started a game successfully, switch to game view. else if (cmd.equals("gameStart") || cmd.equals("randomStart")) { mazeRacer.setOpponent( getOpponentName( results)); startGame( false); return true; } // Logout. else if (cmd.equals("unifiedLogout")) { setLoginInfo( null, null, null, null); switchToView( Community.WELCOME); return true; } } else { if (cmd.equals("randomStart")) { if (errorMessage.equals("CmdTimeout 762") && waitingForGame) { showError("No players were available " + "Please try again." ); return true; } if (!waitingForGame) return true; } else if (cmd.equals("gameStart")) { if (errorMessage.equals("CmdTimeout 762") && waitingForGame) { showError("Sorry, the player didn't respond to your " + "challenge in time. Please try again!" ); return true; } if (!waitingForGame) return true; } else if (cmd.equals("requestBuddy")) { if (errorMessage.equals("Not Found 914")) { showError("Sorry, couldn't find a user by that name. " + "Please try another name!" ); return true; } } } return false; } /** * Main event loop for sending SNAP commands to server. * Handles sending commands, catching error results, and notifying * Views of the success/failure of their requests. */ public void run() { AsyncCommandListener listener; ItemList itemList, returnValues; String error, cmd; try { //----------------------------------- // run main loop while (!done) { //------------------------------- // Wait for next request synchronized (this) { while (cmdList.isEmpty()) { try {wait();} catch (InterruptedException e) {} } synchronized (cmdList) { itemList = (ItemList)cmdList.elementAt(0); cmdList.removeElementAt(0); } } cmd = itemList.getString("cmd"); returnValues = null; lastError = null; lastErrorSeverity = -1; System.out.println("Community.run(), cmd = " + cmd); // Login and CreateUser are special, in that they are // guaranteed to be first SNAP commands attempted in the // CommUI app. Therefore, if there are network-related // errors or exceptions, we display extra-informational // error dialogs suggesting users check their permissions // and GPRS/phone account service settings & plans. if (cmd.equals("extendedLogin") || cmd.equals("createUser")) { try { if (cmd.equals("extendedLogin")) { returnValues = comm.extendedLogin( itemList.getString("user"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -