www.pudn.com > M2Server.rar > MainForm.pas


//////////////////////////////////////////////////////////////////////////////// 
//                                                                            // 
//                       工程:  M2Server                                     // 
//                       版本:   1.0                                          // 
//                       公司:  乐都在线                                     // 
//                       网址:  http://www.hh8.net                           // 
//                       日期:  2005-05-28                                   // 
//                                                                            // 
//////////////////////////////////////////////////////////////////////////////// 
unit MainForm; 
 
interface 
 
uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ComCtrls, IdThreadMgr, IdThreadMgrDefault, IdTCPServer, 
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, INIFiles, 
  StdCtrls, Buttons, ClassDeclaration, PredefinedData, DataHandler, StrUtils, 
  ExtCtrls, IdWinSock2, UserInfo, D7ScktComp, ObjectMonster, ObjectNPC; 
 
type 
 
 
  ProcessTCPClientLog = class(TThread) 
  private 
    //   CB: TCommBlock; 
    procedure HandleInput; 
  protected 
    m_bInHandle: Boolean; 
    procedure Execute; override; 
  end; 
 
  TFormMain = class(TForm) 
    TimerConnectServer: TTimer; 
    ServerSocket1: TServerSocket; 
    DecodeTimer: TTimer; 
    ClientSocketDB: TClientSocket; 
    Timer1: TTimer; 
    ClientSocketID: TClientSocket; 
    TimerHum: TTimer; 
    TimerMon: TTimer; 
    TimerNpc: TTimer; 
    Label1: TLabel; 
    Label2: TLabel; 
    StatusBar1: TStatusBar; 
    memLogInfo: TMemo; 
    procedure FormCreate(Sender: TObject); 
    procedure BitBtnStopServiceClick(Sender: TObject); 
    procedure TimerConnectServerTimer(Sender: TObject); 
    procedure IdTCPServerSocketConnect(AThread: TIdPeerThread); 
    procedure ServerSocket1ClientConnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure ServerSocket1ClientError(Sender: TObject; 
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
      var ErrorCode: Integer); 
    procedure ServerSocket1ClientRead(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure DecodeTimerTimer(Sender: TObject); 
    procedure ClientSocketDBRead(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure ClientSocketDBError(Sender: TObject; 
      Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
      var ErrorCode: Integer); 
    procedure Timer1Timer(Sender: TObject); 
    procedure ClientSocketIDRead(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure TimerHumTimer(Sender: TObject); 
    procedure TimerMonTimer(Sender: TObject); 
    procedure FormClose(Sender: TObject; var Action: TCloseAction); 
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    procedure TimerNpcTimer(Sender: TObject); 
    procedure ClientSocketDBConnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
    procedure ClientSocketDBDisconnect(Sender: TObject; 
      Socket: TCustomWinSocket); 
  private 
    { Private declarations } 
  public 
    // Public Variable decalrations 
 
    ThreadTCPClientLog: ProcessTCPClientLog; 
 
    // Public Method and Function decalrations 
 
    procedure StartServer; 
    procedure InsertLogMsg(strMessage: string); 
    function ReadConfig(var iniconfiguration: TIniConfiguration_RCD): Boolean; 
    function SaveConfig(): Boolean; 
 
    function InitializingServer(pMapInfo: MAPINFO_RCD_ARRAY): Integer; 
    function InitDataInDatabase: MAPINFO_RCD_ARRAY; 
    procedure ProcessUserPacket(UserData: pTSendUserData); 
 
  end; 
 
  // Global Function Declarations 
procedure InitGlobalVariable; 
procedure FreeGlobalVariable; 
 
procedure ProcReceiveBufferDB; 
 
var 
  FormMain: TFormMain; 
  g_IniConfiguration: TIniConfiguration_RCD; 
  HumCOunt: Integer; 
  mon: TMonsterObject; 
  nCurrMonGen: Integer; 
  RunMonGen: Integer; 
  Busy: Boolean; 
 
  MDlgPoints: TList; 
  SelectMenuStr: string; 
  MdgStr: string; 
  RequireAddPoints: Boolean; 
  Myself: TUserInfo; 
  MonCount: Integer; 
implementation 
 
uses FunctionDeclaration, ObjectPlayer, GlobalDefinition, 
  ProcessThreads, EDcode, show, MyDebug; 
 
{$R *.dfm} 
 
 
 
 
 
procedure ProcessTCPClientLog.HandleInput; 
begin 
  //  do nothing 
end; 
 
procedure ProcessTCPClientLog.Execute; 
 
begin 
  // while 
end; 
 
{解析数据包} 
procedure ProcReceiveBufferDB; 
var 
  I, 
    nPos, 
    nFirst, 
    nEnd, 
    nCount, 
    nBuffLen, 
    index, 
    nCertification: Integer; 
  w1, 
    w2: Word; 
  lValid: Integer; 
  pszData, 
    pszDevide, 
    pszFirst, 
    pszEnd: string; 
  GenItemRcd: TGENITEM_RCD; 
  lptGenItemRcd: PUSERITEM; 
  DefMsg, 
    SendDefMsg: TDEFAULTMESSAGE_RCD; 
  pReadyUserInfo: TReadyUserInfo; 
  pReadyUserInfo2: TReadyUserInfo2; 
  pPlayerObject: TPlayerObject; 
  pUserInfo: TUserInfo; 
  tClientItem: PTCLIENTITEM; 
  lpHumanMagicRcd: PTClientMagic; 
  szVal: string; 
  szCC: array[1..32] of Char; 
  szBuff: array[1..8192] of Char; 
  szEncodeMsg: array[1..256] of Char; 
  m_THumanRcd: THUMAN_RCD; 
 
begin 
  g_szRemainBuff := g_szRemainBuff + g_szTempBuffer; 
  g_szTempBuffer := ''; 
 
  nBuffLen := Length(g_szRemainBuff); 
  g_szRemainBuff := ArrestStringEx(g_szRemainBuff, '#', '!', pszData); 
 
  while pszData <> '' do 
  begin 
    pszData := GetValidStr3(pszData, pszDevide, ['/']); 
    if pszDevide <> '' then 
    begin 
      nCertification := StrToInt(pszDevide); 
 
      w1 := nCertification xor $AA; 
      w2 := Length(pszData); 
      lValid := MAKELONG(w1, w2); 
 
      nPos := Encode6BitBuf(@lValid, @szCC[1], SizeOf(Integer), SizeOf(szCC)); 
      Inc(nPos); 
      szCC[nPos] := #0; 
      if Copy(pszData, Length(pszData) - nPos + 2, nPos - 1) = LeftBStr(szCC, 
        nPos - 1) then 
      begin 
        pszData := GetValidStr3(pszData, pszDevide, ['/']); 
        DefMsg := DecodeMessage(string(pszDevide)); 
 
        case DefMsg.wIdent of // 
          DBR_LOADHUMANRCD2: 
            begin 
 
            end; 
          DBR_LOADHUMANRCD: //获取角色信息 
            begin 
              Decode6BitBuf(pszData, @m_THumanRcd, SizeOf(THUMAN_RCD)); 
              if g_xReadyUserInfoList <> nil then 
              begin 
                try 
                  with g_xReadyUserInfoList.LockList do 
                  begin 
                    for nCount := 0 to COunt - 1 do 
                    begin 
                      pReadyUserInfo := TReadyUserInfo(items[nCount]); 
                      if (pReadyUserInfo.m_pUserInfo.m_szCharName =     //找到相应的用户 
                        m_THumanRcd.szCharName) or 
                        (pReadyUserInfo.m_pUserInfo.m_szUserID = m_THumanRcd.Id) 
                        then 
                      begin 
                        pReadyUserInfo.m_pUserInfo.m_THumanRcd := m_THumanRcd; 
                        if Trim(pReadyUserInfo.m_pUserInfo.m_THumanRcd.szMapName) = '' 
                          then 
                          pReadyUserInfo.m_pUserInfo.m_THumanRcd.szMapName := 
                            '0'; 
                        pReadyUserInfo.m_pUserInfo.m_TakeItemsCount := 0; 
                        for I := 0 to 8 do       //获取当前身上装备 
                        begin 
                          if 
                            pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Id 
                            > 0 then 
                          begin 
                            index := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].GoodId - 1; 
                            if (index < 0) or (index > High(g_pStdItemSpecial)) 
                              then 
                              Continue; 
                            g_pStdItemSpecial[index].GetStandardItem(@pReadyUserInfo.m_pUserInfo.m_TakeItems[I]); 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[I].Dura := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Stand; 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[I].DuraMax := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].MaxStand; 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[I].MakeIndex 
                              := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Id; 
                            Inc(pReadyUserInfo.m_pUserInfo.m_TakeItemsCount); 
                          end 
                          else 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[I].MakeIndex 
                              := 0; 
                        end; 
 
                        pReadyUserInfo.m_pUserInfo.m_BagItems.Clear; //获取物品栏中的物品 
                        for I := 9 to 50 do 
                        begin 
                          if 
                            pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Id 
                            > 0 then 
                          begin 
                            index := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].GoodId - 1; 
                            if (index < 0) or (index > High(g_pStdItemSpecial)) 
                              then 
                              Continue; 
                            New(tClientItem); 
                            g_pStdItemSpecial[index].GetStandardItem(tClientItem); 
                            tClientItem^.Dura := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Stand; 
                            tClientItem^.DuraMax := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].MaxStand; 
                            tClientItem^.MakeIndex := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.szTakeItem[I].Id; 
                            pReadyUserInfo.m_pUserInfo.m_BagItems.Add(tClientItem); 
 
                          end; 
                        end; 
 
                        for I := 0 to 3 do                   //获取四格 
                        begin 
                          if 
                            pReadyUserInfo.m_pUserInfo.m_THumanRcd.KeepGoods[46 + I].Id 
                            > 0 then 
                          begin 
                            index := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.KeepGoods[46 + i].GoodId - 1; 
                            if (index < 0) or (index > High(g_pStdItemSpecial)) 
                              then 
                              Continue; 
                            g_pStdItemSpecial[index].GetStandardItem(@pReadyUserInfo.m_pUserInfo.m_TakeItems[9 + I]); 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[9 + I].Dura := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.KeepGoods[46 + I].Stand; 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[9 + I].DuraMax := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.KeepGoods[46 + I].MaxStand; 
                            pReadyUserInfo.m_pUserInfo.m_TakeItems[9 + I].MakeIndex 
                              := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.KeepGoods[46 + I].Id; 
                            Inc(pReadyUserInfo.m_pUserInfo.m_TakeItemsCount); 
                            // 
                          end; 
                        end; 
 
                        for I := 0 to 19 do                     //获取魔法 
                        begin 
                          if pReadyUserInfo.m_pUserInfo.m_THumanRcd.Magic12[I].Id 
                            > 0 then 
                          begin 
                            New(lpHumanMagicRcd); 
                            lpHumanMagicRcd^.Level := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.Magic12[I].code; 
                            lpHumanMagicRcd^.key := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.Magic12[I].key; 
                            lpHumanMagicRcd^.CurTrain := 
                              pReadyUserInfo.m_pUserInfo.m_THumanRcd.Magic12[I].no; 
                            lpHumanMagicRcd^.Def := 
                              g_pMagicInfo[pReadyUserInfo.m_pUserInfo.m_THumanRcd.Magic12[I].Id - 1].Def; 
                            pReadyUserInfo.m_pUserInfo.m_lpTMagicRcd.Add(lpHumanMagicRcd); 
 
                          end; 
                        end; 
                        if pReadyUserInfo.m_pUserInfo.m_pxPlayerObject <> nil 
                          then 
                        begin 
                          TPlayerObject(pReadyUserInfo.m_pUserInfo.m_pxPlayerObject).AddProcess(TPlayerObject(pReadyUserInfo.m_pUserInfo.m_pxPlayerObject), 
                            RM_SendNotice, 0, 0, 0, 0, ''); 
                          TPlayerObject(pReadyUserInfo.m_pUserInfo.m_pxPlayerObject).MakeFeature; 
                          TPlayerObject(pReadyUserInfo.m_pUserInfo.m_pxPlayerObject).Initialize; 
                          TPlayerObject(pReadyUserInfo.m_pUserInfo.m_pxPlayerObject).m_fIsAlive := True; 
 
                          pReadyUserInfo.m_pUserInfo.m_btCurrentMode := 
                            USERMODE_PLAYGAME; 
                          Inc(HumCOunt); 
                        end; 
                        Delete(nCount); 
                        Break; 
                      end; 
                    end; 
                  end; 
                finally 
                  g_xReadyUserInfoList.UnlockList; 
                end; 
              end; 
            end; 
          DBR_MAKEITEMRCD: 
            begin 
 
            end; 
          DBR_MAKEITEMRCD2: 
            begin 
 
            end; 
        end; // case 
      end; 
    end; 
    g_szRemainBuff := ArrestStringEx(g_szRemainBuff, '#', '!', pszData); 
  end; 
 
 
 
  {if (pszFirst <> nil) and (nBuffLen > 0) then 
  begin 
    CopyMemory(@g_szRemainBuff[1], pszFirst, nBuffLen); 
    g_nRemainBuffLen := nBuffLen; 
  end 
  else 
  begin 
    g_nRemainBuffLen := 0; 
  end;     } 
 
