Merge pull request #12252 from MednauN/master

iOS GameCenter fixes
This commit is contained in:
Rémi Verschelde 2017-10-20 21:37:14 +02:00 committed by GitHub
commit 5bc44fe000
2 changed files with 62 additions and 17 deletions

View File

@ -43,11 +43,13 @@ class GameCenter : public Object {
List<Variant> pending_events; List<Variant> pending_events;
bool connected; bool authenticated;
void return_connect_error(const char *p_error_description);
public: public:
Error connect(); void connect();
bool is_connected(); bool is_authenticated();
Error post_score(Variant p_score); Error post_score(Variant p_score);
Error award_achievement(Variant p_params); Error award_achievement(Variant p_params);
@ -55,6 +57,7 @@ public:
void request_achievements(); void request_achievements();
void request_achievement_descriptions(); void request_achievement_descriptions();
Error show_game_center(Variant p_params); Error show_game_center(Variant p_params);
Error request_identity_verification_signature();
void game_center_closed(); void game_center_closed();

View File

@ -49,8 +49,7 @@ extern "C" {
GameCenter *GameCenter::instance = NULL; GameCenter *GameCenter::instance = NULL;
void GameCenter::_bind_methods() { void GameCenter::_bind_methods() {
ClassDB::bind_method(D_METHOD("connect"), &GameCenter::connect); ClassDB::bind_method(D_METHOD("is_authenticated"), &GameCenter::is_authenticated);
ClassDB::bind_method(D_METHOD("is_connected"), &GameCenter::is_connected);
ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score); ClassDB::bind_method(D_METHOD("post_score"), &GameCenter::post_score);
ClassDB::bind_method(D_METHOD("award_achievement"), &GameCenter::award_achievement); ClassDB::bind_method(D_METHOD("award_achievement"), &GameCenter::award_achievement);
@ -58,24 +57,41 @@ void GameCenter::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements); ClassDB::bind_method(D_METHOD("request_achievements"), &GameCenter::request_achievements);
ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions); ClassDB::bind_method(D_METHOD("request_achievement_descriptions"), &GameCenter::request_achievement_descriptions);
ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center); ClassDB::bind_method(D_METHOD("show_game_center"), &GameCenter::show_game_center);
ClassDB::bind_method(D_METHOD("request_identity_verification_signature"), &GameCenter::request_identity_verification_signature);
ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count); ClassDB::bind_method(D_METHOD("get_pending_event_count"), &GameCenter::get_pending_event_count);
ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event); ClassDB::bind_method(D_METHOD("pop_pending_event"), &GameCenter::pop_pending_event);
}; };
Error GameCenter::connect() { void GameCenter::return_connect_error(const char *p_error_description) {
authenticated = false;
Dictionary ret;
ret["type"] = "authentication";
ret["result"] = "error";
ret["error_code"] = 0;
ret["error_description"] = p_error_description;
pending_events.push_back(ret);
}
void GameCenter::connect() {
//if this class isn't available, game center isn't implemented //if this class isn't available, game center isn't implemented
if ((NSClassFromString(@"GKLocalPlayer")) == nil) { if ((NSClassFromString(@"GKLocalPlayer")) == nil) {
GameCenter::get_singleton()->connected = false; return_connect_error("GameCenter not available");
return ERR_UNAVAILABLE; return;
} }
GKLocalPlayer *player = [GKLocalPlayer localPlayer]; GKLocalPlayer *player = [GKLocalPlayer localPlayer];
ERR_FAIL_COND_V(![player respondsToSelector:@selector(authenticateHandler)], ERR_UNAVAILABLE); if (![player respondsToSelector:@selector(authenticateHandler)]) {
return_connect_error("GameCenter doesn't respond to 'authenticateHandler'");
return;
}
ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController; ViewController *root_controller = (ViewController *)((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController;
ERR_FAIL_COND_V(!root_controller, FAILED); if (!root_controller) {
return_connect_error("Window doesn't have root ViewController");
return;
}
// This handler is called several times. First when the view needs to be shown, then again // This handler is called several times. First when the view needs to be shown, then again
// after the view is cancelled or the user logs in. Or if the user's already logged in, it's // after the view is cancelled or the user logs in. Or if the user's already logged in, it's
@ -90,23 +106,21 @@ Error GameCenter::connect() {
if (player.isAuthenticated) { if (player.isAuthenticated) {
ret["result"] = "ok"; ret["result"] = "ok";
ret["player_id"] = [player.playerID UTF8String]; ret["player_id"] = [player.playerID UTF8String];
GameCenter::get_singleton()->connected = true; GameCenter::get_singleton()->authenticated = true;
} else { } else {
ret["result"] = "error"; ret["result"] = "error";
ret["error_code"] = error.code; ret["error_code"] = error.code;
ret["error_description"] = [error.localizedDescription UTF8String]; ret["error_description"] = [error.localizedDescription UTF8String];
GameCenter::get_singleton()->connected = false; GameCenter::get_singleton()->authenticated = false;
}; };
pending_events.push_back(ret); pending_events.push_back(ret);
}; };
}); });
return OK;
}; };
bool GameCenter::is_connected() { bool GameCenter::is_authenticated() {
return connected; return authenticated;
}; };
Error GameCenter::post_score(Variant p_score) { Error GameCenter::post_score(Variant p_score) {
@ -326,6 +340,34 @@ Error GameCenter::show_game_center(Variant p_params) {
return OK; return OK;
}; };
Error GameCenter::request_identity_verification_signature() {
ERR_FAIL_COND_V(!is_authenticated(), ERR_UNAUTHORIZED);
GKLocalPlayer *player = [GKLocalPlayer localPlayer];
[player generateIdentityVerificationSignatureWithCompletionHandler:^(NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp, NSError *error) {
Dictionary ret;
ret["type"] = "identity_verification_signature";
if (error == nil) {
ret["result"] = "ok";
ret["public_key_url"] = [publicKeyUrl.absoluteString UTF8String];
ret["signature"] = [[signature base64EncodedStringWithOptions:0] UTF8String];
ret["salt"] = [[salt base64EncodedStringWithOptions:0] UTF8String];
ret["timestamp"] = timestamp;
ret["player_id"] = [player.playerID UTF8String];
} else {
ret["result"] = "error";
ret["error_code"] = error.code;
ret["error_description"] = [error.localizedDescription UTF8String];
};
pending_events.push_back(ret);
}];
return OK;
};
void GameCenter::game_center_closed() { void GameCenter::game_center_closed() {
Dictionary ret; Dictionary ret;
@ -354,7 +396,7 @@ GameCenter *GameCenter::get_singleton() {
GameCenter::GameCenter() { GameCenter::GameCenter() {
ERR_FAIL_COND(instance != NULL); ERR_FAIL_COND(instance != NULL);
instance = this; instance = this;
connected = false; authenticated = false;
}; };
GameCenter::~GameCenter(){}; GameCenter::~GameCenter(){};