websocket を Lua から利用する時の注意

cocos2d-x-3.13 LuaでWebsocketを利用する際に、以前にはでてなかったと思うエラーが出た。
いつのバージョンからかは不明だが、3.6くらいの時は出てなかったと思う(曖昧な記憶)

  local ws = cc.WebSocket:create("ws://example.com")

  ws:registerScriptHandler(function(msg)
      -- なんらかの処理...
    end,
    cc.WEBSOCKET_MESSAGE)

上記を実行すると、registerScriptHandler の第4の引数が無いとエラーが出る。



以下のbindingファイルがその該当箇所のようなので398行目 のエラーチェックに引っかかってたようだ。

# Lua_web_socket.cpp line 390

int tolua_Cocos2d_WebSocket_registerScriptHandler00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
    tolua_Error tolua_err;
    if (
        !tolua_isusertype(tolua_S,1,"cc.WebSocket",0,&tolua_err) ||
        !toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err) ||
        !tolua_isnumber(tolua_S,3,0,&tolua_err) || 
        !tolua_isnoobj(tolua_S,4,&tolua_err)    // ここにひっかかってる
        )
        goto tolua_lerror;
    else
#endif
    {
        LuaWebSocket* self    = (LuaWebSocket*)  tolua_tousertype(tolua_S,1,0);
        if (NULL != self ) {
            int handler = (  toluafix_ref_function(tolua_S,2,0));
            ScriptHandlerMgr::HandlerType handlerType = (ScriptHandlerMgr::HandlerType)((int)tolua_tonumber(tolua_S,3,0) + (int)ScriptHandlerMgr::HandlerType::WEBSOCKET_OPEN);
            ScriptHandlerMgr::getInstance()->addObjectHandler((void*)self, handler, handlerType);
        }
    }
    return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
    tolua_error(tolua_S,"#ferror in function 'registerScriptHandler'.",&tolua_err);
    return 0;
#endif
}

ただ、tolua_toobject(tolua_S,4,0) と、この第4の引数を利用している箇所が関数内には存在しないので
このチェックは無視しても問題なさそう。

以下の部分をfalseに変更

- !tolua_isnoobj(tolua_S,4,&tolua_err)
+ false

エラーは出なくなりました。

AsyncTaskPoolが便利

バックで非同期実行する際などに利用。

AssetsManager とか Download 関係のソースに実装されてるので見様見真似で使ってみる。

Luaからも利用できるように luabinding もさせておくとなおよし。

# 自前のSQLを実行する関数に適用

void Wx::execSqlAsync(const std::string& sql, ResCallback callback)
{
	struct AsyncData
	{
		bool res;
		std::string sql;
	};

	AsyncData* asyncData = new AsyncData;
	asyncData->sql = sql;

	std::function<void(void*)> mainThread = [this, callback, sql](void* param) {
		auto asyncDataInner = reinterpret_cast<AsyncData*>(param);
		callback(asyncDataInner->res, sql);

		delete asyncDataInner;
	};

	AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_OTHER, mainThread, (void*)asyncData, [this, asyncData] {
		asyncData->res = execSql(asyncData->sql);
	});
}

