Add missing binaries

This commit is contained in:
halx99 2022-10-02 17:07:39 +08:00
parent d2d2005027
commit 2eea90545d
6 changed files with 2323 additions and 0 deletions

18
tools/console/bin/axmol Normal file
View File

@ -0,0 +1,18 @@
#!/bin/bash -l
AXMOL_CONSOLE_BIN_DIRECTORY=$(dirname "$0")
AXMOL_CONSOLE_BIN_DIRECTORY=$(cd "$AXMOL_CONSOLE_BIN_DIRECTORY" && pwd -P)
if hash python3 2>/dev/null; then
PYTHON=python3
elif hash python2 2>/dev/null; then
PYTHON=python2
elif hash python 2>/dev/null; then
PYTHON=python
else
echo "Python 2+ required."
exit 1
fi
$PYTHON "$AXMOL_CONSOLE_BIN_DIRECTORY/axmol.py" "$@"

View File

@ -0,0 +1,4 @@
@echo off
rem Ensure vswhere installed for cmdline tool could find vs2017+
pip install vswhere
python "%~dp0/axmol.py" %*

View File

@ -0,0 +1,55 @@
#
# axmol command line tool configuration file
#
[global]
# there are 3 modes
# "source", which means that the cocos2d-x source code is being used for "new" and other plugins.
# "precompiled", which means that cocos2d-x precompiled libraries and headers will be used for "new" and other plugins
# "distro", which means that cocos2d-x precompiled libraries and headers won't be copied when using "new" and other plugins
# Default: source. Distros and other installers must override this setting
cocos2d_x_mode=source
# Enable/Disable the data statistics
# If the value is 'false' or 'no', statistics is disabled.
# Otherwise, it's enabled.
enable_stat=false
[plugins]
# What are the plugins that must be enabled
plugin_new.CCPluginNew
plugin_compile.CCPluginCompile
plugin_run.CCPluginRun
plugin_deploy.CCPluginDeploy
plugin_luacompile.CCPluginLuaCompile
# plugin_generate.LibsCompiler
plugin_generate.SimulatorCompiler
#plugin_generate.TemplateGenerator
; plugin_package.CCPluginPackage
#plugin_gui.CCPluginGUI
#plugin_version.CCPluginVersion
#plugin_install.CCPluginInstall
#plugin_update.CCPluginUpdate
#plugin_clean.CCPluginClean
#plugin_dist.CCPluginDist
#plugin_test.CCPluginTest
# To add a new plugin add it's classname here
[paths]
# where cocos2d-x is installed
# example: /usr/local/axmol
# eg: this file must exist: /usr/local/axmol/core/axmol.h
# Default: empty. Installers will populate it
cocos2d_x=
# where are the cocos2d-x's templates installed
# example: /home/user/templates
# eg: this directory must exist: /home/user/templates/cpp-template-default
# Default: empty. Installers will populate it
templates=
# where are the plugins installed
# but distros can override this directory
# Default: ../plugins. Installers can replace it if needed
plugins=../plugins