end; 
 
{var 
 I, 
 nPos, 
 nFirst, 
 nEnd, 
 nBuffLen, 
 nCertification:   Integer; 
 w1, 
 w2:               Word; 
 lValid:           Integer; 
 pszData, 
 pszDevide, 
 pszFirst, 
 pszEnd:           PChar; 
 GenItemRcd:       TGENITEM_RCD ; 
 lptGenItemRcd:    PGENERALITEM_RCD; 
 DefMsg, 
 SendDefMsg:       TDEFAULTMESSAGE_RCD; 
 pReadyUserInfo:   TReadyUserInfo; 
 pReadyUserInfo2:  TReadyUserInfo2; 
 pPlayerObject:    TPlayerObject; 
 pUserInfo:        TUserInfo; 
 tClientItemRcd:   TCLIENTITEM_RCD; 
 lpTItemRcd:       PUSERITEM_RCD; 
 lpHumanMagicRcd:  PHUMANMAGIC_RCD; 
 szVal:            String; 
 szCC:             array [1..32]   of Char; 
 szBuff:           array [1..8192] of Char; 
 szEncodeMsg:      array [1..256]  of Char; 
begin 
 pszData   := nil; 
 pszDevide := nil; 
 pszFirst  := nil; 
 pszEnd    := nil; 
 
 g_szRemainBuff  := g_szRemainBuff + g_szTempBuffer; 
 g_szTempBuffer  := ''; 
 
 nBuffLen        := Length(g_szRemainBuff); 
 if nBuffLen > 0 then 
 begin 
   CopyMemory(@szBuff[1], @g_szRemainBuff[1], nBuffLen); 
 end; 
 
 pszEnd  := @szBuff[1]; 
 
 while nBuffLen > 0 do 
 begin 
   pszFirst  := MemChrDelphi(pszEnd,   '#', nBuffLen); 
   pszEnd    := MemChrDelphi(pszFirst, '!', nBuffLen); 
   if (pszFirst <> nil) and (pszEnd <> nil) then 
   begin 
     pszEnd[0] := #0; 
     Inc(pszEnd); 
     pszDevide := MemChrDelphi(pszFirst, '/', pszEnd - pszFirst); 
     if pszDevide <> nil then 
     begin 
       pszDevide[0]  := #0; 
       Inc(pszDevide); 
 
       nCertification := StrToInt(pszFirst + 1); 
 
       w1 := nCertification xor $AA; 
       w2 := StrLen(pszDevide); 
       lValid  := MAKELONG(w1, w2); 
 
       nPos := Encode6BitBuf(@lValid, @szCC[1], SizeOf(Integer), SizeOf(szCC)); 
       szCC[nPos] := #0; 
 
     end; 
   end; 
 end; 
 
 
 if (pszFirst <> nil) and (nBuffLen > 0) then 
 begin 
   CopyMemory(@g_szRemainBuff[1], pszFirst, nBuffLen); 
   g_nRemainBuffLen := nBuffLen; 
 end 
 else 
 begin 
   g_nRemainBuffLen := 0; 
 end; 
end; 
} 
 
 
{读取配置文件} 
function TFormMain.ReadConfig(var iniconfiguration: TIniConfiguration_RCD): 
  Boolean; 
