C++ implementation of the distributed game server engine KBEngine

  • 2020-04-02 03:00:16
  • OfStack

KBEngine is an open source game server engine that USES simple conventions to enable clients to interact with servers.
The KBEngine plug-in can be quickly combined with (Unity3D, OGRE, Cocos2d, HTML5, etc.) technologies to form a complete client.

The underlying framework of the server side is written in c++, and the game logic layer is written in Python(support for hot update). Developers do not need to repeatedly implement some common underlying technologies of the game server side.
Will concentrate on the game development level, quickly create a variety of network games.

(often asked about load limits, the kbengine underlying architecture is designed to be a multi-process distributed dynamic load balancing scheme,
In theory, you only need to expand the hardware to increase the load limit. The load limit of a single machine depends on the complexity of the game logic itself.

Cstdkbe. HPP


/*
This source file is part of KBEngine
For the latest info, see http://www.kbengine.org/
 
Copyright (c) 2008-2012 KBEngine.
 
KBEngine is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
 
KBEngine 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 Lesser General Public License for more details.
 
You should have received a copy of the GNU Lesser General Public License
along with KBEngine. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KBE_CSTDKBE_HPP
#define KBE_CSTDKBE_HPP
#include "cstdkbe/platform.hpp"
#include "cstdkbe/singleton.hpp"
#include "cstdkbe/kbeversion.hpp"
#include "cstdkbe/kbemalloc.hpp"
#include "cstdkbe/stringconv.hpp"
#include "cstdkbe/format.hpp"
 
namespace KBEngine{

#define SAFE_RELEASE(i)                   
  if (i)                         
    {                          
      delete i;                    
      i = NULL;                    
    }
 

#define SAFE_RELEASE_ARRAY(i)                
  if (i)                         
    {                          
      delete[] i;                   
      i = NULL;                    
    }
 
#ifdef CODE_INLINE
  #define INLINE  inline
#else
  #define INLINE
#endif
 

extern GAME_TIME g_kbetime;
 

enum ACCOUNT_TYPE
{
  ACCOUNT_TYPE_NORMAL = 1,  //Ordinary account
  ACCOUNT_TYPE_MAIL = 2,   //Email account (to be activated)
  ACCOUNT_TYPE_SMART = 3   //Intelligent identification
};
 
enum ACCOUNT_FLAGS
{
  ACCOUNT_FLAG_NORMAL = 0x00000000,
  ACCOUNT_FLAG_LOCK = 0x000000001,
  ACCOUNT_FLAG_NOT_ACTIVATED = 0x000000002
};
 

enum ENTITY_MAILBOX_TYPE
{
  MAILBOX_TYPE_CELL                        = 0,
  MAILBOX_TYPE_BASE                        = 1,
  MAILBOX_TYPE_CLIENT                       = 2,
  MAILBOX_TYPE_CELL_VIA_BASE                   = 3,
  MAILBOX_TYPE_BASE_VIA_CELL                   = 4,
  MAILBOX_TYPE_CLIENT_VIA_CELL                  = 5,
  MAILBOX_TYPE_CLIENT_VIA_BASE                  = 6,
};
 

const char ENTITY_MAILBOX_TYPE_TO_NAME_TABLE[][8] = 
{
  "cell",
  "base",
  "client",
  "cell",
  "base",
  "client",
  "client",
};
 

enum COMPONENT_TYPE
{
  UNKNOWN_COMPONENT_TYPE = 0,
  DBMGR_TYPE       = 1,
  LOGINAPP_TYPE      = 2,
  BASEAPPMGR_TYPE     = 3,
  CELLAPPMGR_TYPE     = 4,
  CELLAPP_TYPE      = 5,
  BASEAPP_TYPE      = 6,
  CLIENT_TYPE       = 7,
  MACHINE_TYPE      = 8,
  CONSOLE_TYPE      = 9,
  MESSAGELOG_TYPE     = 10,
  BOTS_TYPE        = 11,
  WATCHER_TYPE      = 12,
  BILLING_TYPE      = 13,
  COMPONENT_END_TYPE   = 14,
};
 

extern COMPONENT_TYPE g_componentType;
extern COMPONENT_ID g_componentID;
 

const char COMPONENT_NAME[][255] = {
  "unknown",
  "dbmgr",
  "loginapp",
  "baseappmgr",
  "cellappmgr",
  "cellapp",
  "baseapp",
  "client",
  "kbmachine",
  "console",
  "messagelog",
  "bots",
  "watcher",
  "billing",
};
 
const char COMPONENT_NAME_1[][255] = {
  "unknown  ",
  "dbmgr   ",
  "loginapp  ",
  "baseappmgr ",
  "cellappmgr ",
  "cellapp  ",
  "baseapp  ",
  "client   ",
  "kbmachine ",
  "console  ",
  "messagelog ",
  "bots",
  "watcher",
  "billing",
};
 
inline const char* COMPONENT_NAME_EX(COMPONENT_TYPE CTYPE)
{                  
  if(CTYPE < 0 || CTYPE >= COMPONENT_END_TYPE)
  {
    return COMPONENT_NAME[UNKNOWN_COMPONENT_TYPE];
  }
 
  return COMPONENT_NAME[CTYPE];
}
 
inline const char* COMPONENT_NAME_EX_1(COMPONENT_TYPE CTYPE)
{                  
  if(CTYPE < 0 || CTYPE >= COMPONENT_END_TYPE)
  {
    return COMPONENT_NAME_1[UNKNOWN_COMPONENT_TYPE];
  }
 
  return COMPONENT_NAME_1[CTYPE];
}
 
inline COMPONENT_TYPE ComponentName2ComponentType(const char* name)
{
  for(int i=0; i<(int)COMPONENT_END_TYPE; i++)
  {
    if(kbe_stricmp(COMPONENT_NAME[i], name) == 0)
      return (COMPONENT_TYPE)i;
  }
 
  return UNKNOWN_COMPONENT_TYPE;
}
 
//List of all components
const COMPONENT_TYPE ALL_COMPONENT_TYPES[] = {BASEAPPMGR_TYPE, CELLAPPMGR_TYPE, DBMGR_TYPE, CELLAPP_TYPE, 
            BASEAPP_TYPE, LOGINAPP_TYPE, MACHINE_TYPE, CONSOLE_TYPE, MESSAGELOG_TYPE, 
            WATCHER_TYPE, BILLING_TYPE, BOTS_TYPE, UNKNOWN_COMPONENT_TYPE};
 
//List of all back-end components
const COMPONENT_TYPE ALL_SERVER_COMPONENT_TYPES[] = {BASEAPPMGR_TYPE, CELLAPPMGR_TYPE, DBMGR_TYPE, CELLAPP_TYPE, 
            BASEAPP_TYPE, LOGINAPP_TYPE, MACHINE_TYPE, MESSAGELOG_TYPE, 
            WATCHER_TYPE, BILLING_TYPE, BOTS_TYPE, UNKNOWN_COMPONENT_TYPE};
 
//List of all back-end components
const COMPONENT_TYPE ALL_GAME_SERVER_COMPONENT_TYPES[] = {BASEAPPMGR_TYPE, CELLAPPMGR_TYPE, DBMGR_TYPE, CELLAPP_TYPE, 
            BASEAPP_TYPE, LOGINAPP_TYPE, BILLING_TYPE, UNKNOWN_COMPONENT_TYPE};
 
//All auxiliary components
const COMPONENT_TYPE ALL_HELPER_COMPONENT_TYPE[] = {MESSAGELOG_TYPE, UNKNOWN_COMPONENT_TYPE};
 
//Returns whether it is a valid component
#define VALID_COMPONENT(C_TYPE) ((C_TYPE) > 0 && (C_TYPE) < COMPONENT_END_TYPE)
 
 
//The category of front-end applications, All client type
enum COMPONENT_CLIENT_TYPE
{
  UNKNOWN_CLIENT_COMPONENT_TYPE  = 0,
 
  //Mobile, mobile, tablet
  // Mobile, Phone, Pad(Allowing does not contain Python-scripts and entitydefs analysis, can be imported protocol from network)
  CLIENT_TYPE_MOBILE       = 1,
 
  //Standalone Windows/Linux/Mac applications (including python scripts, entitydefs parses and checks MD5 of entitydefs, native)
  // Windows/Linux/Mac Application program (Contains the Python-scripts, entitydefs parsing and check entitydefs-MD5, Native)
  CLIENT_TYPE_PC         = 2,  
 
  //Without Python scripts, the entitydefs protocol USES network imports
  // Web, HTML5, Flash
  CLIENT_TYPE_BROWSER       = 3,  
 
  //Contains Python script, entitydefs parsing and checking entitydefs MD5, native
  // bots (Contains the Python-scripts, entitydefs parsing and check entitydefs-MD5, Native)
  CLIENT_TYPE_BOTS        = 4,  
 
  //Lightweight classes that do not contain python scripts, entitydefs protocol can be imported using the network
  // Mini-Client(Allowing does not contain Python-scripts and entitydefs analysis, can be imported protocol from network)
  CLIENT_TYPE_MINI        = 5,  
 
  // End
  CLIENT_TYPE_END         = 6   
};
 

const char COMPONENT_CLIENT_NAME[][255] = {
  "UNKNOWN_CLIENT_COMPONENT_TYPE",
  "CLIENT_TYPE_MOBILE",
  "CLIENT_TYPE_PC",
  "CLIENT_TYPE_BROWSER",
  "CLIENT_TYPE_BOTS",
  "CLIENT_TYPE_MINI",
};
 
//Categories for all front-end applications
const COMPONENT_CLIENT_TYPE ALL_CLIENT_TYPES[] = {CLIENT_TYPE_MOBILE, CLIENT_TYPE_PC, CLIENT_TYPE_BROWSER, 
                        CLIENT_TYPE_BOTS, CLIENT_TYPE_MINI, UNKNOWN_CLIENT_COMPONENT_TYPE};
 
typedef int8 CLIENT_CTYPE;
 
//Whether the front end supports floating point Numbers
// #define CLIENT_NO_FLOAT
 
//The default boundary or minimum size of a cell
#define CELL_DEF_MIN_AREA_SIZE       500.0f
 

#define SPACE_CHUNK_SIZE          100
 
 

inline bool validName(const char* name, int size)
{
  if(size >= 256)
    return false;
 
  for(int i=0; i<size; i++)
  {
    char ch = name[i];
    if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || (ch == '_'))
      continue;
 
    return false;
  }
 
  return true;
}
 
inline bool validName(const std::string& name)
{
  return validName(name.c_str(), name.size());
}
 
/**  check email Address validity  
 For a strict match, use the following expression 
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
*/
#ifdef USE_REGEX
#include <regex>
#endif
 
inline bool email_isvalid(const char *address) 
{
#ifdef USE_REGEX
  std::tr1::regex _mail_pattern("([a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)");
  return std::tr1::regex_match(accountName, _mail_pattern);
#endif
  int len = strlen(address);
  if(len <= 3)
    return false;
 
  char ch = address[len - 1];
  if(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')))
    return false;
 
  int    count = 0;
  const char *c, *domain;
  static const char *rfc822_specials = "()<>@,;:\"[]";
 
  
  for (c = address; *c; c++) {
  if (*c == '"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
    '"')) {
   while (*++c) {
    if (*c == '"') break;
    if (*c == '\' && (*++c == ' ')) continue;
    if (*c <= ' ' || *c >= 127) return false;
   }
   if (!*c++) return false;
   if (*c == '@') break;
   if (*c != '.') return false;
   continue;
  }
  if (*c == '@') break;
  if (*c <= ' ' || *c >= 127) return false;
  if (strchr(rfc822_specials, *c)) return false;
  }
  if (c == address || *(c - 1) == '.') return false;
 
  
  if (!*(domain = ++c)) return false;
  do {
  if (*c == '.') {
   if (c == domain || *(c - 1) == '.') return false;
   count++;
  }
  if (*c <= ' ' || *c >= 127) return false;
  if (strchr(rfc822_specials, *c)) return false;
  } while (*++c);
 
  return (count >= 1);
}
 
}
#endif // KBE_CSTDKBE_HPP

The above is the entire content of this article, there is a need for the companion can refer to the next.


Related articles: