//Terry 2001/09/27
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "char.h"
#include "object.h"
#include "char_base.h"
#include "npcutil.h"
#include "lssproto_serv.h"
#include "npc_stoneserviceman.h"
#include "readmap.h"
#include "battle.h"
#include "log.h"
#include "enemy.h"
#include "configfile.h"

#ifdef _SERVICE
#define LOOP_TIME 100		//0.1秒(进入loop function 的时间)
#define MAX_AP_MSG 128		// 接收AP送来讯息的最大数

// socket struct
struct socketaddr_in
{
  u_short sin_family;
  u_short sin_port;
  u_long  sin_addr;
  char    sin_zero[8];
};

// 接收AP传来的讯息
typedef struct _MSG
{
  int nAid;		// nAid => 流水号*10 + 讯息代号(_AP_CLIENT_MESSAGE)
  int nIndex;		// NPC的index值
  int nLen;		// 讯息长度
  LPList Data;		// 实际资料
  int bIsUse;		// 这个讯息是否有使用过
}Msg,*pMsg;
Msg g_APMsg[MAX_AP_MSG];
        
// 动作id        
enum _AP_CLIENT_MESSAGE
{
  Cli_CHECKPLAYER,  //要求AP对玩家是否有购买产品的确认  0
  AP_CHECKPLAYER,   //AP回应玩家是否有购买产品
  Cli_YES,          //玩家确定要将奖品拿走
  Cli_CANCEL,	    //通知AP把lock栏位清为0             
  Cli_GET,	    //通知AP给物品
  AP_GET,	    //AP回应物品			5
  Cli_CONNECT,      //测试是否有连到AP
  AP_CONNECT,       //AP回应
  AP_ERROR          //AP有错误				
};

// NPC的工作变数
enum
{
  NPC_WORK_FLAG1   	 = CHAR_NPCWORKINT2,	//flag1
  NPC_WORK_FLAG2   	 = CHAR_NPCWORKINT3,	//flag2
  NPC_WORK_FLAG3   	 = CHAR_NPCWORKINT4,	//flag3
  NPC_WORK_TIMEOUT 	 = CHAR_NPCWORKINT5,	//time out 时间
  NPC_WORK_STATE   	 = CHAR_NPCWORKINT6,	//目前执行状态
  NPC_WORK_START   	 = CHAR_NPCWORKINT7,	//开始计时flag
  NPC_WORK_LEAVE_COUNT   = CHAR_NPCWORKINT8,	//玩家talk时间计时
  NPC_WORK_TOINDEX 	 = CHAR_NPCWORKINT9,	//玩家的index值
  NPC_WORK_SERIALNUM     = CHAR_NPCWORKINT10,   //流水号
  NPC_WORK_ISUSE   	 = CHAR_NPCWORKINT11,	//目前NPC是否有玩家在使用
};

// 执行的状态
enum
{
  SERVICE_STATE_1,	// check 有没有和AP连线中 
  SERVICE_STATE_2,	// 向AP取得玩家有无买产品
  SERVICE_STATE_3,	// 取得要给玩家的东西的资料
  SERVICE_STATE_4	// end state
};
                                                                
extern int errno;

int g_nServiceSocket;
int g_EnableService = 0;
char g_ApID[32];
struct socketaddr_in server_sin;
struct sockaddr      temp;
unsigned short g_Port;

static void NPC_StoneServiceMan_selectWindow(int meindex,int toindex,int num,int select);
extern int GetSerialNum(void);
static int flag = 1;

/*********************************
* 初始化
*********************************/
BOOL NPC_StoneServiceManInit(int meindex )
{
  char npcarg[NPC_UTIL_GETARGSTR_BUFSIZE];
  
  if(NPC_Util_GetArgStr(meindex,npcarg,sizeof(npcarg)) == NULL){
    print("StoneServiceMan:GetArgStrErr");
    return FALSE;
  }

  CHAR_setInt(meindex,CHAR_LOOPINTERVAL,LOOP_TIME);
  CHAR_setInt(meindex,CHAR_WHICHTYPE,CHAR_TYPESTONESERVICEMAN);
  CHAR_setWorkInt(meindex,NPC_WORK_FLAG1,1);
  CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,1);
  CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,1);
  CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
  CHAR_setWorkInt(meindex,NPC_WORK_STATE,SERVICE_STATE_2);
  CHAR_setWorkInt(meindex,NPC_WORK_START,0);  
  CHAR_setWorkInt(meindex,NPC_WORK_TOINDEX,-1);
  CHAR_setWorkInt(meindex,NPC_WORK_ISUSE,0);
  CHAR_setWorkInt(meindex,NPC_WORK_LEAVE_COUNT,0);
  CHAR_setWorkInt(meindex,NPC_WORK_SERIALNUM,-1);

  g_EnableService = getEnableService();
  
  //连线到AP在init时只做一次
  if(flag && g_EnableService){
    strcpy(g_ApID,getApID());
		g_Port = getApPort();
    bzero(g_APMsg,sizeof(g_APMsg));
    ConnectToAP();//连线到AP
    flag = 0;
  }
  
  return TRUE;
}