1162
tools/console/bin/axmol.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,515 @@
import os
import re
import json
import axmol
from MultiLanguage import MultiLanguage
class Project(object):
CPP = 'cpp'
LUA = 'lua'
JS = 'js'
CONFIG = '.axproj.json'
KEY_PROJ_TYPE = 'project_type'
KEY_HAS_NATIVE = 'has_native'
KEY_CUSTOM_STEP_SCRIPT = "custom_step_script"
KEY_ENGINE_VERSION = "engine_version"
CUSTOM_STEP_PRE_BUILD = "pre-build"
CUSTOM_STEP_POST_BUILD = "post-build"
CUSTOM_STEP_PRE_NDK_BUILD = "pre-ndk-build"
CUSTOM_STEP_POST_NDK_BUILD = "post-ndk-build"
CUSTOM_STEP_PRE_COPY_ASSETS = "pre-copy-assets"
CUSTOM_STEP_POST_COPY_ASSETS = "post-copy-assets"
CUSTOM_STEP_PRE_ANT_BUILD = "pre-ant-build"
CUSTOM_STEP_POST_ANT_BUILD = "post-ant-build"
@staticmethod
def list_for_display():
return [x.lower() for x in Project.language_list()]
@staticmethod
def language_list():
return (Project.CPP, Project.LUA, Project.JS)
def __init__(self, project_dir):
# parse the config file
self.info = self._parse_project_json(project_dir)
def _parse_project_json(self, src_dir):
proj_path = self._find_project_dir(src_dir)
# config file is not found
if proj_path == None:
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_CFG_NOT_FOUND_FMT',
os.path.join(src_dir, Project.CONFIG)),
axmol.CCPluginError.ERROR_PATH_NOT_FOUND)
project_json = os.path.join(proj_path, Project.CONFIG)
try:
f = open(project_json)
project_info = json.load(f)
f.close()
except Exception:
if f is not None:
f.close()
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_CFG_BROKEN_FMT',
project_json),
axmol.CCPluginError.ERROR_PARSE_FILE)
if project_info is None:
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_CFG_PARSE_FAILED_FMT',
Project.CONFIG), axmol.CCPluginError.ERROR_PARSE_FILE)
if not axmol.dict_contains(project_info, Project.KEY_PROJ_TYPE):
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_CFG_GET_VALUE_FAILED_FMT',
(Project.KEY_PROJ_TYPE, Project.CONFIG)),
axmol.CCPluginError.ERROR_WRONG_CONFIG)
lang = project_info[Project.KEY_PROJ_TYPE]
lang = lang.lower()
# The config is invalid
if not (lang in Project.language_list()):
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_CFG_INVALID_LANG_FMT',
(Project.KEY_PROJ_TYPE, ', '.join(Project.list_for_display()))),
axmol.CCPluginError.ERROR_WRONG_CONFIG)
# record the dir & language of the project
self._project_dir = proj_path
self._project_lang = lang
# if is script project, record whether it has native or not
self._has_native = False
if (self._is_script_project() and axmol.dict_contains(project_info, Project.KEY_HAS_NATIVE)):
self._has_native = project_info[Project.KEY_HAS_NATIVE]
# if has custom step script, record it
self._custom_step = None
if (axmol.dict_contains(project_info, Project.KEY_CUSTOM_STEP_SCRIPT)):
script_path = project_info[Project.KEY_CUSTOM_STEP_SCRIPT]
if not os.path.isabs(script_path):
script_path = os.path.join(self._project_dir, script_path)
if os.path.isfile(script_path):
import sys
script_dir, script_name = os.path.split(script_path)
sys.path.append(script_dir)
self._custom_step = __import__(os.path.splitext(script_name)[0])
axmol.Logging.info(MultiLanguage.get_string('PROJECT_INFO_FOUND_CUSTOM_STEP_FMT', script_path))
else:
axmol.Logging.warning(MultiLanguage.get_string('PROJECT_WARNING_CUSTOM_SCRIPT_NOT_FOUND_FMT',
script_path))
self._custom_step = None
return project_info
def invoke_custom_step_script(self, event, tp, args):
try:
if self._custom_step is not None:
self._custom_step.handle_event(event, tp, args)
except Exception as e:
axmol.Logging.warning(MultiLanguage.get_string('PROJECT_WARNING_CUSTOM_STEP_FAILED_FMT', e))
raise e
def _find_project_dir(self, start_path):
path = start_path
while True:
if axmol.os_is_win32():
# windows root path, eg. c:\
if re.match(".+:\\\\$", path):
break
else:
# unix like use '/' as root path
if path == '/' :
break
cfg_path = os.path.join(path, Project.CONFIG)
if (os.path.exists(cfg_path) and os.path.isfile(cfg_path)):
return path
path = os.path.dirname(path)
return None
def get_proj_config(self, key):
project_json = os.path.join(self._project_dir, Project.CONFIG)
f = open(project_json)
project_info = json.load(f)
f.close()
ret = None
if axmol.dict_contains(project_info, key):
ret = project_info[key]
return ret
def write_proj_config(self, key, value):
project_json = os.path.join(self._project_dir, Project.CONFIG)
if os.path.isfile(project_json):
f = open(project_json)
project_info = json.load(f)
f.close()
if project_info is None:
project_info = {}
project_info[key] = value
outfile = open(project_json, "w")
json.dump(project_info, outfile, sort_keys = True, indent = 4)
outfile.close()
def get_project_dir(self):
return self._project_dir
def get_language(self):
return self._project_lang
def has_android_libs(self):
if self._is_script_project():
proj_android_path = os.path.join(self.get_project_dir(), "frameworks", "runtime-src", "proj.android", "libs")
else:
proj_android_path = os.path.join(self.get_project_dir(), "proj.android", "libs")
return os.path.isdir(proj_android_path)
def _is_native_support(self):
return self._has_native
def _is_script_project(self):
return self._is_lua_project() or self._is_js_project()
def _is_cpp_project(self):
return self._project_lang == Project.CPP
def _is_lua_project(self):
return self._project_lang == Project.LUA
def _is_js_project(self):
return self._project_lang == Project.JS
class Platforms(object):
ANDROID = 'android'
IOS = 'ios'
TVOS = 'tvos'
MAC = 'mac'
WEB = 'web'
WIN32 = 'win32'
LINUX = 'linux'
CFG_CLASS_MAP = {
ANDROID : "axmol_project.AndroidConfig",
IOS : "axmol_project.iOSConfig",
TVOS : "axmol_project.tvOSConfig",
MAC : "axmol_project.MacConfig",
WEB : "axmol_project.WebConfig",
WIN32 : "axmol_project.Win32Config",
LINUX : "axmol_project.LinuxConfig",
}
@staticmethod
def list_for_display():
return [x.lower() for x in Platforms.list()]
@staticmethod
def list():
return Platforms.CFG_CLASS_MAP.keys()
def __init__(self, project, current, proj_dir = None):
self._project = project
proj_info = self._project.info
self._gen_available_platforms(proj_info, proj_dir)
self._current = None
if current is not None:
current_lower = current.lower()
if current_lower in self._available_platforms.keys():
self._current = current_lower
else:
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_INVALID_PLATFORM_FMT',
(self._available_platforms.keys(), current)),
axmol.CCPluginError.ERROR_WRONG_ARGS)
def _filter_platforms(self, platforms):
ret = []
platforms_for_os = {
"linux" : [ Platforms.WEB, Platforms.LINUX, Platforms.ANDROID ],
"mac" : [ Platforms.WEB, Platforms.IOS, Platforms.TVOS, Platforms.MAC, Platforms.ANDROID ],
"win32" : [ Platforms.WEB, Platforms.WIN32, Platforms.ANDROID ]
}
for p in platforms:
if axmol.os_is_linux():
if p in platforms_for_os["linux"]:
ret.append(p)
if axmol.os_is_mac():
if p in platforms_for_os["mac"]:
ret.append(p)
if axmol.os_is_win32():
if p in platforms_for_os["win32"]:
ret.append(p)
return ret
def _gen_available_platforms(self, proj_info, proj_dir):
# generate the platform list for different projects
if self._project._is_lua_project():
if self._project._is_native_support():
platform_list = [ Platforms.ANDROID, Platforms.WIN32, Platforms.IOS, Platforms.TVOS, Platforms.MAC, Platforms.LINUX ]
else:
if self._project.has_android_libs():
platform_list = [ Platforms.ANDROID ]
else:
platform_list = []
elif self._project._is_js_project():
if self._project._is_native_support():
platform_list = [ Platforms.ANDROID, Platforms.WIN32, Platforms.IOS, Platforms.TVOS, Platforms.MAC, Platforms.WEB, Platforms.LINUX ]
else:
if self._project.has_android_libs():
platform_list = [ Platforms.ANDROID, Platforms.WEB ]
else:
platform_list = [ Platforms.WEB ]
elif self._project._is_cpp_project():
platform_list = [ Platforms.ANDROID, Platforms.WIN32, Platforms.IOS, Platforms.TVOS, Platforms.MAC, Platforms.LINUX ]
# filter the available platform list
platform_list = self._filter_platforms(platform_list)
# check the real available platforms
self._available_platforms = {}
root_path = self._project.get_project_dir()
for p in platform_list:
cfg_class = axmol.get_class(Platforms.CFG_CLASS_MAP[p])
if cfg_class is None:
continue
cfg_key = "%s_cfg" % p
if axmol.dict_contains(proj_info, cfg_key):
cfg_obj = cfg_class(root_path, self._project._is_script_project(), proj_info[cfg_key])
else:
cfg_obj = cfg_class(root_path, self._project._is_script_project())
if proj_dir is not None:
cfg_obj.proj_path = os.path.join(root_path, proj_dir)
if cfg_obj._is_available():
self._available_platforms[p] = cfg_obj
# don't have available platforms
if len(self._available_platforms) == 0:
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_NO_AVAILABLE_PLATFORMS'),
axmol.CCPluginError.ERROR_WRONG_CONFIG)
def get_current_platform(self):
return self._current
def get_available_platforms(self):
return self._available_platforms
def none_active(self):
return self._current is None
def is_android_active(self):
return self._current == Platforms.ANDROID
def is_ios_active(self):
return self._current == Platforms.IOS
def is_tvos_active(self):
return self._current == Platforms.TVOS
def is_mac_active(self):
return self._current == Platforms.MAC
def is_web_active(self):
return self._current == Platforms.WEB
def is_win32_active(self):
return self._current == Platforms.WIN32
def is_linux_active(self):
return self._current == Platforms.LINUX
def get_current_config(self):
if self.none_active():
return None
return self._available_platforms[self._current]
def project_path(self):
if self._current is None:
return None
cfg_obj = self._available_platforms[self._current]
return cfg_obj.proj_path
def _has_one(self):
return len(self._available_platforms) == 1
def select_one(self):
if self._has_one():
self._current = self._available_platforms.keys()[0]
return
raise axmol.CCPluginError(MultiLanguage.get_string('PROJECT_SPECIFY_PLATFORM_FMT',
str(self._available_platforms.keys())),
axmol.CCPluginError.ERROR_WRONG_CONFIG)
class PlatformConfig(object):
KEY_PROJ_PATH = "project_path"
def __init__(self, proj_root_path, is_script, cfg_info = None):
self._proj_root_path = proj_root_path
self._is_script = is_script
if cfg_info is None:
self._use_default()
else:
self._parse_info(cfg_info)
def _use_default(self):
pass
def _parse_info(self, cfg_info):
if axmol.dict_contains(cfg_info, PlatformConfig.KEY_PROJ_PATH):
self.proj_path = os.path.join(self._proj_root_path, cfg_info[PlatformConfig.KEY_PROJ_PATH])
else:
self.proj_path = None
def _is_available(self):
ret = True
if self.proj_path is None or not os.path.isdir(self.proj_path):
ret = False
return ret
class AndroidConfig(PlatformConfig):
def _use_default(self):
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.android")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.android")
def _parse_info(self, cfg_info):
super(AndroidConfig, self)._parse_info(cfg_info)
def _is_available(self):
proj_android_existed = super(AndroidConfig, self)._is_available()
return proj_android_existed
class LinuxConfig(PlatformConfig):
KEY_CMAKE_PATH = "cmake_path"
KEY_BUILD_DIR = "build_dir"
KEY_PROJECT_NAME = "project_name"
KEY_BUILD_RESULT_DIR = "build_result_dir"
def _use_default(self):
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.linux")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.linux")
self.cmake_path = None
self.build_dir = None
self.project_name = None
self.build_result_dir = None
def _parse_info(self, cfg_info):
super(LinuxConfig, self)._parse_info(cfg_info)
if axmol.dict_contains(cfg_info, LinuxConfig.KEY_CMAKE_PATH):
self.cmake_path = cfg_info[LinuxConfig.KEY_CMAKE_PATH]
else:
self.cmake_path = None
if axmol.dict_contains(cfg_info, LinuxConfig.KEY_BUILD_DIR):
self.build_dir = cfg_info[LinuxConfig.KEY_BUILD_DIR]
else:
self.build_dir = None
if axmol.dict_contains(cfg_info, LinuxConfig.KEY_PROJECT_NAME):
self.project_name = cfg_info[LinuxConfig.KEY_PROJECT_NAME]
else:
self.project_name = None
if axmol.dict_contains(cfg_info, LinuxConfig.KEY_BUILD_RESULT_DIR):
self.build_result_dir = cfg_info[LinuxConfig.KEY_BUILD_RESULT_DIR]
else:
self.build_result_dir = None
def _is_available(self):
ret = super(LinuxConfig, self)._is_available()
return ret
class MacConfig(LinuxConfig):
def _use_default(self):
super(MacConfig, self)._use_default()
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.ios_mac")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.ios_mac")
class iOSConfig(LinuxConfig):
def _use_default(self):
super(iOSConfig, self)._use_default()
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.ios_mac")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.ios_mac")
class tvOSConfig(LinuxConfig):
def _use_default(self):
super(tvOSConfig, self)._use_default()
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.ios_mac")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.ios_mac")
class Win32Config(LinuxConfig):
def _use_default(self):
super(Win32Config, self)._use_default()
if self._is_script:
self.proj_path = os.path.join(self._proj_root_path, "frameworks", "runtime-src", "proj.win32")
else:
self.proj_path = os.path.join(self._proj_root_path, "proj.win32")
class WebConfig(PlatformConfig):
KEY_SUB_URL = "sub_url"
KEY_RUN_ROOT_DIR = "run_root_dir"
KEY_COPY_RESOURCES = "copy_resources"
def _use_default(self):
self.proj_path = self._proj_root_path
self.run_root_dir = self._proj_root_path
self.copy_res = None
self.sub_url = None
def _parse_info(self, cfg_info):
super(WebConfig, self)._parse_info(cfg_info)
if axmol.dict_contains(cfg_info, WebConfig.KEY_SUB_URL):
self.sub_url = cfg_info[WebConfig.KEY_SUB_URL]
else:
self.sub_url = None
if axmol.dict_contains(cfg_info, WebConfig.KEY_RUN_ROOT_DIR):
self.run_root_dir = os.path.join(self._proj_root_path, cfg_info[WebConfig.KEY_RUN_ROOT_DIR])
else:
self.run_root_dir = None
if axmol.dict_contains(cfg_info, WebConfig.KEY_COPY_RESOURCES):
self.copy_res = cfg_info[WebConfig.KEY_COPY_RESOURCES]
else:
self.copy_res = None
def _is_available(self):
ret = super(WebConfig, self)._is_available()
if ret:
index_path = os.path.join(self.proj_path, "index.html")
ret = os.path.isfile(index_path)
return ret