var 
  inifile: TIniFile; 
begin 
  inifile := TIniFile.Create('.\GameSvr.ini'); 
  iniconfiguration.ServerTitle := inifile.ReadString('Server', 'ServerTitle', 
    '乐都传奇'); 
  iniconfiguration.Installed := inifile.ReadBool('Server', 'Installed', True); 
  iniconfiguration.ServerPort := inifile.ReadInteger('Server', 'ServerPort', 
    5000); 
  iniconfiguration.ServerNumber := inifile.ReadInteger('Server', 'ServerNumber', 
    0); 
  iniconfiguration.GameServerIndex := inifile.ReadInteger('Server', 
    'GameServerIndex', 0); 
  iniconfiguration.GameServerNumber := inifile.ReadInteger('Server', 
    'GameServerNumber', 0); 
  iniconfiguration.GameServerName := inifile.ReadString('Server', 
    'GameServerName', 'ServerName'); 
  iniconfiguration.StartLevel := inifile.ReadInteger('Server', 'StartLevel', 1); 
  iniconfiguration.StartGold := inifile.ReadInteger('Server', 'StartGold', 1); 
  iniconfiguration.Map := inifile.ReadString('Server', 'Map', 'GameMap'); 
  iniconfiguration.MapFileLoc := inifile.ReadString('Server', 'MapFileLoc', 
    'D:\mirserver\Map'); 
 
  iniconfiguration.DBServerIP := inifile.ReadString('Server', 'DatabaseServerIP', 
    '127.0.0.1'); 
  iniconfiguration.DBServerPort := inifile.ReadInteger('Server', 
    'DatabaseServerPort', 6000); 
 
  iniconfiguration.IDServerIP := inifile.ReadString('Server', 'IDServerIP', 
    '127.0.0.1'); 
  iniconfiguration.IDServerPort := inifile.ReadInteger('Server', 'IDServerPort', 
    5600); 
 
  iniconfiguration.SQLServerIP := inifile.ReadString('Server', 'SQLServerIP', 
    '127.0.0.1'); 
  iniconfiguration.SQLServerPort := inifile.ReadInteger('Server', 
    'SQLServerPort', 5100); 
  iniconfiguration.SQLServerDatabase := inifile.ReadString('Server', 
    'SQLServerDatebase', 'sqldatabase'); 
  iniconfiguration.SQLServerID := inifile.ReadString('Server', 'SQLServerID', 
    'User'); 
  iniconfiguration.SQLServerPassword := inifile.ReadString('Server', 
    'SQLServerPassword', 'password'); 
  inifile.Free; 
  inifile := TIniFile.Create('.\!SetUp.txt'); 
  Randomize; 
  MyMakeIndex := inifile.ReadInteger('setup', 'ItemNumber', 0) + Random(100); 
  inifile.Free; 