void NPC_StoneServiceManTalked(int meindex,int talkerindex,char *szMes,int color)
{
  if(CHAR_getInt(talkerindex,CHAR_WHICHTYPE) != CHAR_TYPEPLAYER) return;
  if(NPC_Util_isFaceToFace(talkerindex,meindex,1) == FALSE) return;
  NPC_StoneServiceMan_selectWindow(meindex,talkerindex,0,-1);
}

static void NPC_StoneServiceMan_selectWindow(int meindex,int toindex,int num,int select)
{
  char npcarg[NPC_UTIL_GETARGSTR_BUFSIZE];
  char token[1024],buf[128],*pUserid;
  int buttontype = 0, windowtype = 0, windowno = 0,nAid,nLen;
  int fd = getfdFromCharaIndex(toindex);
  char Data[3][32],talk[128];
  int i,j,k,Ret;
  LPList DataList = NULL,Kill = NULL;

	
  if(fd == -1) 
  {
    print("getfd err\n");
    return;
  }
	
  if(NPC_Util_GetArgStr(meindex,npcarg,sizeof(npcarg)) == NULL)
  {
    print("GetArgStrErr");
    return ;
  }
  
  token[0] = '\0';

  //如果不使用石器服务员的功能
  if(!g_EnableService)
  {
    sprintf(token,"\n 请到此星系的最後一颗星球使用此服务，谢谢！");
    buttontype = WINDOW_BUTTONTYPE_OK;
    windowtype = WINDOW_MESSAGETYPE_MESSAGE;
    windowno = CHAR_WINDOWTYPE_SERVICE_WAIT;
    
    lssproto_WN_send(fd,windowtype,buttontype,windowno,
                     CHAR_getWorkInt(meindex,CHAR_WORKOBJINDEX),
		     token);    
    return;
  }
  
  //如果这个玩家是第一个和NPC讲话
  if(CHAR_getWorkInt(meindex,NPC_WORK_ISUSE) == 0 && 
     CHAR_getWorkInt(meindex,NPC_WORK_TOINDEX) == -1)
  {
    //记住第一个和NPC讲话的是谁
    CHAR_setWorkInt(meindex,NPC_WORK_TOINDEX,toindex);
    //设定为NPC正在使用中
    CHAR_setWorkInt(meindex,NPC_WORK_ISUSE,1);
  }
  //如果是第二个以後和NPC讲话的人
  else if(CHAR_getWorkInt(meindex,NPC_WORK_ISUSE) == 1 &&
          CHAR_getWorkInt(meindex,NPC_WORK_TOINDEX) != toindex)
  {
    sprintf(token,"\n 正在服务其他玩家中，请稍等...");
    buttontype = WINDOW_BUTTONTYPE_OK;
    windowtype = WINDOW_MESSAGETYPE_MESSAGE;
    windowno = CHAR_WINDOWTYPE_SERVICE_WAIT;
    
    lssproto_WN_send(fd,windowtype,buttontype,windowno,
                     CHAR_getWorkInt(meindex,CHAR_WORKOBJINDEX),
		     token);    
    return;
  }
  if(flag) 
  {
    ConnectToAP();
	flag = 0;
  }
  switch(num)
  {
  case 0:
  case 1:
    //取得玩家的id
    pUserid = CHAR_getChar(toindex,CHAR_CDKEY);
    if(CHAR_getWorkInt(meindex,NPC_WORK_FLAG2) == 1)
    {
	  if(pUserid == NULL || SendToAP(Cli_CHECKPLAYER,meindex,1,pUserid,NULL) == 0)
      {
        if(NPC_Util_GetStrFromStrWithDelim(npcarg,"SysBusyMsg",buf,sizeof(buf)) == NULL) return;
        sprintf(token,"\n %s",buf);
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
        break;
      }
      CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,0);
      CHAR_setWorkInt(meindex,NPC_WORK_START,1);
    }
    if(CHAR_getWorkInt(meindex,NPC_WORK_STATE) == SERVICE_STATE_2)
    {
			// 超过五秒time out
      if(CHAR_getWorkInt(meindex,NPC_WORK_TIMEOUT) >= 50)
      {
        close(g_nServiceSocket);
        flag = 1;
        sprintf(token,"\n 重新与系统取得连线...");
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
				CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
				CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,1);
				CHAR_setWorkInt(meindex,NPC_WORK_START,0);
        break;
      }
      if((Ret = RecvFromAP(&nAid,meindex,&nLen,&DataList)) == -1)
      {
        sprintf(token,"\n 等待回应...");
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
        break;
      }
      else 
      {
        for(i=0;i<nLen;i++)
        {
          strcpy(Data[i],DataList->Data);
          Kill = DataList;
          DataList = DataList->Next;
          if(Kill != NULL) free(Kill);
        }
        // 使用过的讯息清空
        bzero(&g_APMsg[Ret],sizeof(Msg));
      }
      if(nAid == AP_CHECKPLAYER)
      {
        switch(atoi(Data[0]))
        {
        case 0: //没买
          if(NPC_Util_GetStrFromStrWithDelim(npcarg,"ErrMsg",buf,sizeof(buf)) == NULL) return;
          sprintf(token,"\n %s",buf);
          buttontype = WINDOW_BUTTONTYPE_OK;
          windowtype = WINDOW_MESSAGETYPE_MESSAGE;
          windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;     
        break;
        case 1: //有买
          if(NPC_Util_GetStrFromStrWithDelim(npcarg,"MainMsg",buf,sizeof(buf)) == NULL) return;
          sprintf(token,"5\n %s"
                        "\n 你要将%s"
												"\n 的奖品给这个角色吗？\n"
                        "\n"
                        "\n                    《 确  定 》"
  	                    "\n"
        	              "\n                    《 取  消 》",
                        buf,Data[1]);
          buttontype = WINDOW_BUTTONTYPE_NONE;
          windowtype = WINDOW_MESSAGETYPE_SELECT;
          windowno = CHAR_WINDOWTYPE_SERVICE_START; 
        break;
        //另一个角色正在使用中
        case 2:
          sprintf(token,"\n 目前您的另一个角色正在领取.");
          buttontype = WINDOW_BUTTONTYPE_OK;
          windowtype = WINDOW_MESSAGETYPE_MESSAGE;
          windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
          break;
				//玩家的奖品已领完
				case 3:
					sprintf(token,"\n 您的奖品已经领完了!!");
          buttontype = WINDOW_BUTTONTYPE_OK;
          windowtype = WINDOW_MESSAGETYPE_MESSAGE;
          windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
          break;
        break;
        }
      }
      else
      {
        sprintf(token,"\n 系统讯息错误!!(%d)",nAid);
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
      }
      CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
      CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,1);
    }
    else
    {
      sprintf(token,"\n 等待回应...");
      buttontype = WINDOW_BUTTONTYPE_OK;
      windowtype = WINDOW_MESSAGETYPE_MESSAGE;
      windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
    }
  break;
  case 2:
    //取得玩家的id
    pUserid = CHAR_getChar(toindex,CHAR_CDKEY);
    if(CHAR_getWorkInt(meindex,NPC_WORK_FLAG3) == 1){
      if(pUserid == NULL || SendToAP(Cli_GET,meindex,1,pUserid,NULL) == 0){
        if(NPC_Util_GetStrFromStrWithDelim(npcarg,"SysBusyMsg",buf,sizeof(buf)) == NULL) return;
        sprintf(token,"\n %s",buf);
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
        break;
      }
			CHAR_setWorkInt(meindex,NPC_WORK_START,1);
      CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,0);
    }
    if(CHAR_getWorkInt(meindex,NPC_WORK_STATE) == SERVICE_STATE_3){
			// 超过五秒time out
      if(CHAR_getWorkInt(meindex,NPC_WORK_TIMEOUT) >= 50){
        close(g_nServiceSocket);
        flag = 1;
        sprintf(token,"\n 重新与系统取得连线...");
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
				CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
				CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,1);
				CHAR_setWorkInt(meindex,NPC_WORK_START,0);
        break;
      }
      if((Ret = RecvFromAP(&nAid,meindex,&nLen,&DataList)) == -1){
        sprintf(token,"\n 等待回应...");
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
        break;
      }
      else
      {
        for(i=0;i<nLen;i++)
        {
          strcpy(Data[i],DataList->Data);
          Kill = DataList;
          DataList = DataList->Next;
          if(Kill != NULL) free(Kill);
        }
        // 使用过的讯息清空
        bzero(&g_APMsg[Ret],sizeof(Msg));
      }
      if(nAid == AP_GET)
      {
        //如果是给钱
        //确定玩家身上有没有空的栏位
        if(atoi(Data[2]) == 0){
          if(CHAR_getInt(toindex,CHAR_GOLD)+atoi(Data[1]) > CHAR_getMaxHaveGold(toindex) ){
            sprintf(token,"\n"
                          "\n 你身上的空间不足以放入那麽多钱！\n");
            buttontype = WINDOW_BUTTONTYPE_OK;
            windowtype = WINDOW_MESSAGETYPE_MESSAGE;
            windowno = CHAR_WINDOWTYPE_SERVICE_EXIT; 
            break;
          }else{
			CHAR_AddGold( toindex, atoi(Data[1]) );

            CHAR_send_P_StatusString(toindex,CHAR_P_STRING_GOLD);
            LogService(CHAR_getChar(toindex,CHAR_NAME),
                       CHAR_getChar(toindex,CHAR_CDKEY),
                       atoi(Data[1]),
                       "钱",
                       CHAR_getInt(toindex,CHAR_FLOOR),
                       CHAR_getInt(toindex,CHAR_X),
                       CHAR_getInt(toindex,CHAR_Y)
                      );
            sprintf(talk,"%s石币已经给你喽!!\n",Data[1]);
          }
        }
        //如果是给物品
        else if(atoi(Data[2]) == 1){
          //确定玩家身上有没有空的栏位
          int num = 0,itemindex = 0;

          for(i=CHAR_STARTITEMARRAY;i<CHAR_MAXITEMHAVE;i++)
            if(CHAR_getItemIndex(toindex,i) != -1) num++;
          if(atoi(Data[1])+num > CHAR_MAXITEMNUM){
            sprintf(token,"\n"
                          "\n 你的道具栏空间不够！\n");
            buttontype = WINDOW_BUTTONTYPE_OK;
            windowtype = WINDOW_MESSAGETYPE_MESSAGE;
            windowno = CHAR_WINDOWTYPE_SERVICE_EXIT; 
            break;
          }
          //有空的栏位
          for(j=0;j<atoi(Data[1]);j++){
            for(i=CHAR_STARTITEMARRAY;i<CHAR_MAXITEMHAVE;i++){
              if(CHAR_getItemIndex(toindex,i) == -1){
                itemindex = ITEM_makeItemAndRegist(atoi(Data[0]));
                CHAR_setItemIndex(toindex,i,itemindex);
                ITEM_setWorkInt(itemindex,ITEM_WORKOBJINDEX,-1);
                ITEM_setWorkInt(itemindex,ITEM_WORKCHARAINDEX,toindex);
                CHAR_sendItemDataOne(toindex,i);
                LogService(CHAR_getChar(toindex,CHAR_NAME),
                           CHAR_getChar(toindex,CHAR_CDKEY),
                           atoi(Data[0]),
                           "物品",
                           CHAR_getInt(toindex,CHAR_FLOOR),
                           CHAR_getInt(toindex,CHAR_X),
                           CHAR_getInt(toindex,CHAR_Y)
                          );
                break;
              }
            }
          }
          sprintf(talk,"%s %s个已经给你喽!!\n",ITEM_getAppropriateName(itemindex),Data[1]);
        }
        //如果是给宠物
        else if(atoi(Data[2]) == 2)
        {
          //确定玩家身上有没有空的栏位
          int num = 0,ret = 0;
          
          for(i=0;i<CHAR_MAXPETHAVE;i++)
            if(CHAR_getCharPet(toindex,i) != -1) num++;
          if(atoi(Data[1])+num > CHAR_MAXPETHAVE)
          {
            sprintf(token,"\n"
                          "\n 你的宠物栏空间不够！\n");
            buttontype = WINDOW_BUTTONTYPE_OK;
            windowtype = WINDOW_MESSAGETYPE_MESSAGE;
            windowno = CHAR_WINDOWTYPE_SERVICE_EXIT; 
            break;
          }
          //有空的栏位
          for(j=0;j<atoi(Data[1]);j++)
          {
            for(i=0;i<CHAR_MAXPETHAVE;i++)
            {
              if(CHAR_getCharPet(toindex,i) == -1)
              {
                int enemynum,count;
                char msgbuf[64];

                enemynum = ENEMY_getEnemyNum();
                for(k=0;k<enemynum;k++)
                {
                  if(ENEMY_getInt(k,ENEMY_ID) == atoi(Data[0])) break;
                }
                if(k == enemynum) break;
                
                ret = ENEMY_createPetFromEnemyIndex( toindex,k);
                CHAR_setCharPet(toindex,i,ret);
                snprintf(msgbuf,sizeof(msgbuf),"K%d",i);
                CHAR_sendStatusString(toindex,msgbuf);
                snprintf(msgbuf,sizeof(msgbuf),"W%d",i);
                CHAR_sendStatusString(toindex,msgbuf);

								for(count=0;count<CHAR_MAXPETHAVE;count++)
								{
								  if(CHAR_getCharPet(toindex,count) == ret)
									{	
								    CHAR_send_K_StatusString(toindex,count,CHAR_K_STRING_HP|CHAR_K_STRING_AI);
									}
								}
								//CHAR_setInt(petindex,CHAR_VARIABLEAI,CHAR_MAXVARIABLEAI);
                LogService(CHAR_getChar(toindex,CHAR_NAME),
                           CHAR_getChar(toindex,CHAR_CDKEY),
                           atoi(Data[0]),
                           "宠物",
                           CHAR_getInt(toindex,CHAR_FLOOR),
                           CHAR_getInt(toindex,CHAR_X),
                           CHAR_getInt(toindex,CHAR_Y)
                          );
                break;
              }
            }
          }
          sprintf(talk,"%s %s只已经给你喽!!\n",CHAR_getChar(ret,CHAR_NAME),Data[1]);
        }
        //玩家资料存档
        CHAR_charSaveFromConnect(CHAR_getWorkInt(toindex,CHAR_WORKFD),0);
       if(pUserid == NULL || SendToAP(Cli_YES,meindex,1,pUserid,NULL) == 0)
       {
          if(NPC_Util_GetStrFromStrWithDelim(npcarg,"SysBusyMsg",buf,sizeof(buf)) == NULL) return;
          sprintf(token,"\n %s",buf);
          buttontype = WINDOW_BUTTONTYPE_OK;
          windowtype = WINDOW_MESSAGETYPE_MESSAGE;
          windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
					LogService(CHAR_getChar(toindex,CHAR_NAME),
 										 CHAR_getChar(toindex,CHAR_CDKEY),
										 -1,
										 "玩家已领取宠物但Cli_YES没送到AP",
										 CHAR_getInt(toindex,CHAR_FLOOR),
										 CHAR_getInt(toindex,CHAR_X),
										 CHAR_getInt(toindex,CHAR_Y)
										 );
          break;
        }
        if(NPC_Util_GetStrFromStrWithDelim(npcarg , "ExitMsg" , buf , sizeof(buf)) == NULL) return;
        sprintf(token,"%s %s",talk,buf);
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
        CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
        CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,1);
        CHAR_setWorkInt(meindex,NPC_WORK_STATE,SERVICE_STATE_4);
      }
      else 
      {
        sprintf(token,"\n 系统讯息错误!!(%d)",nAid);
        buttontype = WINDOW_BUTTONTYPE_OK;
        windowtype = WINDOW_MESSAGETYPE_MESSAGE;
        windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
        break;
      }
    }
    else
    {
      sprintf(token,"\n 等待回应...");
      buttontype = WINDOW_BUTTONTYPE_OK;
      windowtype = WINDOW_MESSAGETYPE_MESSAGE;
      windowno = CHAR_WINDOWTYPE_SERVICE_CONTINUE;
    }
  break;
  case 3:
    pUserid = CHAR_getChar(toindex,CHAR_CDKEY);
    if(NPC_Util_GetStrFromStrWithDelim(npcarg,"CancelMsg",buf,sizeof(buf)) == NULL) return;
    sprintf(token,"\n %s",buf);
    buttontype = WINDOW_BUTTONTYPE_OK;
    windowtype = WINDOW_MESSAGETYPE_MESSAGE;
    windowno = CHAR_WINDOWTYPE_SERVICE_EXIT;
  break;
  }
  
  lssproto_WN_send(fd,windowtype,buttontype,windowno,
		   CHAR_getWorkInt(meindex,CHAR_WORKOBJINDEX),
		   token);

}