static int lua_cocos2dx_Wx_execSqlAsync(lua_State* L)
{
	if (nullptr == L)
		return 0;

	int argc = 0;
	Wx* self = nullptr;
	bool ok = true;

#if COCOS2D_DEBUG >= 1
	tolua_Error tolua_err;
	if (!tolua_isusertype(L, 1, "Wx", 0, &tolua_err)) goto tolua_lerror;
#endif

	self = static_cast<Wx*>(tolua_tousertype(L, 1, 0));

#if COCOS2D_DEBUG >= 1
	if (nullptr == self) {
		tolua_error(L, "invalid 'self' in function 'lua_cocos2dx_Wx_execSqlAsync'\n", NULL);
		return 0;
	}
#endif
	argc = lua_gettop(L) - 1;
	if (2 == argc)
	{

		std::string arg0;
		ok &= luaval_to_std_string(L, 2, &arg0, "Wx:execSqlAsync");
		if (!ok)
		{
			tolua_error(L, "invalid arguments in function 'lua_cocos2dx_custom_Wx_execSqlAsync'", nullptr);
			return 0;
		}


#if COCOS2D_DEBUG >= 1
		if (!toluafix_isfunction(L, 3, "LUA_FUNCTION", 0, &tolua_err)) { goto tolua_lerror; }
#endif

		LUA_FUNCTION handler = (toluafix_ref_function(L, 3, 0));

		std::function<void(bool b, const std::string sql)> callback = [L, handler](bool b, const std::string sql) {
			LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
			stack->pushBoolean(b);
			stack->pushString(sql.c_str());
			stack->executeFunctionByHandler(handler, 2);
		};

		self->execSqlAsync(arg0, callback);

		return 0;

	}

	luaL_error(L, "'execSqlAsync' function of Wx has wrong number of arguments: %d, was expecting %d\n", argc, 2);

	return 0;

#if COCOS2D_DEBUG >= 1
	tolua_lerror:
				tolua_error(L, "#ferror in function 'execSqlAsync'.", &tolua_err);
				return 0;
#endif
}

Google Playで課金テストをするときに、テストアカウントが認識されない

新しくテストアカウント(Googleアカウント)を作って課金テストをした時の失敗。

1.Google Play console で、APKファイルをアルファー版で公開。
2.クローズドアルファ版テストとして、テスターをリストに追加
3.オプトインURLを該当者に送付
4.メールに届いたURLをクリックしてインストール
5.起動

ここまでは、よかった。
この後、やりたかった課金テストに進むわけだが、どういうわけか課金処理に入ると
テストなのに、クレジット情報が表示されて正規の課金フローのように。。。
テスト課金なら「これはテスト用の注文です。。。」と表示されてくれるはず。。。

仕様が変わったのかなぁ。。と半信半疑でポチってしまったのが運の尽き。
普通に課金されてしまった。。。。

どうも、テスターの設定だけでなく、

DeveloperConsoleの設定 -> 「テスト用のアクセス権がある Gmail アカウント」

この設定が抜けていたのが問題だったらしい。

テスター登録だけでOKだと勘違いしていた。
以前作ったアプリではちゃんと登録していたみたいで、完全に忘却していました。
今回のように新しくテストアカウント作った時には注意が必要。

現在サンドボックスでInApp購入を行う権限がありません

iPhone5S 端末でテストをしようとしたら、「現在サンドボックスでInApp購入を行う権限がありません」とエラーメッセージ。AppleIDをitunes-connectで設定したSandboxユーザに変更してなかっただけ。

端末のAppstoreのトップページを下のほうにスクロールすると「サインアウト」できるので、いったんサインアウトして、改めてテストアプリを起動。課金をしようとするとアカウント入力から求められるのでSandboxに設定したユーザでサインインして課金を行うとOK

cocos2d-x sdkbox とかの問題じゃないので混同しないように注意。

Xcodeでテストビルド用にパッケージを分ける方法

単純にSchemaとTargetに追加すると新しい設定が追加できるのでパッケージ名を変えた設定でビルドすると幸せになれる。

TARGETS [+]ボタンでターゲットの追加
Product -> Scheme -> ManageSchemes で、適当に編集

※Info.plist も別になるはずなので、設定に追加されているか確認すること

XcodeからTestflightへアップロード時に Error ITMS-90032 No image found ...

cocos2d-x 3.13 のinfo.plistにiconの設定が増えているようなのだが、
Xcodeのプロジェクトにはリソース追加設定がされていないようでArch時にエラーになった。

# Xcodeのプロジェクトがリソースと認識するように以下を追加
# Build Phases -> Copy Bundle Resources +(add) 

ios/icons/icno-87.png
ios/icons/icon-180.png