end; 
 
{保存配置文件} 
function TFormMain.SaveConfig(): Boolean; 
var 
  inifile: TIniFile; 
begin 
 
  inifile := TIniFile.Create('.\!SetUp.txt'); 
  inifile.WriteInteger('setup', 'ItemNumber', MyMakeIndex); 
  inifile.Free; 
end; 
 
procedure TFormMain.FormCreate(Sender: TObject); 
 
var 
  I: Integer; 
  pMapInfo: MAPINFO_RCD_ARRAY; 
begin 
  WOrdList := TStringHash.Create; 
  for I := 0 to High(Script_Command) do 
  begin 
    WOrdList.Add(Script_Command[I], I); 
  end; 
 
  MDlgPoints := TList.Create; 
  Myself := TUserInfo.Create; 
  ReadConfig(g_IniConfiguration); 
  // Myself.ScriptNpc('c:\npc.txt'); 
  Myself.m_THumanRcd.dwGold := 1000000; 
 
 
 
 
  InitGlobalVariable; 
  FormMain.Caption := g_IniConfiguration.ServerTitle; 
 
  g_fTerminated := False; 
  pMapInfo := InitDataInDatabase; 
  InitializingServer(pMapInfo); 
end; 
 
procedure TFormMain.BitBtnStopServiceClick(Sender: TObject); 
begin 
  g_fTerminated := True; 
  // UnInitAdminCommandList; 
end; 
 
 
{初始化服务器} 
function TFormMain.InitializingServer(pMapInfo: MAPINFO_RCD_ARRAY): Integer; 
var 
  I, 
    hFile: Integer; 
  szFullPath: string; 
  btInstalled: Byte; 
  pMyMapInfo: MAPINFO_RCD_ARRAY; 
begin 
  g_szGoldName := IDS_GOLD; 
 
  szFullPath := g_IniConfiguration.MapFileLoc + '\SearchTable.tbl'; 
 
  hFile := FileOpen(szFullPath, fmOpenRead); 
 
  if hFile > 0 then 
  begin 
    FileRead(hFile, g_SearchTable, SizeOf(g_SearchTable)); 
    FileClose(hFile); 
  end; 
 
  pMyMapInfo := pMapInfo; 
 
  for I := 0 to g_nNumOfMapInfo - 1 do 
  begin 
    LoadMap(@pMyMapInfo[I]); 
  end; 
 
  pMyMapInfo := nil; 
 
  InitAdminCommandList; 
 
  if not g_IniConfiguration.Installed then 
  begin 
    ShowMessage('Please Set the parameter first!'); 
  end; 
 
  ServerSocket1.Port := g_IniConfiguration.ServerPort; 
 
  ClientSocketDB.Host := g_IniConfiguration.DBServerIP; 
  ClientSocketDB.Port := g_IniConfiguration.DBServerPort; 
 
  ClientSocketID.Host := g_IniConfiguration.IDServerIP; 
  ClientSocketID.Port := g_IniConfiguration.IDServerPort; 
 
 
 
 
  TimerConnectServer.Enabled := True; 
 
  Result := 0; 
end; 
 
 
{初始化全局变量} 
procedure InitGlobalVariable; 
begin 
  g_xAdminCommandList := TStringList.Create; 
  g_xUserCommandList := TStringList.Create; 
 
  g_xEventList := TThreadList.Create; 
  g_xEventCloseList := TThreadList.Create; 
 
  g_xHolySeizeList := TThreadList.Create; 
 
 
  g_xReadyUserInfoList := TThreadList.Create; 
  g_xReadyUserInfoList2 := TThreadList.Create; 
  g_xMerchantObjList := TThreadList.Create; 
 
  g_fInitMerchant := False; 
  g_xNPCObjList := TThreadList.Create; 
  g_xReadyList := TThreadList.Create; 
 
  g_xGateList := TThreadList.Create; 
 
 
 
  // General Standard Data 
  g_xMirMapList := TThreadList.Create; 
  g_xScripterList := TThreadList.Create; 
 
 
 
 
  // SetLength(g_szRemainBuff, DATA_BUFSIZE); 
end; 
 
 
{释放全局变量} 
procedure FreeGlobalVariable; 
begin 
  if g_xAdminCommandList <> nil then 
  begin 
    FreeAndNil(g_xAdminCommandList); 
  end; 
 
  if g_xUserCommandList <> nil then 
  begin 
    FreeAndNil(g_xUserCommandList); 
  end; 
 
  if g_xEventList <> nil then 
  begin 
    FreeAndNil(g_xEventList); 
  end; 
 
  if g_xEventCloseList <> nil then 
  begin 
    FreeAndNil(g_xEventCloseList); 
  end; 
 
  if g_xHolySeizeList <> nil then 
  begin 
    FreeAndNil(g_xHolySeizeList); 
  end; 
 
 
 
  if g_xReadyUserInfoList <> nil then 
  begin 
    FreeAndNil(g_xReadyUserInfoList); 
  end; 
 
  if g_xReadyUserInfoList2 <> nil then 
  begin 
    FreeAndNil(g_xReadyUserInfoList2); 
  end; 
 
  if g_xMerchantObjList <> nil then 
  begin 
    FreeAndNil(g_xMerchantObjList); 
  end; 
 
  if g_xNPCObjList <> nil then 
  begin 
    FreeAndNil(g_xNPCObjList); 
  end; 
 
  if g_xReadyList <> nil then 
  begin 
    FreeAndNil(g_xReadyList); 
  end; 
 
  if g_xGateList <> nil then 
  begin 
    FreeAndNil(g_xGateList); 
  end; 
 
 
  // General Standard Data 
  if g_xMirMapList <> nil then 
  begin 
    FreeAndNil(g_xMirMapList); 
  end; 
 
  if g_xScripterList <> nil then 
  begin 
    FreeAndNil(g_xScripterList); 
  end; 
end; 
 
 
{初始化数据库信息} 
function TFormMain.InitDataInDatabase: MAPINFO_RCD_ARRAY; 
var 
  cu: PTCLIENTITEM; 
begin 
  InitMagicInfo; //初始化魔法 
  InsertLogMsg('初始化魔法'); 
 
 
 
  InitMonRaceInfo; 
  InsertLogMsg('加载怪物数据库'); 
 
  InitMonsterGenInfo; //初始化刷怪文件 
  InsertLogMsg('初始化刷怪文件'); 
 
  InitStdItemSpecial; 
  InsertLogMsg('加载物品数据库'); 
 
 
 
  InitMerchantInfo; 
  InsertLogMsg('初始化NPC'); 
 
  InitMoveMapEventInfo; 
  InsertLogMsg('初始化地图移动'); 
 
  Result := InitMapInfo(g_IniConfiguration.ServerNumber); 
  InsertLogMsg('加载地图文件'); 
 
  New(cu); 
  g_pStdItemSpecial[225].GetStandardItem(cu); 
  cu.MakeIndex := GetMakeIndex; 
  Myself.m_BagItems.Add(cu); 
 
end; 
 
{校正DBServer服务器} 
procedure TFormMain.TimerConnectServerTimer(Sender: TObject); 
begin 
 
  StartServer; 
 
  if not ClientSocketDB.Active then 
    ClientSocketDB.Active := True; 
  if not ClientSocketID.Active then 
    ClientSocketID.Active := True; 
  TimerMon.Enabled := True; 
  TimerNpc.Enabled := True; 
 
  { if not IdTCPClient.Connected then 
   begin 
     try 
       IdTCPClient.Connect(1000); 
     except 
     end; 
 
     if not IdTCPClient.Connected then 
     begin 
       InsertLogMsg('无法连接到数据库服务器'); 
     end 
     else 
     begin 
       InsertLogMsg('登陆数据库服务器成功'); 
       g_cSocket := IdTCPClient.Socket.Binding.Handle; 
       ConnectToServer; 
       StartServer; 
     end; 
   end; 
 
  if not IdTCPClientLog.Connected then 
   begin 
     try 
       IdTCPClientLog.Connect(1000); 
     except 
     end; 
 
     if not IdTCPClientLog.Connected then 
     begin 
       InsertLogMsg('无法连接到日志服务器'); 
     end 
     else 
     begin 
       InsertLogMsg('登陆日志服务器成功'); 
       g_clSocket  := IdTCPClient.Socket.Binding.Handle; 
     end; 
   end; 
   } 
  // if IdTCPClient.Connected and IdTCPClientLog.Connected then 
  begin 
    TimerConnectServer.Enabled := False; 
  end; 
end; 
 
 
 
 
procedure TFormMain.StartServer; 
begin 
  try 
  if Not ServerSocket1.Active then 
 
    ServerSocket1.Active := True; 
  //  InsertLogMsg('服务端'); 
  except 
  end; 
end; 
 
{添加日志信息} 
procedure TFormMain.InsertLogMsg(strMessage: string); 
var 
  CurrentTime: TSystemTime; 
  ItemString: string; 
  NewItem: TListItem; 
begin 
  memLogInfo.Lines.Add(strMessage); 
end; 
 
procedure TFormMain.IdTCPServerSocketConnect(AThread: TIdPeerThread); 
var 
  pGateInfo: TGateInfo; 
  SessionIndex: Integer; 
begin 
 
end; 
 