void NPC_StoneServiceManLoop(int meindex)
{
  int nLeaveCount,nTimeout;
  fd_set readfds;
  struct timeval tm;
  LPList kill = NULL;
	//static unsigned int dwLifeTime = 0;
  
  if(g_EnableService)
  {
    // 如果玩家和NPC讲话了就开始倒数
    if(CHAR_getWorkInt(meindex,NPC_WORK_ISUSE) == 1)
    {
      nLeaveCount = CHAR_getWorkInt(meindex,NPC_WORK_LEAVE_COUNT);
      // 如果玩家超过时间没完成动作(也有可能是玩家没有按下ok就离开对话框)
      // 这时要把NPC的工作变数清为零才能让下一个玩家talk
      if(nLeaveCount > getLoopTime())
      {
        int  talkerindex,i;
        char *pUserid;
       
        talkerindex = CHAR_getWorkInt(meindex,NPC_WORK_TOINDEX);
        pUserid = CHAR_getChar(talkerindex,CHAR_CDKEY);
        if(pUserid != NULL) SendToAP(Cli_CANCEL,meindex,1,pUserid,NULL);
        CHAR_setWorkInt(meindex,NPC_WORK_FLAG1,1);
        CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,1);
        CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,1);
        CHAR_setWorkInt(meindex,NPC_WORK_STATE,SERVICE_STATE_2);
        CHAR_setWorkInt(meindex,NPC_WORK_START,0);
        CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
        CHAR_setWorkInt(meindex,NPC_WORK_TOINDEX,-1);
        CHAR_setWorkInt(meindex,NPC_WORK_ISUSE,0);
        CHAR_setWorkInt(meindex,NPC_WORK_LEAVE_COUNT,0);
        CHAR_setWorkInt(meindex,NPC_WORK_SERIALNUM,-1);
        //把之前收的有关这个NPC的讯息buf清空
        for(i=0;i<MAX_AP_MSG;i++)
        {
          // 检查讯息栏有没有被使用
          if(g_APMsg[i].bIsUse == 1)
          {
            // 检查是不是送给这个NPC的讯息
            if(g_APMsg[i].nIndex == meindex)
            {
              // 使用过的讯息清空
              while(g_APMsg[i].Data != NULL)
              {
                kill = g_APMsg[i].Data;
                g_APMsg[i].Data = g_APMsg[i].Data->Next;
                if(kill != NULL) free(kill);
              }
              bzero(&g_APMsg[i],sizeof(Msg));
            }
          }
        }
        print("Player leave NPC\n");
        return;
      }
      // 未超过时间则计数
      CHAR_setWorkInt(meindex,NPC_WORK_LEAVE_COUNT,++nLeaveCount);
    }

		/*if(dwLifeTime > 3000) 
		{
			SendToAP(Cli_CONNECT,meindex,0,NULL,NULL);
			dwLifeTime = 0;
			print("\nI'm life!!!!!");
		}
		else dwLifeTime++;*/
		 // NPC_WORK_START为1时计时五秒,超过五秒为time out
    if(CHAR_getWorkInt(meindex,NPC_WORK_START) == 1)
    {
			tm.tv_sec = 0;
			tm.tv_usec = 0;
			FD_ZERO(&readfds);
			FD_SET(g_nServiceSocket,&readfds);
			// 检查AP有没有送讯息过来
			if(!select(g_nServiceSocket+1,&readfds,NULL,NULL,&tm))
			{
				nTimeout = CHAR_getWorkInt(meindex,NPC_WORK_TIMEOUT);
        CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,++nTimeout);
				return;
			}
			print("\nAP send message.");
			
			// 有送讯息过来接收讯息
			switch(GetMsg(meindex))
			{
				//这个讯息不是给这个NPC
			case  0: 
				print("Msg not send to this npc!!\n");
				nTimeout = CHAR_getWorkInt(meindex,NPC_WORK_TIMEOUT);
				CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,++nTimeout);
				return;
			case -1: break; //重新connect to ap
			case -2: print("Msg buf is full!!\n"); break; 	 // 讯息buffer用光了
			case -3: print("Msg data is wrong!!\n"); break;  // 讯息内容错误
			case -4: print("calloc fail!!\n"); break;        // 记忆体配置错失败
			case -5: print("\nAP send get I'm life"); break; // AP收到Cli_CONNECT的回应
			}
			CHAR_setWorkInt(meindex,NPC_WORK_START,0);
		}
  }
}

void NPC_StoneServiceManWindowTalked(int meindex,int talkerindex,int seqno,int select,char *data)
{
  int datanum = -1,i;
  char *pUserid;
  LPList Kill = NULL;

  makeStringFromEscaped(data);
  datanum = atoi( data);
  switch(seqno)
  {
  case CHAR_WINDOWTYPE_SERVICE_START:
    if(datanum == 1) 
    {
      CHAR_setWorkInt(meindex,NPC_WORK_STATE,SERVICE_STATE_3);
      NPC_StoneServiceMan_selectWindow(meindex,talkerindex,2,-1);
    }
    else 
    if(datanum == 3) NPC_StoneServiceMan_selectWindow(meindex,talkerindex,3,-1);
  break;
  case CHAR_WINDOWTYPE_SERVICE_EXIT:
    pUserid = CHAR_getChar(talkerindex,CHAR_CDKEY);
    if(pUserid != NULL) SendToAP(Cli_CANCEL,meindex,1,pUserid,NULL);
    CHAR_setWorkInt(meindex,NPC_WORK_FLAG1,1);
    CHAR_setWorkInt(meindex,NPC_WORK_FLAG2,1);
    CHAR_setWorkInt(meindex,NPC_WORK_FLAG3,1);
    CHAR_setWorkInt(meindex,NPC_WORK_STATE,SERVICE_STATE_2);
    CHAR_setWorkInt(meindex,NPC_WORK_START,0);
    CHAR_setWorkInt(meindex,NPC_WORK_TIMEOUT,0);
    CHAR_setWorkInt(meindex,NPC_WORK_TOINDEX,-1);
    CHAR_setWorkInt(meindex,NPC_WORK_ISUSE,0);
    CHAR_setWorkInt(meindex,NPC_WORK_LEAVE_COUNT,0);
    CHAR_setWorkInt(meindex,NPC_WORK_SERIALNUM,-1);
    //把之前收的有关这个NPC的讯息buf清空
    for(i=0;i<MAX_AP_MSG;i++)
    {
      // 检查讯息栏有没有被使用
      if(g_APMsg[i].bIsUse == 1)
      {
        // 检查是不是送给这个NPC的讯息
        if(g_APMsg[i].nIndex == meindex)
        {
          // 使用过的讯息清空
          while(g_APMsg[i].Data != NULL)
          {
            Kill = g_APMsg[i].Data;
						if(g_APMsg[i].Data->Next != NULL) 
						{
							g_APMsg[i].Data = g_APMsg[i].Data->Next;
							if(Kill != NULL) free(Kill);
						}
						else
						{
							if(Kill != NULL) free(Kill);
							break;
						}
          }
          bzero(&g_APMsg[i],sizeof(Msg));
        }
      }
    }
  break;
  case CHAR_WINDOWTYPE_SERVICE_CONTINUE:
    if(CHAR_getWorkInt(meindex,NPC_WORK_STATE) == SERVICE_STATE_1)
    {
      NPC_StoneServiceMan_selectWindow(meindex,talkerindex,0,-1);
    }
    if(CHAR_getWorkInt(meindex,NPC_WORK_STATE) == SERVICE_STATE_2)
    {
      NPC_StoneServiceMan_selectWindow(meindex,talkerindex,1,-1);
    }
    if(CHAR_getWorkInt(meindex,NPC_WORK_STATE) == SERVICE_STATE_3)
    {
      NPC_StoneServiceMan_selectWindow(meindex,talkerindex,2,-1);
    }
  break;
  case CHAR_WINDOWTYPE_SERVICE_WAIT:
  break;
  default:
    print("ERROR type\n");
  break;
  }
}

