Package net.sphene.goim.rcp.extensionpoints

Source Code of net.sphene.goim.rcp.extensionpoints.GameAdapter$GameStatusExtension

/*
* Gamers Own Instant Messenger
* Copyright (C) 2005-2006 Herbert Poul (kahless@sphene.net)
* http://goim.sphene.net
*
* 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 net.sphene.goim.rcp.extensionpoints;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;

import net.sphene.goim.rcp.GOIMPlugin;
import net.sphene.goim.rcp.beans.GOIMGameItem;
import net.sphene.goim.rcp.beans.GOIMGameList;
import net.sphene.goim.rcp.beans.GameStatusChangeEvent;
import net.sphene.goim.rcp.beans.GOIMGameItem.GOIMGameExecuteCommands;
import net.sphene.goim.rcp.extensionpoints.GameExtensionPoint.GameExtensionProxy;
import net.sphene.goim.rcp.extensionpoints.game.IGameDestination;
import net.sphene.goim.rcp.preferences.PreferenceConstants;
import net.sphene.libs.SpheneStringUtil;

public class GameAdapter implements IGame {
  protected InetSocketAddress getCurrentDestination(GOIMGameItem game) {
    return (InetSocketAddress)game.getSessionData(IGame.GAMEITEM_SESSION_CURRENT_DESTINATION);
  }
  protected void setCurrentDestination(GOIMGameItem game, InetSocketAddress destination) {
    game.setSessionData(IGame.GAMEITEM_SESSION_CURRENT_DESTINATION,destination);
  }

 
  protected void setCurrentSourcePort(GOIMGameItem game, int sourcePort) {
    game.setSessionData(IGame.GAMEITEM_SESSION_CURRENT_SOURCEPORT,sourcePort);
  }
  protected int getCurrentSourcePort(GOIMGameItem game) {
    Integer sourcePort = (Integer)game.getSessionData(IGame.GAMEITEM_SESSION_CURRENT_SOURCEPORT);
    if(sourcePort == null) return -1;
    return sourcePort.intValue();
  }
 
  protected void setNextDestination(GOIMGameItem game, InetSocketAddress destination) {
    game.setSessionData(IGame.GAMEITEM_SESSION_NEXT_DESTINATION,destination);
  }
  protected InetSocketAddress getNextDestination(GOIMGameItem game) {
    return (InetSocketAddress)game.getSessionData(IGame.GAMEITEM_SESSION_NEXT_DESTINATION);
  }
 
  protected void setPacketCount(GOIMGameItem game, int packetCount) {
    game.setSessionData(IGame.GAMEITEM_SESSION_PACKET_COUNT,packetCount);
  }
  protected int getPacketCount(GOIMGameItem game) {
    Integer packetCount = (Integer)game.getSessionData(IGame.GAMEITEM_SESSION_PACKET_COUNT);
    if(packetCount == null) return 0;
    return packetCount.intValue();
  }
 
 
 
 
  public void closedUdpPort(GOIMGameItem game, int port) {
    if(getCurrentDestination(game) != null && getCurrentSourcePort(game) == port) {
      System.out.printf("Closed connection (%s) to %s\n",game.retrieveExtensionProxy().name,getCurrentDestination(game).toString());
      setCurrentDestination(game,null);
      setNextDestination(game,null);
      setPacketCount(game,0);
      leftServer();
    }
  }
 
 
 
  /**
   * This method can be overloaded to return e.g. 2 when destination.getPort() is the default port of the game,
   * and 100 when it is a known port for e.g. punkbuster update or soemthing. This way we need x packets in a row to signal a server join.
   * @param game
   * @param destination
   * @param sourceport
   * @return
   */
  public int requiredPacketCountForDestination(GOIMGameItem game, InetSocketAddress destination, int sourceport) {
    return 2;
  }
  public void sniffedPacketFromGame(GOIMGameItem game, InetSocketAddress destination, int sourceport) {
    // We ignore all broadcasts ...
    byte[] address = destination.getAddress().getAddress();
    if(address[0] == (byte)255 &&
        address[1] == (byte)255 &&
        address[2] == (byte)255 &&
        address[3] == (byte)255)
      return;

    // When we receive the 3rd packet to the same destination on the same source port we fire the connect event..
    InetSocketAddress nextDestination = getNextDestination(game);
    if(getPacketCount(game) == requiredPacketCountForDestination(game,destination,sourceport)) {
      System.out.println("enough packets ... ");
      if(nextDestination != null && nextDestination.equals(destination)) {
        System.out.printf("I got a connection from %s to %s (source port: %d)\n",game.retrieveExtensionProxy().name,destination.toString(),sourceport);
        setCurrentDestination(game,nextDestination);
        setCurrentSourcePort(game,sourceport);
        setNextDestination(game,null);
        joinedServer(game);
      } else {
        setPacketCount(game,0);
        setCurrentDestination(game,null);
      }
    }
    //System.out.println("nextDestination: " + nextDestination.toString());
    if(nextDestination != null && nextDestination.equals(destination)) {
      setPacketCount(game,getPacketCount(game)+1);
      //System.out.printf("Connected packet to %s (source port: %d)\n",destination.toString(),sourceport);
    } else {
      if(getCurrentDestination(game) != null && getCurrentDestination(game).equals(destination)) {
        setNextDestination(game,null);
        setPacketCount(game, 0);
      } else {
        setPacketCount(game, 1);
        setNextDestination(game,destination);
      }
    }
  }
 
  /**
   * This method gets called by sniffedPacketFromGame if the user just joined a
   * (new) server. The default implementation just fires the event.
   *
   * (subclasses should always call this implementation if they overload)
   * @param game the GameItem of the joined server.
   *
   */
  protected void joinedServer(GOIMGameItem game) {
    GOIMPlugin.gameStatusChanged.fireEvent(new GameStatusChangeEvent(this,GameStatusChangeEvent.TYPE_JOINED_GAME));
  }
 
  /**
   * This method gets called by closedUdpPort(GOIMGameItem,int) if it detects that
   * the local UDP port was closed used for this game. (ie. When the game server was
   * left)
   *
   * Subclass should always call this super method when overloading, because it sends
   * the game server left event.
   *
   */
  protected void leftServer() {
    GOIMPlugin.gameStatusChanged.fireEvent(new GameStatusChangeEvent(this,GameStatusChangeEvent.TYPE_LEFT_GAME));
  }

  //public void initWithConfig(GOIMGameItem item) {
  //  this.game = item;
  //}

  public IGameExtension getStatusPacket(GOIMGameItem game) {
    if(getCurrentDestination(game) == null) return null;
    return new GameStatusExtension(getCurrentDestination(game),game.retrieveExtensionProxy(),game, null);
  }
  public String getStatusString(GOIMGameItem game) {
    if(getCurrentDestination(game) == null) return null;
    return String.format("%s (@ %s:%d)",game.retrieveExtensionProxy().name,getCurrentDestination(game).getAddress().getHostAddress(),getCurrentDestination(game).getPort());
    //return null;
  }

  public static class GameStatusExtension implements IGame.IGameExtension,PacketExtension {
    public static final String ELEMENT_NAME = "x";
    public static final String NAMESPACE = "http://goim.sphene.net/gameStatus";
    //public static final MessageFormat targetMessageFormat = new MessageFormat("{0,number,integer}.{1,number,integer}.{2,number,integer}.{3,number,integer}:{4,number,integer}");
    public static InetSocketAddress parseSocketAddress(String text) {
      try {
//        Object[] obj = targetMessageFormat.parse(text);
//        return new InetSocketAddress(InetAddress.getByAddress(new byte[]{((Integer)obj[0]).byteValue(),
//            ((Integer)obj[1]).byteValue(),
//            ((Integer)obj[2]).byteValue(),
//            ((Integer)obj[3]).byteValue()}),
//            ((Integer)obj[0]).intValue());
        StringTokenizer st = new StringTokenizer(text,".:");
        byte[] ip = new byte[4];
        int port = 0;
        for(int i = 0 ; st.hasMoreElements() ; i ++) {
          String token = st.nextToken();
          int val = Integer.parseInt(token);
          if(i < 4) ip[i] = (byte) val;
          else port = val;
        }
        return new InetSocketAddress(InetAddress.getByAddress(ip),port);
      } catch (Exception e) {
        e.printStackTrace();
      }
      return null;
    }
    public static String formatSocketAddressIP(InetAddress address) {
      byte[] ip = address.getAddress();
      return new StringBuffer().append(ip[0]&0xff).append('.').append(ip[1]&0xff).append('.').append(ip[2]&0xff).append('.').append(ip[3]&0xff).toString();
    }
    public static String formatSocketAddress(InetSocketAddress addr) {
      //return targetMessageFormat.format(new Object[] {(int)ip[0],(int)ip[1],(int)ip[2],(int)ip[3],addr.getPort()});
      return formatSocketAddressIP(addr.getAddress()) + ':' + addr.getPort();
    }
    InetSocketAddress target;
    GOIMGameItem game;
    private GameExtensionProxy proxy;
    private Map<String, String> atts;
    String gameId;
    public GameStatusExtension(InetSocketAddress target, GameExtensionProxy proxy, GOIMGameItem game, Map<String, String> atts, String gameId) {
      this.gameId = gameId;
      this.target = target;
      this.game = game;
      this.proxy = proxy;
      this.atts = atts;
    }
    public GameStatusExtension(InetSocketAddress target, GameExtensionProxy proxy, GOIMGameItem game, Map<String, String> atts) {
      this(target,proxy,game,atts,(game == null || game.retrieveExtensionProxy() == null ? null : game.retrieveExtensionProxy().id));
    }
    public Map<String,String> getAdditionalAttributes() { return atts; }
    public String setAdditionalAttribute(String key, String value) {
      if(atts == null)
        atts = new HashMap<String,String>();
      return atts.put(key,value);
    }
    public String getElementName() {
      return ELEMENT_NAME;
    }
    public String getNamespace() {
      return NAMESPACE;
    }
    public String toXML() {
      StringBuffer additionalXMLAttributes = new StringBuffer("");
      if(atts != null)
        for(String key : atts.keySet()) {
          additionalXMLAttributes.append(' ').append(key).append("=\"").append(SpheneStringUtil.escapeXMLElementEntities(atts.get(key))).append("\"");
        }
      return String.format("<%s xmlns=\"%s\" game=\"%s\" target=\"%s\"%s></%s>",
          getElementName(),getNamespace(),gameId,
          formatSocketAddress(target),additionalXMLAttributes.toString(),getElementName());
    }
    public static class Provider implements PacketExtensionProvider {
      public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
        InetSocketAddress addr = parseSocketAddress(parser.getAttributeValue("","target"));
        GOIMGameList list = GOIMPlugin.getPreferenceObject(GOIMGameList.class);
        String gameId = parser.getAttributeValue("","game");
        int attributes = parser.getAttributeCount();
        Map<String,String> atts = new HashMap<String,String>();
        for(int i = 0 ; i < attributes ; i++) {
          String name = parser.getAttributeName(i);
          if(name.equals("xmlns") || name.equals("game") || name.equals("target"))
            continue;
          atts.put(parser.getAttributeName(i),parser.getAttributeValue(i));
        }
        if(atts.size() < 1) atts = null;
        GameExtensionProxy proxy = GameExtensionPoint.getGameExtension(gameId);
        GOIMGameItem game = null;
        for(GOIMGameItem item : list) {
          if(item.gameId.equals(gameId)) {
            game = item;
            break;
          }
        }
        if(proxy == null || addr == null) return null;
        return new GameStatusExtension(addr,proxy,game,atts,gameId);
      }
     
    }
    public GOIMGameItem getGameItem() {
      return game;
    }
    public GameExtensionProxy getGameExtension() {
      return proxy;
    }
    public InetSocketAddress getDestination() {
      return target;
    }
  }

  /**
   * Returns the command used to launch the game and connect to a specified server.
   * @param game
   * @return
   * @see #getExecuteParameters(GOIMGameItem, IGameDestination)
   */
  public List<GOIMGameExecuteCommands> getConnectCommands(GOIMGameItem game) {
    List<GOIMGameExecuteCommands> commands = new ArrayList<GOIMGameExecuteCommands>();
    GOIMGameExecuteCommands cmd;
   
    cmd = getExecuteCommandBefore();
    if(cmd != null) commands.add(cmd);
    if(game.customizedExecute && game.executeCommands != null && game.executeCommands.size() > 0) {
      for(GOIMGameExecuteCommands command : game.executeCommands) {
        if(command.commandType == GOIMGameExecuteCommands.ExecuteCommandType.CONNECT ||
            command.commandType == GOIMGameExecuteCommands.ExecuteCommandType.BOTH) {
          commands.add(command);
        }
      }
    } else {
      String command = getConnectCommand(game);
      commands.add(stringCommandToObject(command));
    }
    cmd = getExecuteCommandAfter();
    if(cmd != null) commands.add(cmd);

    return commands;
  }
  public String getConnectCommand(GOIMGameItem game) {
    return game.retrieveExtensionProxy().getDefaultConnectCommand();
  }
 
  /**
   * Returns the Execute Command before a game is launched. (from the preference store)
   * @return a GOIMGameExecuteCommands representing the command.
   */
  private GOIMGameExecuteCommands getExecuteCommandBefore() {
    String cmd = GOIMPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.P_GAME_EXECUTE_COMMAND_BEFORE);
    return stringCommandToObject(cmd);
  }
  /**
   * Returns the Execute Command after a game is launched. (from the preference store)
   * @return a GOIMGameExecuteCommands representing the command.
   */
  private GOIMGameExecuteCommands getExecuteCommandAfter() {
    String cmd = GOIMPlugin.getDefault().getPreferenceStore().getString(PreferenceConstants.P_GAME_EXECUTE_COMMAND_AFTER);
    return stringCommandToObject(cmd);
  }
  private GOIMGameExecuteCommands stringCommandToObject(String cmd) {
    if("".equals(cmd.trim())) return null;
    return new GOIMGameExecuteCommands(cmd,true,GOIMGameExecuteCommands.ExecuteCommandType.BOTH);
  }
  /**
   * Returns the command used to launch the game.
   * @param game
   * @return
   * @see #getExecuteParameters(GOIMGameItem, IGameDestination)
   */
  public List<GOIMGameExecuteCommands> getLaunchCommands(GOIMGameItem game) {
    List<GOIMGameExecuteCommands> commands = new ArrayList<GOIMGameExecuteCommands>();
    GOIMGameExecuteCommands cmd;
   
    cmd = getExecuteCommandBefore();
    if(cmd != null) commands.add(cmd);
    if(game.customizedExecute && game.executeCommands != null && game.executeCommands.size() > 0) {
      for(GOIMGameExecuteCommands command : game.executeCommands) {
        if(command.commandType == GOIMGameExecuteCommands.ExecuteCommandType.LAUNCH ||
            command.commandType == GOIMGameExecuteCommands.ExecuteCommandType.BOTH) {
          commands.add(command);
        }
      }
    } else {
      String command;
      command = game.retrieveExtensionProxy().launchcommand;
      if(command == null) {
        command = game.retrieveExtensionProxy().params.get("launchcommand");
      }
      if(command == null) {
        command = "{gamepath}";
      }
      commands.add(stringCommandToObject(command));
    }
    cmd = getExecuteCommandAfter();
    if(cmd != null) commands.add(cmd);
   
    return commands;
  }

  /**
   * Returns parameters which can be used in launchcommand and connectcommand.
   * Subclasses may overwrite this method to provide custom parameters.
   * By default adds: serverip, serverport and gamepath
   *
   * so you can use e.g.: {gamepath} +connect {serverip}:{serverport}
   * @param game
   * @param gameDestination
   * @return
   */
  public Map<String,String> getExecuteParameters(GOIMGameItem game, IGameDestination gameDestination) {
    Map<String,String> params = new HashMap<String,String>();
    InetSocketAddress destination = null;
    if(gameDestination != null) destination = gameDestination.getDestination();
    params.put("gamename",game.retrieveExtensionProxy().name);
    params.put("gameid",game.retrieveExtensionProxy().id);
    if(destination != null) {
      params.put("serveraddress",GameStatusExtension.formatSocketAddress(destination));
      params.put("serverip",GameStatusExtension.formatSocketAddressIP(destination.getAddress()));
      params.put("serverport",Integer.toString(destination.getPort()));
    }
    params.put("gamepath",game.path);
    return params;
  }
 
  /**
   * Executes the specified game.
   */
  public void execute(GOIMGameItem game, IGameDestination gameDestination) {
    InetSocketAddress destination = null;
    if(gameDestination != null) destination = gameDestination.getDestination();
    List<GOIMGameExecuteCommands> commands = null;
    Map<String,String> params = getExecuteParameters(game, gameDestination);
    if(destination == null) {
      commands = getLaunchCommands(game);
    } else {
      commands = getConnectCommands(game);
    }
    if(commands != null) {
      new Thread(new GameLauncher(commands,params,game)).start();
    }
  }
  public boolean needsOnlineStatusChange(GOIMGameItem item) {
    return getCurrentDestination(item) != null && item.retrieveExtensionProxy().changestatus;
  }
  public String getTooltipText(GOIMGameItem game, IGameExtension gameEx) {
    GameExtensionProxy proxy = gameEx.getGameExtension();
    return proxy.name + ": " + GameStatusExtension.formatSocketAddress(gameEx.getDestination());
  }
  public void init(GameExtensionProxy proxy) {
  }
 
  public static class GameLauncher implements Runnable {
    private List<GOIMGameExecuteCommands> commands;
    private Map<String, String> params;
    private GOIMGameItem game;
    public GameLauncher(List<GOIMGameExecuteCommands> commands, Map<String,String> params, GOIMGameItem game) {
      this.commands = commands;
      this.params = params;
      this.game = game;
    }
    public void run() {
      for(GOIMGameExecuteCommands cmd : commands) {
        String command = cmd.command;
        for(String param : params.keySet()) {
          command.replace("{" + param + "}",params.get(param));
        }
        try {
          Process process = Runtime.getRuntime().exec(command,null,new File(game.path).getParentFile());
          if(cmd.waitforterminate) {
            process.waitFor();
          }
        } catch (IOException e) {
          e.printStackTrace();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
TOP

Related Classes of net.sphene.goim.rcp.extensionpoints.GameAdapter$GameStatusExtension

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.