Package Manager provides a way for developers to easily extend cocos2d-x with plugins
Core Features:
- Modularize coocs2d-x enable developers to customize the engine for their own game
- Developers can search, manage and install plugins
- Update project for the developers when install, remove or update the plugin
- Developers can share their plugin with others
~
$ cd myapp
$ cocos search leaderboard
searching "leaderboard" in repository ... ok
> leaderboard 1.2 (Zhan Huang)
> leaderboard-gamecenter 1.0 (Zhan Huang)
done.
search
will list all the plugins contains the search keyword, each search result contains three parts
- Plugin Name
- Version
- Maintainer
~
$ cd myapp
$ cocos info leaderboard
get description for plugin "leaderboard" ... ok
name: leaderboard
version: 1.2
updated: 2014/11/11
author: Zhan Huang
This plugin allows people to be ranked based on their scores.
info
followed by the fullname of the plugin
~
$ cd myapp
$ cocos install leaderboard
downloading plugin "leaderboard 1.2 (Zhan Huang)" ... ok
installing ...
> add file src/packages/leaderboard/init.lua
> add file src/packages/leaderboard/Leaderboard.lua
done.
For script plugin, we just need to copy the scripts to related folder
For C/C++ plugin, we have to update project file
$ cd myapp
$ cocos install gamecenter
downloading plugin "gamecenter 1.0 (Peng Li)" ... ok
installing ...
> add file native/packages/gamecenter/GameCenter.mm
> add file native/packages/gamecenter/GameCenter.h
> add file native/packages/gamecenter/GameCenterIOS.mm
> add file native/packages/gamecenter/GameCenterIOS.h
> add file native/packages/gamecenter/GameCenterMac.mm
> add file native/packages/gamecenter/GameCenterMac.h
> add file native/packages/gamecenter/GameCenterLuabinding.cpp
> add file native/packages/gamecenter/GameCenterLuabinding.h
> updating project file native/proj.ios_mac/packages.xcodeproj
done.
~
$ cd myapp
$ cocos uninstall gamecenter
uninstalling ...
> remove file native/packages/gamecenter/GameCenter.mm
> remove file native/packages/gamecenter/GameCenter.h
> remove file native/packages/gamecenter/GameCenterIOS.mm
> remove file native/packages/gamecenter/GameCenterIOS.h
> remove file native/packages/gamecenter/GameCenterMac.mm
> remove file native/packages/gamecenter/GameCenterMac.h
> remove file native/packages/gamecenter/GameCenterLuabinding.cpp
> remove file native/packages/gamecenter/GameCenterLuabinding.h
> updating project file native/proj.ios_mac/packages.xcodeproj
done.
~
$ cd myapp
$ cocos list
list all installed plugins ...
> leaderboard 1.2 (Zhan Huang)
> gamecenter 1.0 (Peng Li)
done.
~
$ cd myapp
$ cocos upgrade leaderboard
searching latest version for plugin "leaderboard" ... ok
downloading "leaderboard 1.3 (Zhan Huang)" ... ok
installing ...
> update file src/packages/leaderboard/init.lua
> update file src/packages/leaderboard/leaderboard.lua
> add file src/packages/leaderboard/leaderboardExt.lua
done.
~
If developer needs a certain version of the plugin, they can use this command to download this certain version
For example, we have the latest 1.3 version of leaderboard, and now we need to revert back to 1.2 version
$ cd myapp
$ cocos install leaderboard 1.2
downloading plugin "leaderboard 1.2 (Zhan Huang)" ... ok
installing ...
> replace file src/packages/leaderboard/init.lua
> replace file src/packages/leaderboard/leaderboard.lua
> remove file src/packages/leaderboard/leaderboardExt.lua
done.
~
Developer can use this command to create a new plugin project
$ cocos create-plugin myplugin
> create directory "myplugin"
> create file "README.md"
> create file "config.json"
> create file "install.json"
> create file "src/init.lua"
> create file "src/myplugin.lua"
done.
For C/C++ plugin, you need -native
$ cocos create-plugin -native myplugin
$ cocos create-plugin myplugin
> create directory "myplugin"
> create file "README.md"
> create file "config.json"
> create file "install.json"
> create file "native/myplugin.cpp"
> create file "native/myplugin.h"
done.
Developer can add whatever code thats required for their plugin based on the plugin project
~
Each plugin contains following parts
-
config.json
Plugin metadata file:{ "name": "PluginName", "version": "1.1", "engine": "supported cocos2d-x version", "author": "auther", "url": "website or repo", "description": "Whether article spirits new her covered hastily sitting her.\n\nMoney witty books nor son add. Chicken age had evening believe but pretend mrs. At missed advice my it no sister. Miss told ham dull knew see she spot near can. Spirit her entire her called.", "depends": [ {"name": "Name of the dependency", "version": "version number of dependency"}, {"name": "Name of the dependency", "version": "version number of dependency"} ] }
-
install.json
Installation file:[ {"command": "command", param ... }, {"command": "command", param ... } ]
-
src/
,native/
source code directories
~
config.json
defines the metadata file for a plugin:
-
name
: Plugin name must start with letters, "-","_" and numbers are allowed, case insensitive. Must be unique from all the plugins -
version
: Version number is two numbers, new version number must be bigger than the old version -
engine
: supported engine version, it can support multiple version like 3.1-3.2supported engine version can only be
final
orrelease
version, in another word, it has to have a version number.major.minor
: specific versionmajor.minor+
:higher versionmajor.minor-major.minor
:between two version
Here are some examples:
3.3+
: cocos2d-x 3.3 or higher2.2.1-2.2.5
: between cocos2d-x 2.2.1 to 2.2.5
-
author
: the author of the plugin。 -
url
: website of the plugin, can be a url to the github repo -
description
: Description for the plugin。 -
depends
: dependencies。Some plugin will require other plugins in order to work, that when
depends
come in:"depends": [ {"name": "plugin name", "version": "version"}, {"name": "plugin name", "version": "version"} ]
For example
leaderboard-gamecenter
requiresleaderboard
version 1.0 or higher,then thedepends
setting will be:"depends": [ {"name": "leaderboard", "version": "1.0+"} ]
Version number rule is the same with
engine
~
install.json
Tells package manager how to install plugin
install.json
contains serials of commands to install a plugin
[
{"command": "command", param ... },
{"command": "command", param ... }
]
Following are the supported commands
-
copy_files
: copy files to the specified path{ "command": "copy_files", "from": "src/*", "to": "src/packages/leaderboard/", }
cory all the files from
<Plugin>/src/
to<Project>/src/packages/leaderboard
, it will copy all the subfolder within it.copy_files
also supports wild card{ "command": "copy_files", "from": "native/LeaderboardGameCenter.*", "to": "native/packages/leaderboard-gamecenter/" }
this will copy all the files match
LeaderboardGameCenter.*
to project folder -
update_project
: update the project fileplugin that contains C/C++ or Objective-C/Java code, requires
update_project
to update the project files:{ "command": "update_project", "add_files": [ "native/packages/leaderboard-gamecenter/*.mm", ], "platform": ["ios", "mac"] }
The code above will add the specific files to the project file.
-
All the source file of a plugin will be added into a group with the same name as the plugin.
For example the above command will create a group named
leaderboard-gamecenter
(because they belongs to pluginleaderboard-gamecenter
) and then add all the source files under it. -
When adding the new files, it will also update
header search paths
-
use
platform
field for platform specific commands, ifplatform
is not specified, the command will perform on all platforms. -
For android, if you want to import a Java package, you need to use
add_packages
param, and specify the path that contains the source code. Note, Because in Java,package name
needs to be the same as the folder of the source code. So you don't need to specify the full path here. such ascom/cocos2d/org
are not required -
If you want to add libraries to the project use
add_libs
param
-
~
Here is an example of how to create install.json
for flurry SDK
[
{
"command": "copy_files",
"from": "native/*",
"to": "native/packages/flurry/"
},
{
"command": "copy_files",
"from": "src/*",
"to": "src/packages/flurry/"
},
{
"command": "update_project",
"add_files": [
"native/packages/flurry/*.cpp",
"native/packages/flurry/*.h"
]
},
{
"command": "update_project",
"add_files": [
"native/packages/flurry/*.mm"
],
"add_libs": [
"native/package/flurry/ios/libflurry.a"
],
"platform": "ios"
},
{
"command": "update_project",
"add_packages": [
"native/packages/flurry/java/",
],
"add_libs": [
"native/package/flurry/android/libflurry.so"
],
"platform": "android"
}
]
Here is what the script performs:
- Copy Flurry code and libs to
<Project>/native/packages/flurry/
- Copy script code into
<Project>/src/packages/flurry/
- Update ios/android project, add required code and libraries.
~
Here is what happens when install a plugin with dependencies:
- Iterate through all the plugins
- Check if a plugin is already installed 2.1 not installed: add to the list to install 2.2 installed: check the version, if not match the requirement, add to the list to install
- Download the
config.json
of all the dependencies, and repeat setp 2 and add plugins to install list - Make sure plugins install list don't have duplicate entries
- Stop the installation and notify user if a conflict has been detected
After installation list is prepared, we can start install all the plugins
~
All the scripting for the plugin goes to src
folder
To use leaderboard
simply call
local leaderboard = cc.load("leaderboard")
cc.load()
implementation:
cc.load = function(pluginName)
-- all ways load packages.pluginname.init to initialze the plugin
local packageName = string.format("packages.%s.init", pluginName)
return require(packageName)
end
since cc.load()
will always call init
function, plugins always need to implement this function for initialization.
~
Compare to scripting native plugins will be a bit more complicated
Based on the commands in install.json
, it will copy the source files and update the project, make sure the updated project still compiles
We'll need to change cocos2d-x's project structure a little bit. We'll need to add a packages
folder for the plugins
this plugins
project will use CMake to generate projects, so developers don't need to manually modify the project.
~
After creating the plugin, developers needs to publish their plugin
Because developers could update their plugin constantly, a centralized server to download everything maybe is not a good idea.
So if a developer wants to submit their plugin, there are two ways to do it.
-
Submit a git hub repo, with proper tagging
For example, a github repo url coule be
https://github.com/dualface/leaderboard/
with tag1.2
, the url should behttps://github.com/dualface/leaderboard/tree/1.2
-
Submit a url, with config.json as well as the zip contains all the files plugin requires
For example
http://mysite.com/downloads/
we'll download
http://mysite.com/downloads/config.json
first, and based onname
andversion
we can decide which zip to downloadif
name
isleaderboard
,version
is1.2
, then the final zip url should behttp://mysite.com/downloads/leaderboard-1.2.zip
Developer must submit their plugin to the repo server. and then user will be able to search and use them.
Before publish your plugin, you can use following command to validate the plugin.
$ cd myplugin
$ cocos validate-plugin
It will check if config.json
and install.json
are valid.
~
After submit plugin to the Package Manager, package manager server will valid if the url of the plugin is valid.
~
Everytime a plguin updates, developer just need to prepare the latest version and submit to the Package Manager server.
~
To support cocos
command, Package Manager server will require the following API:
-
?search=keyword
If we want to search
leaderboard
, then the query will be:http://repo.cocos.org/?search=leaderboard
Return value of json will be:
{ "ok": true, "result": [ { "name": "leaderboard", "version": "1.2", "author": "Zhan Huang" }, { "name": "leaderboard-gamecenter", "version": "1.0", "author": "Zhan Huang" } ] }
-
?info=plugin name
If we want to get the details of
leaderboard
,the query should be:http://repo.cocos.org/?info=leaderboard
Return value of json will be:
{ "name": "leaderboard", "version": "1.2", "author": "Zhan Huang", "description": "XXXXX", "url": "https://github.com/dualface/leaderboard/tree/1.2" }
Package Manager didn't have
download
command, becausecocos install
will use the detail info to findout the download url. ~
The biggest challenge will be the client side
cocos
command will need the following function
- download plugin
- Analyze
install.json
file to install plugin - Update project file for C/C++/Java project file
- Maintain what plugin and which version user already installed.
- Handle upgrading plugin.
- Handle delete plugin and clean up
Some idea:
- each project will have a
plugins.json
file to record the name and version of installed plugin - copy scripting file directly to
src/pacakges/pluginname
folder - For C/C++ file, copy to
native/packages/pluginname
folder - Use CMake to update project file.
- Delete the old plugin when upgrading.
~
Package Manager System contains the following parts
- A website for plugin submission
- A server side app for query plugin info.
- New commands for
cocos
command line.
-EOF-