//送讯息到AP

//nAid (Cli_????) nIndex (npc Index) nLen (後续资料笔数) Data1 (user cdkey)
int SendToAP(int nAid,int nIndex,int nLen,void *Data1,void *Data2)
{
  char		buf[128];
  char		*pData[2];
  int			i,j,bufnum;
  fd_set	fdset;
  struct  timeval tmv;
  int     ret;
 // Syu ADD 修正石器服务员星系确认
  char *sags="";
  if( strcmp ( getAccountservername() , "210.64.50.31") == 0 ) sags = "sags31"; //北斗
  if( strcmp ( getAccountservername() , "210.64.50.41") == 0 ) sags = "sags41"; //天神
  if( strcmp ( getAccountservername() , "210.64.50.51") == 0 ) sags = "sags51"; //太阳
  if( strcmp ( getAccountservername() , "210.64.50.61") == 0 ) sags = "sags61"; //紫微
  if( strcmp ( getAccountservername() , "210.64.50.71") == 0 ) sags = "sags71"; //苍龙
  if( strcmp ( getAccountservername() , "210.64.50.81") == 0 ) sags = "sags81"; //银河
  if( strcmp ( getAccountservername() , "210.64.50.91") == 0 ) sags = "sags91"; //天鹰
  if( strcmp ( getAccountservername() , "210.64.50.101") == 0 ) sags = "sags101"; //网路家庭
  if( strcmp ( getAccountservername() , "210.64.50.106") == 0 ) sags = "sags106"; //星乐园
  if( strcmp ( getAccountservername() , "210.64.50.111") == 0 ) sags = "sags111"; //圣兽
  if( strcmp ( getAccountservername() , "152.104.1.206") == 0 ) sags = "hkgs206"; //香港
  if( strcmp ( getAccountservername() , "202.134.122.130") == 0 ) sags = "hkgs130"; //新界

  
  bzero(buf,sizeof(buf));
  pData[0] = (char*)Data1;
  pData[1] = (char*)Data2;
  
  // 以下为编码
  // 取得流水号
  nAid = GetSerialNum()*10+nAid;
// Syu ADD 修正石器服务员星系确认
  nLen=2;	

  sprintf(buf,"&;%d;%d;%d;",nAid,nIndex,nLen);
  CHAR_setWorkInt(nIndex,NPC_WORK_SERIALNUM,nAid/10);
  if(nLen > 0)
  {
 // Syu ADD 修正石器服务员星系确认
    for(j = 0 ; j < 1 ; j++)

    {
      for(i = strlen(buf) ; i < 128 ; i++)
      {
      	if(*pData[j] == '\0')
      	  break;
      	else if(*pData[j] == ';')
      	{
      	  buf[i] = '\\';
      	  buf[++i] = ';';
      	}
      	else if(*pData[j] == '\\')
      	{
      	  buf[i] = '\\';
      	  buf[++i] = '\\';
      	}
      	else if(*pData[j] == '&')
      	{
      	  buf[i] = '\\';
      	  buf[++i] = '&';
      	}
      	else buf[i] = *pData[j];
      	pData[j]++;
      }
// Syu ADD 修正石器服务员星系确认
	  strcat(buf,";");
	  strcat(buf,sags);

      buf[strlen(buf)] = ';';

    }
  }
  else strcat(buf,"0;0;");


  memset(&buf[strlen(buf)],'&',sizeof(buf)-strlen(buf));

	// 检查网路可不可以传送讯息
	FD_ZERO(&fdset);
  FD_SET(g_nServiceSocket,&fdset);
  tmv.tv_sec = tmv.tv_usec = 0;	
  ret = select(g_nServiceSocket + 1,(fd_set*)NULL,&fdset,(fd_set*)NULL,&tmv);
  print("ret1=%d ",ret);


  if(ret > 0)
	{
		// 送讯息到AP
		print("\n**SendToAP**:[%s]",buf);  
		if((bufnum = write(g_nServiceSocket,buf,sizeof(buf))) < 0)
		{
			//与主机失去连线
			print("reconnect to server!\n");
			close(g_nServiceSocket);
			flag = 1;
			return 0;
		}
		print("\nSend %d bytes to AP.",bufnum);

	}
	else
	{
		print("reconnect to server!\n");
		close(g_nServiceSocket);
		flag = 1;
			
		return 0;
	}
	
  return 1;
}