procedure TFormMain.ServerSocket1ClientConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  I: Integer; 
begin 
  Socket.nIndex := -1; 
  for I := 0 to 49 do 
  begin 
    if GateInfo[I].Socket = nil then 
    begin 
      GateInfo[I].Socket := Socket; 
      GateInfo[I].m_Socket := Socket.Handle; 
      GateInfo[I].sSocData := ''; 
      GateInfo[I].PeerIP := Socket.RemoteAddress; 
      GateInfo[I].m_nIndex := I; 
      Socket.nIndex := I; 
      InsertLogMsg('Gate' + IntToStr(I) + '打开'); 
      Exit; 
    end; 
 
  end; 
  
end; 
 
procedure TFormMain.ServerSocket1ClientError(Sender: TObject; 
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
  var ErrorCode: Integer); 
begin 
  ErrorCode := 0; 
end; 
 
procedure TFormMain.ServerSocket1ClientRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  nSocketIndex: Integer; 
  UserData: pTSendUserData; 
  sReviceMsg: string; 
  nReviceLen: Integer; 
begin 
  nSocketIndex := Socket.nIndex; 
  sReviceMsg := Socket.ReceiveText; //接收到的数据 
  nReviceLen := Length(sReviceMsg); 
  if (nSocketIndex >= 0) and (nSocketIndex < 50) and (sReviceMsg <> '') then 
  begin 
    New(UserData); 
    UserData.nSocketIndx := nSocketIndex; //把接收的数据添加到UserData对象中 
    UserData.nSocketHandle := Socket.SocketHandle; 
    UserData.sMsg := sReviceMsg; 
    ReviceMsgList.Add(UserData); 
  end; 
end; 
 
{处理用户数据包} 
procedure TFormMain.ProcessUserPacket(UserData: pTSendUserData); 
var 
  sMsg, Str: string; 
  pMsg: PMSGHEADER_RCD; 
  nLen: Integer; 
  MsgBuff: PChar; 
  nIndex: Integer; 
  pUserInfo: TUserInfo; 
  I: Integer; 
begin 
 
  try 
    if (UserData.nSocketIndx >= 0) and (UserData.nSocketIndx < 50) then 
    begin 
      nIndex := UserData.nSocketIndx; 
      sMsg := GateInfo[UserData.nSocketIndx].sSocData + UserData.sMsg; 
      nLen := Length(sMsg); 
      GetMem(MsgBuff, nLen); 
      MsgBuff := PChar(sMsg); 
      while nLen > 19 do 
      begin 
        pMsg := PMSGHEADER_RCD(MsgBuff); 
        if pMsg.nCode <> $AA55AA55 then 
        begin 
          Inc(MsgBuff); 
          Dec(nLen); 
        end 
        else 
        begin 
          case pMsg^.wIdent of // 
            GM_OPEN: 
              begin 
                GateInfo[nIndex].OpenNewUser((MsgBuff)); 
              end; 
            GM_CLOSE: //玩家退出 
              begin 
                pUserInfo := g_xUserInfoArr[pMsg^.wUserListIndex]; 
                Dec(HumCOunt); 
 
                if pUserInfo <> nil then 
                begin 
                  if pMsg.nSocket <> pUserInfo.m_Socket then 
                  begin 
                    pUserInfo := nil; 
                    for I := 0 to 4999 do 
                    begin 
                      if g_xUserInfoArr[I] <> nil then 
                        if g_xUserInfoArr[I].m_Socket = pMsg.nSocket then 
                        begin 
                          pUserInfo := g_xUserInfoArr[I]; 
                          Break; 
                        end; 
                    end; 
                  end; 
                end; 
                if pUserInfo = nil then 
                  Break; 
                if pUserInfo <> nil then 
                begin 
                  if pUserInfo.m_bEmpty then 
                    Break; 
 
                  pUserInfo.CloseUserHuman(26); 
                  pUserInfo.CloseAccount(pUserInfo.m_szUserID, 
                    pUserInfo.m_nCertification); 
                  for I := 0 to pUserInfo.m_BagItems.COunt - 1 do 
                    Dispose(pUserInfo.m_BagItems.items[I]); 
                  pUserInfo.m_BagItems.Clear; 
                  pUserInfo.m_lpTMagicRcd.Clear; 
                  pUserInfo.m_TakeItemsCount := 0; 
                  g_xPlayerObjectArr[TPlayerObject(pUserInfo.m_pxPlayerObject).m_nArrIndex].m_bEmpty := True; 
 
 
                  g_xUserInfoArr[pMsg^.wUserListIndex].m_bEmpty := True; 
 
                end; 
              end; 
            GM_CHECKCLIENT: 
              begin 
                GateInfo[nIndex].SendGateCheck; 
              end; 
            GM_RECEIVE_OK: 
              begin 
                // do nothing Now 
              end; 
            GM_Data: 
              begin 
                pUserInfo := g_xUserInfoArr[pMsg^.wUserListIndex]; 
 
                if pUserInfo <> nil then 
                begin 
                  if pMsg.nSocket <> pUserInfo.m_Socket then 
                  begin 
                    pUserInfo := nil; 
                    for I := 0 to 4999 do 
                    begin 
                      if g_xUserInfoArr[I] <> nil then 
                        if g_xUserInfoArr[I].m_Socket = pMsg.nSocket then 
                        begin 
                          pUserInfo := g_xUserInfoArr[I]; 
                          Break; 
                        end; 
                    end; 
                  end; 
                  if pUserInfo = nil then 
                    Break; 
 
                  if pUserInfo.m_btCurrentMode = USERMODE_PLAYGAME then 
                  begin 
                    if pMsg.nSocket = pUserInfo.m_Socket then 
                      pUserInfo.ProcessUserMessage((MsgBuff + 
                        SizeOf(TMSGHEADER_RCD)), pMsg^.nLength); 
                  end 
                  else 
                  begin 
                    pUserInfo.DoClientCertification(string(MsgBuff + 
                      SizeOf(TMSGHEADER_RCD))); 
                  end; 
 
                end; 
 
              end; 
 
          end; 
        end; 
        MsgBuff := MsgBuff + abs(pMsg.nLength) + 20; 
        nLen := nLen - (abs(pMsg.nLength) + 20); 
 
      end; 
      GateInfo[UserData.nSocketIndx].sSocData := string(MsgBuff); 
    end; 
  except 
  end; 