View File

@ -0,0 +1,569 @@
#!/usr/bin/python
# ----------------------------------------------------------------------------
# statistics: Statistics the user behaviors of axmol-console by google analytics
#
# Author: Bin Zhang
#
# License: MIT
# ----------------------------------------------------------------------------
'''
Statistics the user behaviors of axmol-console by google analytics
'''
import axmol
import uuid
import locale
import urllib
import platform
import sys
import os
import json
import time
import socket
import hashlib
import datetime
import zlib
import multiprocessing
urlEncode = None
if sys.version_info.major >= 3:
import http.client as httplib
urlEncode = urllib.parse.urlencode
else:
import httplib
urlEncode = urllib.urlencode
# GA related Constants
GA_HOST = 'www.google-analytics.com'
GA_PATH = '/collect'
GA_APIVERSION = '1'
APPNAME = 'AxisConsole'
TIMEOUT_VALUE = 0.5
# formal tracker ID
GA_TRACKERID = 'UA-60734607-3'
# debug tracker ID
# GA_TRACKERID = 'UA-60530469-4'
# BI related Constants
BI_HOST = 'ark.cocounion.com'
BI_PATH = '/as'
BI_APPID = '433748803'
GA_ENABLED = True
BI_ENABLED = False
class Fields(object):
API_VERSION = 'v'
TRACKING_ID = 'tid'
HIT_TYPE = 't'
CLIENT_ID = 'cid'
EVENT_CATEGORY = 'ec'
EVENT_ACTION = 'ea'
EVENT_LABEL = 'el'
EVENT_VALUE = 'ev'
APP_NAME = 'an'
APP_VERSION = 'av'
USER_LANGUAGE = 'ul'
USER_AGENT = 'ua'
SCREEN_NAME = "cd"
SCREEN_RESOLUTION = "sr"
GA_CACHE_EVENTS_FILE = 'cache_events'
GA_CACHE_EVENTS_BAK_FILE = 'cache_event_bak'
local_cfg_path = os.path.expanduser('~/.axmol')
local_cfg_file = os.path.join(local_cfg_path, GA_CACHE_EVENTS_FILE)
local_cfg_bak_file = os.path.join(local_cfg_path, GA_CACHE_EVENTS_BAK_FILE)
file_in_use_lock = multiprocessing.Lock()
bak_file_in_use_lock = multiprocessing.Lock()
BI_CACHE_EVENTS_FILE = 'bi_cache_events'
bi_cfg_file = os.path.join(local_cfg_path, BI_CACHE_EVENTS_FILE)
bi_file_in_use_lock = multiprocessing.Lock()
def get_user_id():
node = uuid.getnode()
mac = uuid.UUID(int = node).hex[-12:]
uid = hashlib.md5(mac.encode('utf-8')).hexdigest()
return uid
def get_language():
lang, encoding = locale.getdefaultlocale()
return lang
def get_user_agent():
ret_str = None
if axmol.os_is_win32():
ver_info = sys.getwindowsversion()
ver_str = '%d.%d' % (ver_info[0], ver_info[1])
if axmol.os_is_32bit_windows():
arch_str = "WOW32"
else:
arch_str = "WOW64"
ret_str = "Mozilla/5.0 (Windows NT %s; %s) Chrome/103.0.5060.114 Safari/537.36" % (ver_str, arch_str)
elif axmol.os_is_mac():
ver_str = (platform.mac_ver()[0]).replace('.', '_')
ret_str = "Mozilla/5.0 (Macintosh; Intel Mac OS X %s) Chrome/103.0.5060.114 Safari/537.36" % ver_str
elif axmol.os_is_linux():
arch_str = platform.machine()
ret_str = "Mozilla/5.0 (X11; Linux %s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36" % arch_str
return ret_str
def get_system_info():
if axmol.os_is_win32():
ret_str = "windows"
ret_str += "_%s" % platform.release()
if axmol.os_is_32bit_windows():
ret_str += "_%s" % "32bit"
else:
ret_str += "_%s" % "64bit"
elif axmol.os_is_mac():
ret_str = "mac_%s" % (platform.mac_ver()[0]).replace('.', '_')
elif axmol.os_is_linux():
ret_str = "linux_%s" % platform.linux_distribution()[0]
else:
ret_str = "unknown"
return ret_str
def get_python_version():
return "python_%s" % platform.python_version()
def get_time_stamp():
utc_dt = datetime.datetime.utcnow()
local_dt = utc_dt + datetime.timedelta(hours=8)
epoch = datetime.datetime(1970,1,1)
local_ts = (local_dt - epoch).total_seconds()
ret = '%d' % int(local_ts)
return ret
def get_static_params(engine_version):
static_params = {
Fields.API_VERSION: GA_APIVERSION,
Fields.TRACKING_ID: GA_TRACKERID,
Fields.CLIENT_ID: get_user_id(),
Fields.APP_NAME: APPNAME,
Fields.HIT_TYPE: "event",
Fields.USER_LANGUAGE: get_language(),
Fields.APP_VERSION: engine_version,
Fields.SCREEN_NAME: get_system_info(),
Fields.SCREEN_RESOLUTION: get_python_version()
}
agent_str = get_user_agent()
if agent_str is not None:
static_params[Fields.USER_AGENT] = agent_str
return static_params
def gen_bi_event(event, event_value):
time_stamp = get_time_stamp()
if event_value == 0:
is_cache_event = '1'
else:
is_cache_event = '0'
category = event[0]
action = event[1]
label = event[2]
event_name = category
params = {
'cached_event' : is_cache_event
}
if category == 'axmol':
if action == 'start':
event_name = 'axmol_invoked'
elif action == 'running_command':
event_name = 'running_command'
params['command'] = label
else:
params['category'] = category
params['action'] = action
params['label'] = label
elif category == 'new':
event_name = 'new_project'
params['language'] = action
params['template'] = label
elif category == 'new_engine_ver':
event_name = 'engine_info'
params['version'] = action
params['engine_type'] = label
elif category == 'compile':
params['language'] = action
params['target_platform'] = label
else:
params['category'] = category
params['action'] = action
params['label'] = label
if len(event) >= 4:
appear_time = event[3]
else:
appear_time = time_stamp
ret = {
'u' : {
'28' : get_user_id(),
'34' : get_python_version()
},
'p' : params,
's' : time_stamp,
'e' : event_name,
't' : appear_time
}
return ret
def get_bi_params(events, event_value, multi_events=False, engine_version=''):
if axmol.os_is_win32():
system_str = 'windows'
ver_info = sys.getwindowsversion()
ver_str = '%d.%d' % (ver_info[0], ver_info[1])
if axmol.os_is_32bit_windows():
arch_str = "_32bit"
else:
arch_str = "_64bit"
system_ver = '%s%s' % (ver_str, arch_str)
elif axmol.os_is_mac():
system_str = 'mac'
system_ver = (platform.mac_ver()[0])
elif axmol.os_is_linux():
system_str = 'linux'
system_ver = platform.machine()
else:
system_str = 'unknown'
system_ver = 'unknown'
events_param = []
if multi_events:
for e in events:
events_param.append(gen_bi_event(e, event_value))
else:
events_param.append(gen_bi_event(events, event_value))
params = {
'device': {
'10' : system_ver,
'11' : system_str
},
'app': {
'7' : BI_APPID,
'8' : engine_version,
'9' : get_language()
},
'time' : get_time_stamp(),
'events' : events_param
}
return params
def cache_event(event, is_ga=True, multi_events=False):
if is_ga:
cache_ga_event(event)
else:
cache_bi_event(event, multi_events)
# BI cache events related methods
def cache_bi_event(event, multi_events=False):
bi_file_in_use_lock.acquire()
outFile = None
try:
# get current cached events
cache_events = get_bi_cached_events(need_lock=False)
if multi_events:
need_cache_size = len(event)
else:
need_cache_size = 1
# delete the oldest events if there are too many events.
events_size = len(cache_events)
if events_size >= Statistic.MAX_CACHE_EVENTS:
start_idx = events_size - (Statistic.MAX_CACHE_EVENTS - need_cache_size)
cache_events = cache_events[start_idx:]
# cache the new event
if multi_events:
for e in event:
cache_events.append(e)
else:
cache_events.append(event)
# write file
outFile = open(bi_cfg_file, 'w')
json.dump(cache_events, outFile)
outFile.close()
except:
if outFile is not None:
outFile.close()
finally:
bi_file_in_use_lock.release()
def get_bi_cached_events(need_lock=True):
if not os.path.isfile(bi_cfg_file):
cached_events = []
else:
f = None
try:
if need_lock:
bi_file_in_use_lock.acquire()
f = open(bi_cfg_file)
cached_events = json.load(f)
f.close()
if not isinstance(cached_events, list):
cached_events = []
except:
cached_events = []
finally:
if f is not None:
f.close()
if need_lock:
bi_file_in_use_lock.release()
return cached_events
# GA cache events related methods
def get_ga_cached_events(is_bak=False, need_lock=True):
if is_bak:
cfg_file = local_cfg_bak_file
lock = bak_file_in_use_lock
else:
cfg_file = local_cfg_file
lock = file_in_use_lock
if not os.path.isfile(cfg_file):
cached_events = []
else:
f = None
try:
if need_lock:
lock.acquire()
f = open(cfg_file)
cached_events = json.load(f)
f.close()
if not isinstance(cached_events, list):
cached_events = []
except:
cached_events = []
finally:
if f is not None:
f.close()
if need_lock:
lock.release()
return cached_events
def cache_ga_event(event):
file_in_use_lock.acquire()
outFile = None
try:
# get current cached events
cache_events = get_ga_cached_events(is_bak=False, need_lock=False)
# delete the oldest events if there are too many events.
events_size = len(cache_events)
if events_size >= Statistic.MAX_CACHE_EVENTS:
start_idx = events_size - (Statistic.MAX_CACHE_EVENTS - 1)
cache_events = cache_events[start_idx:]
# cache the new event
cache_events.append(event)
# write file
outFile = open(local_cfg_file, 'w')
json.dump(cache_events, outFile)
outFile.close()
except:
if outFile is not None:
outFile.close()
finally:
file_in_use_lock.release()
def pop_bak_ga_cached_event():
bak_file_in_use_lock.acquire()
events = get_ga_cached_events(is_bak=True, need_lock=False)
if len(events) > 0:
e = events[0]
events = events[1:]
outFile = None
try:
outFile = open(local_cfg_bak_file, 'w')
json.dump(events, outFile)
outFile.close()
except:
if outFile:
outFile.close()
else:
e = None
bak_file_in_use_lock.release()
return e
def do_send_ga_cached_event(engine_version):
e = pop_bak_ga_cached_event()
while(e is not None):
do_send(e, 0, is_ga=True, multi_events=False, engine_version=engine_version)
e = pop_bak_ga_cached_event()
def get_params_str(event, event_value, is_ga=True, multi_events=False, engine_version=''):
if is_ga:
params = get_static_params(engine_version)
params[Fields.EVENT_CATEGORY] = 'ax-' + event[0]
params[Fields.EVENT_ACTION] = event[1]
params[Fields.EVENT_LABEL] = event[2]
params[Fields.EVENT_VALUE] = '%d' % event_value
params_str = urlEncode(params)
else:
params = get_bi_params(event, event_value, multi_events, engine_version)
strParam = json.dumps(params)
params_str = zlib.compress(strParam, 9)
return params_str
def do_http_request(event, event_value, is_ga=True, multi_events=False, engine_version=''):
ret = False
conn = None
try:
params_str = get_params_str(event, event_value, is_ga, multi_events, engine_version)
if is_ga:
host_url = GA_HOST
host_path = GA_PATH
else:
host_url = BI_HOST
host_path = BI_PATH
socket.setdefaulttimeout(TIMEOUT_VALUE)
conn = httplib.HTTPConnection(host_url, timeout=TIMEOUT_VALUE)
conn.request(method="POST", url=host_path, body=params_str)
response = conn.getresponse()
res = response.status
if res >= 200 and res < 300:
# status is 2xx mean the request is success.
ret = True
else:
ret = False
except:
pass
finally:
if conn:
conn.close()
return ret
def do_send(event, event_value, is_ga=True, multi_events=False, engine_version=''):
try:
ret = do_http_request(event, event_value, is_ga, multi_events, engine_version)
if not ret:
# request failed, cache the event
cache_event(event, is_ga, multi_events)
except:
pass
class Statistic(object):
MAX_CACHE_EVENTS = 50
MAX_CACHE_PROC = 5
def __init__(self, engine_version):
self.process_pool = []
self.engine_version = engine_version
if axmol.os_is_win32():
multiprocessing.freeze_support()
def send_cached_events(self):
try:
# send GA cached events
if GA_ENABLED:
events = get_ga_cached_events()
event_size = len(events)
if event_size == 0:
return
# rename the file
if os.path.isfile(local_cfg_bak_file):
os.remove(local_cfg_bak_file)
os.rename(local_cfg_file, local_cfg_bak_file)
# create processes to handle the events
proc_num = min(event_size, Statistic.MAX_CACHE_PROC)
for i in range(proc_num):
p = multiprocessing.Process(target=do_send_ga_cached_event, args=(self.engine_version,))
p.start()
self.process_pool.append(p)
# send BI cached events
if BI_ENABLED:
events = get_bi_cached_events()
event_size = len(events)
if event_size == 0:
return
# remove the cached events file
if os.path.isfile(bi_cfg_file):
os.remove(bi_cfg_file)
p = multiprocessing.Process(target=do_send, args=(events, 0, False, True, self.engine_version,))
p.start()
self.process_pool.append(p)
except:
pass
def send_event(self, category, action, label):
try:
event = [ category, action, label ]
# send event to GA
if GA_ENABLED:
p = multiprocessing.Process(target=do_send, args=(event, 1, True, False, self.engine_version,))
p.start()
self.process_pool.append(p)
# send event to BI
if BI_ENABLED:
# add timestamp
event.append(get_time_stamp())
p = multiprocessing.Process(target=do_send, args=(event, 1, False, False, self.engine_version,))
p.start()
self.process_pool.append(p)
except:
pass
def terminate_stat(self):
# terminate sub-processes
if len(self.process_pool) > 0:
alive_count = 0
for p in self.process_pool:
if p.is_alive():
alive_count += 1
if alive_count > 0:
time.sleep(1)
for p in self.process_pool:
if p.is_alive():
p.terminate()
# remove the backup file
if os.path.isfile(local_cfg_bak_file):
os.remove(local_cfg_bak_file)