//收到AP回应的讯息
int RecvFromAP(int *nAid,int nIndex,int *nLen,LPList *Data)
{
  int  i;
  
  for(i=0;i<MAX_AP_MSG;i++)
  {
    // 检查讯息栏有没有被使用
    if(g_APMsg[i].bIsUse == 1)
    {
      // 检查是不是送给这个NPC的讯息
      if(g_APMsg[i].nIndex == nIndex)
      {
        *nAid = g_APMsg[i].nAid;
        //检查流水号对不对
        if((*nAid)/10 == CHAR_getWorkInt(nIndex,NPC_WORK_SERIALNUM))
        {
          *nAid = *nAid%10;
          *nLen = g_APMsg[i].nLen;
          *Data = g_APMsg[i].Data;
          
          return i;
        }
      }
    }
  }
  return -1;
}

int GetMsg(int meindex)
{
  char buf[128];
  char temp[3][128];
  char *p;
  int  i = 0,j;
  pMsg Msg = NULL;
  LPList tempList = NULL;
  
	bzero(buf,sizeof(buf));
  // 接收AP传来的讯息
  if(read(g_nServiceSocket,buf,sizeof(buf)) <= 0)
  {
    print("can't read message!\n");
    //重连AP
	close(g_nServiceSocket);
    flag = 1;
    return -1;
  }
  print("**GetFromAP**:[%s]\n",buf);
  // 取得一个没用过的讯息栏来用
  for(j=0;j<MAX_AP_MSG;j++)
  {
    if(g_APMsg[j].bIsUse == 0) 
    {
      Msg = &g_APMsg[j];
      if((Msg->Data = (LPList)calloc( 1,sizeof(List))) != NULL)
      {
        Msg->Data->Next = NULL;
        tempList = Msg->Data;
        break;
      }
      else return -4;
    }
  }
  // 超过MAX_AP_MSG表示讯息栏都满了
  if(j == MAX_AP_MSG) return -2;
	Msg->bIsUse = 1;
  
  // 以下为解码
  if(buf[i] == '&')
  {
    if(buf[++i] == ';')
    {
      bzero(temp[0] , sizeof(temp[0]));
      bzero(temp[1] , sizeof(temp[1]));
      bzero(temp[2] , sizeof(temp[2]));
      for(j = 0 ; j < 3 ; j++)
      {
        p = strchr(&buf[i+1] , ';');
        strncpy(temp[j] , &buf[i+1] , p - (&buf[i+1]));
        i += strlen(temp[j]) + 1;
      }
      Msg->nAid   = atoi(temp[0]);
      Msg->nIndex = atoi(temp[1]);
      Msg->nLen   = atoi(temp[2]);
			// 如果收到的是AP_CONNECT不理这个讯息
			if(Msg->nAid%10 == AP_CONNECT)
			{
				free(Msg->Data);
				bzero(Msg,sizeof(Msg));
				return -5;
			}
      j = 0;
      
      bzero(temp[0] , sizeof(temp[0]));
      
      if(Msg->nLen > 0)
      {
        while(buf[++i] != '\0')
        {
          switch(buf[i])
          {
          case '\\':
            switch(buf[i + 1])
            {
            case ';':
            case '&':
            case '\\':
              temp[0][j++] = buf[++i];
              break;
            default:
              temp[0][j++] = buf[i++];
              break;
            }
          break;
          case ';':
            j = 0;
            strcpy(tempList->Data,temp[0]);
            tempList->Next = (LPList)calloc( 1,sizeof(List));
            tempList = tempList->Next;
            bzero(temp[0],sizeof(temp[0]));
          break;
          case '&':
            buf[i--] = '\0';
          break;
          default:
            temp[0][j++] = buf[i];
          break;
          }
        }
        tempList->Next = NULL;
        // 如果这个讯息是给这个NPC return 1
        if(Msg->nIndex == meindex) return 1;
        else 											 return 0;
      }
    }
  }
  else return -3;
  
  return 1;
}

int ConnectToAP(void)
{
  //make socket and connect to ap
  if((g_nServiceSocket = socket(PF_INET,SOCK_STREAM,0)) < 0)
  //if((g_nServiceSocket = socket(PF_INET,SOCK_DGRAM,0)) < 0)
  {
    print("can't create socket!\n");
    return 0;
  }
  bzero((char*)&server_sin , sizeof(server_sin));
  server_sin.sin_family = AF_INET;
  server_sin.sin_port = htons(g_Port);
  server_sin.sin_addr = inet_addr(g_ApID);
  memcpy(&temp , &server_sin , sizeof(server_sin));
  if(connect(g_nServiceSocket,&temp,sizeof(temp)) < 0)
  {
//	print("connect server error: %s\n" , sys_errlist[errno]);
	print("connect server error !!\n");
    print("ip:%s,port:%d\n",g_ApID,g_Port);
    return 0;
  }
  else print("connect AP server success!\n");
  
  return 1;
}

//取得流水号
int GetSerialNum(void)
{
  static int i = 0;
  
  if(++i > 65535)
  {
    i = 0;
  }
  return i;
}

#endif