end; 
 
procedure TFormMain.DecodeTimerTimer(Sender: TObject); 
var 
  dwLoopProcessTime, dwProcessReviceMsgLimiTick: LongWord; 
  UserData: pTSendUserData; 
  I: Integer; 
  tUserData: TSendUserData; 
begin 
  try 
    dwProcessReviceMsgLimiTick := GetTickCount(); 
    while (True) do 
    begin 
      if ReviceMsgList.COunt <= 0 then 
        Break; 
      UserData := ReviceMsgList.items[0]; 
      ReviceMsgList.Delete(0); 
      ProcessUserPacket(UserData); //处理用户数据 
      Dispose(UserData); 
      if (GetTickCount - dwProcessReviceMsgLimiTick) > 80 then 
        Break; 
    end; 
  except 
    on E: Exception do 
    begin 
 
    end; 
  end; 
end; 
 
procedure TFormMain.ClientSocketDBRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  s: string; 
begin 
  s := Socket.ReceiveText; 
  g_szTempBuffer := g_szTempBuffer + s; 
  ProcReceiveBufferDB; 
end; 
 
procedure TFormMain.ClientSocketDBError(Sender: TObject; 
  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; 
  var ErrorCode: Integer); 
begin 
  ErrorCode := 0; 
  StatusBar1.Panels[1].text:='DB Error'; 
end; 
 
procedure TFormMain.Timer1Timer(Sender: TObject); 
const 
  LoginBuf: array[0..17] of Byte = ($28, $31, $30, $33, $2F, $C0, $D6, $B6, $BC, 
    $B4, $AB, $C6, $E6, $2F, $30, $2F, $30, $29); 
 
begin 
  LoginBuf[16] := $30 + HumCOunt; 
  if ClientSocketID.Active then 
    ClientSocketID.Socket.SendBuf(LoginBuf, 18); 
 
   StatusBar1.Panels[0].Text:=Format('网关数:%d',[ServerSocket1.Socket.ActiveConnections]); 
    
 
end; 
 
procedure TFormMain.ClientSocketIDRead(Sender: TObject; 
  Socket: TCustomWinSocket); 
var 
  s: string; 
begin 
  s := Socket.ReceiveText; 
  InsertLogMsg(s); 
 
end; 
 
procedure TFormMain.TimerHumTimer(Sender: TObject); 
var 
  I: Integer; 
  pUserInfo: TUserInfo; 
begin 
  for I := 0 to 4999 do //Iterate 
  begin 
    pUserInfo := g_xUserInfoArr[I]; 
    if pUserInfo <> nil then 
    begin 
 
      if (pUserInfo.m_btCurrentMode = USERMODE_PLAYGAME) and (not 
        pUserInfo.m_bEmpty) then 
      begin 
        pUserInfo.Operate; 
      end; 
    end; 
    //Delete(I); 
  end; 
 
 
end; 
 
 
{处理怪物操作} 
procedure TFormMain.TimerMonTimer(Sender: TObject); 
{begin 
      if mon<>nil then 
      Begin 
         mon.SearchViewRange; 
         mon.Operate; 
      End; 
end; 
} 
var 
  I, 
    N, 
 
  dwCurrentTick, 
    dwLastGenTick: LongWord; 
  pMonGenInfo: PMONSTERGENINFO_RCD; 
  pMonsterObject: TMonsterObject; 
  nCount: Integer; 
 
begin 
 
  //  if Busy then exit; 
  Busy := True; 
 
 
  begin 
    //Generate Monster 
    if (GetTickCount - dwLastGenTick) > 1000 then 
    begin 
      if nCurrMonGen < (g_nNumOfMonGenInfo - 2) then 
      begin 
        Inc(nCurrMonGen); 
      end 
      else 
      begin 
        nCurrMonGen := 0; 
      end; 
      if nCurrMonGen < 0 then 
        nCurrMonGen := 0; 
 
      pMonGenInfo := @g_pMonGenInfo[nCurrMonGen]; 
 
      if pMonGenInfo <> nil then 
      begin 
        if (pMonGenInfo^.dwStartTime = 0) or ((dwLastGenTick - 
          pMonGenInfo^.dwStartTime) > GetZenTime(pMonGenInfo^.dwZenTime)) then 
        begin 
          nCount := pMonGenInfo^.xMonsterObjList.LockList.COunt; 
          if pMonGenInfo^.nCount > nCount then 
          begin 
            if RegenMonster(pMonGenInfo, pMonGenInfo^.nCount - nCount) then 
            begin 
              // InsertLogMsg('刷怪  '+pMonGenInfo^.szMonName+'  '+inttostr(pMonGenInfo^.nCount - nCOunt)); 
              Label1.Caption := IntToStr(MonCount) + '   ' + 
                pMonGenInfo^.szMonName + '  ' + IntToStr(pMonGenInfo^.nCount - 
                nCount); 
              pMonGenInfo^.dwStartTime := GetTickCount; 
            end; 
          end; 
          pMonGenInfo^.xMonsterObjList.UnlockList; 
        end; 
      end; 
    end; 
 
    // Execute Monster A.I   g_nNumOfMonGenInfo 
 
    dwCurrentTick := GetTickCount; 
    dwLastGenTick := GetTickCount; 
     //Label2.Caption:=Inttostr(RunMongen); 
    for I := 0 {RunMonGen} to g_nNumOfMonGenInfo - 1 do 
    begin 
      // if (GetTickCount -dwLastGenTick)>30 then Break; 
       //Inc(RunMonGen); 
       //if RunMonGen>(g_nNumOfMonGenInfo-1) then RunMonGen:=0; 
      {if i > 2680 then 
        MyDebugFile.AddMyDebugFile(IntToStr(i));   } 
 
      pMonGenInfo := @g_pMonGenInfo[I]; 
      if pMonGenInfo <> nil then 
      begin 
        with pMonGenInfo^.xMonsterObjList.LockList do 
        begin 
          if COunt = 0 then 
            Continue; 
          for N := COunt - 1 downto 0 do //Iterate 
          begin 
            pMonsterObject := items[N]; 
 
            if pMonsterObject <> nil then 
            begin 
              {if (pMonsterObject.m_szName = '半兽人') and (n = 51) then 
               Sleep(10);} 
              if TMirMap(pMonsterObject.m_pMap).m_HumCount = 0 then //当前地图人物数量 
                Break; 
              dwCurrentTick := GetTickCount; 
              if not pMonsterObject.m_fIsGhost then 
              begin 
                if (dwCurrentTick - pMonsterObject.m_dwRunTime) >= 
                  pMonsterObject.m_dwRunNextTick then 
                begin 
                  pMonsterObject.m_dwRunTime := dwCurrentTick; 
 
                  if (dwCurrentTick - pMonsterObject.m_dwSearchTime) >= 
                    pMonsterObject.m_dwSearchTick then 
                  begin 
                    pMonsterObject.m_dwSearchTime := dwCurrentTick; 
                    pMonsterObject.SearchViewRange; 
                  end; 
 
                  pMonsterObject.Operate; 
                end; 
              end 
              else 
              begin 
                if (GetTickCount - pMonsterObject.m_dwGhostTime) > 3 * 60 * 1000 
                  then 
                begin 
                  FreeAndNil(pMonsterObject); 
                  Delete(N); 
                  Continue; 
                end; 
              end; 
            end; 
          end; //for 
        end; // with 
        pMonGenInfo^.xMonsterObjList.UnlockList; 
        //Label2.Caption:=Inttostr(RunMongen); 
      end; // if (pMonGenInfo) 
    end; 
 
 
  end; 
  Busy := False; 
 
 
end; 
 
procedure TFormMain.FormClose(Sender: TObject; var Action: TCloseAction); 
begin 
  SaveConfig; 
end; 
 
procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
begin 
  if MessageDlg('是否确认退出服务器?', mtConfirmation, [mbYes, mbNo], 0) = mrYes 
    then 
    SaveConfig 
  else 
    CanClose := False; 
end; 
 
{处理NPC} 
procedure TFormMain.TimerNpcTimer(Sender: TObject); 
var 
  I: Integer; 
  dwCurrentTick: LongWord; 
  pMap: TMirMap; 
  pMerchantObject: TMerchantObject; 
begin 
  dwCurrentTick := GetTickCount; 
 
  if not g_fInitMerchant then 
  begin 
    for I := 0 to g_nNumOfMerchantInfo - 1 do 
    begin 
      pMap := GetMap(g_pMerchantInfo[I].szMapName); 
 
      if pMap <> nil then 
      begin 
        pMerchantObject := TMerchantObject.Create; 
        pMerchantObject.m_wObjectType := _OBJECT_NPC; 
        pMerchantObject.m_nIndex := I; 
        //  pMerchantObject.m_tFeature.btGender := 2; 
        // pMerchantObject.m_tFeature.btWear   := Byte(g_pMerchantInfo[I].sBody); 
        pMerchantObject.m_nCurrX := g_pMerchantInfo[I].nPosX; 
        pMerchantObject.m_nCurrY := g_pMerchantInfo[I].nPosY; 
        pMerchantObject.m_nDirection := g_pMerchantInfo[I].sFace; 
        pMerchantObject.m_pMap := pMap; 
        pMerchantObject.m_tFeature.btGender := 50; 
        pMerchantObject.m_tFeature.btHair := g_pMerchantInfo[I].sBody; 
        pMerchantObject.m_szName := g_pMerchantInfo[I].szNPCName; 
 
        pMerchantObject.ScriptNpc('.\Envir\Market_Def\' + 
          g_pMerchantInfo[I].idStr + '-' + g_pMerchantInfo[I].szMapName + '.txt'); 
 
        TMirMap(pMerchantObject.m_pMap).AddNewObject(pMerchantObject.m_nCurrX, 
          pMerchantObject.m_nCurrY, OS_MOVINGOBJECT, pMerchantObject); 
        g_xMerchantObjList.Add(pMerchantObject); 
      end; 
    end; 
    g_fInitMerchant := True; 
  end; 
 
  with g_xMerchantObjList.LockList do 
  begin 
    for I := 0 to COunt - 1 do // Iterate 
    begin 
      pMerchantObject := items[I]; 
 
      if (dwCurrentTick - pMerchantObject.m_dwRunTime) >= 
        pMerchantObject.m_dwRunNextTick then 
      begin 
        pMerchantObject.m_dwRunTime := dwCurrentTick; 
 
        if (dwCurrentTick - pMerchantObject.m_dwSearchTime) >= 
          pMerchantObject.m_dwSearchTick then 
        begin 
          pMerchantObject.m_dwSearchTime := dwCurrentTick; 
          pMerchantObject.SearchViewRange; 
        end; 
 
        pMerchantObject.RunRace; 
      end; 
    end; // for 
  end; // with 
  g_xMerchantObjList.UnlockList; 
  TimerNpc.Enabled := False; 
end; 
 
procedure TFormMain.ClientSocketDBConnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
   StatusBar1.Panels[1].Text:='DB OK'; 
end; 
 
procedure TFormMain.ClientSocketDBDisconnect(Sender: TObject; 
  Socket: TCustomWinSocket); 
begin 
StatusBar1.Panels[1].text:='DB DisConnect'; 
end; 
 
end.