{"action":"created","comment":{"url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/comments/228787449","pull_request_review_id":169134846,"id":228787449,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyODc4NzQ0OQ==","diff_hunk":"@@ -0,0 +1,50 @@\n+<?php\n+\n+/*\n+ *\n+ *  ____            _        _   __  __ _                  __  __ ____\n+ * |  _ \\ ___   ___| | _____| |_|  \\/  (_)_ __   ___      |  \\/  |  _ \\\n+ * | |_) / _ \\ / __| |/ / _ \\ __| |\\/| | | '_ \\ / _ \\_____| |\\/| | |_) |\n+ * |  __/ (_) | (__|   <  __/ |_| |  | | | | | |  __/_____| |  | |  __/\n+ * |_|   \\___/ \\___|_|\\_\\___|\\__|_|  |_|_|_| |_|\\___|     |_|  |_|_|\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU Lesser General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * @author PocketMine Team\n+ * @link http://www.pocketmine.net/\n+ *\n+ *\n+*/\n+\n+declare(strict_types=1);\n+\n+namespace pocketmine\\scheduler;\n+\n+/**\n+ * Task implementation which allows closures to be called by a scheduler.\n+ *\n+ * Example usage:\n+ *\n+ * TaskScheduler->scheduleTask(new ClosureTask(function(int $currentTick) : void{\n+ *     echo \"HI on $currentTick\\n\";\n+ * });","path":"src/pocketmine/scheduler/ClosureTask.php","position":33,"original_position":33,"commit_id":"3ae24408301c49342d24b7732f476423a926ed5e","original_commit_id":"3ae24408301c49342d24b7732f476423a926ed5e","user":{"login":"dktapps","id":14214667,"node_id":"MDQ6VXNlcjE0MjE0NjY3","avatar_url":"https://avatars2.githubusercontent.com/u/14214667?v=4","gravatar_id":"","url":"https://api.github.com/users/dktapps","html_url":"https://github.com/dktapps","followers_url":"https://api.github.com/users/dktapps/followers","following_url":"https://api.github.com/users/dktapps/following{/other_user}","gists_url":"https://api.github.com/users/dktapps/gists{/gist_id}","starred_url":"https://api.github.com/users/dktapps/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dktapps/subscriptions","organizations_url":"https://api.github.com/users/dktapps/orgs","repos_url":"https://api.github.com/users/dktapps/repos","events_url":"https://api.github.com/users/dktapps/events{/privacy}","received_events_url":"https://api.github.com/users/dktapps/received_events","type":"User","site_admin":false},"body":"I'm not sure how else to do it. Suggestions?","created_at":"2018-10-29T03:14:12Z","updated_at":"2018-10-29T03:14:12Z","html_url":"https://github.com/pmmp/PocketMine-MP/pull/2497#discussion_r228787449","pull_request_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/comments/228787449"},"html":{"href":"https://github.com/pmmp/PocketMine-MP/pull/2497#discussion_r228787449"},"pull_request":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497"}},"in_reply_to_id":228778992},"pull_request":{"url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497","id":226295554,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI2Mjk1NTU0","html_url":"https://github.com/pmmp/PocketMine-MP/pull/2497","diff_url":"https://github.com/pmmp/PocketMine-MP/pull/2497.diff","patch_url":"https://github.com/pmmp/PocketMine-MP/pull/2497.patch","issue_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/2497","number":2497,"state":"open","locked":false,"title":"Added a ClosureTask implementation for easier task scheduling","user":{"login":"dktapps","id":14214667,"node_id":"MDQ6VXNlcjE0MjE0NjY3","avatar_url":"https://avatars2.githubusercontent.com/u/14214667?v=4","gravatar_id":"","url":"https://api.github.com/users/dktapps","html_url":"https://github.com/dktapps","followers_url":"https://api.github.com/users/dktapps/followers","following_url":"https://api.github.com/users/dktapps/following{/other_user}","gists_url":"https://api.github.com/users/dktapps/gists{/gist_id}","starred_url":"https://api.github.com/users/dktapps/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dktapps/subscriptions","organizations_url":"https://api.github.com/users/dktapps/orgs","repos_url":"https://api.github.com/users/dktapps/repos","events_url":"https://api.github.com/users/dktapps/events{/privacy}","received_events_url":"https://api.github.com/users/dktapps/received_events","type":"User","site_admin":false},"body":"## Problem\r\nIt's very common for plugins to use scheduled tasks to fire functions within themselves. Before PocketMine-MP API 2.0.0 (henceforth referred to as 2.0 for simplicity), we had `CallbackTask` which allowed plugins to do this. However, in 2.0 the `CallbackTask` was removed.\r\n\r\nWhile `CallbackTask` was never intended for plugin usage, the usefulness of callables in this aspect is undeniable. So, meet the new `ClosureTask`.\r\n\r\nConsider the old workflow:\r\n\r\n```php\r\n//Main.php\r\n$this->getScheduler()->scheduleDelayedTask(new SimpleTask($this), 1);\r\n\r\n//SimpleTask.php\r\nclass SimpleTask{\r\n    private $plugin;\r\n\r\n    public function __construct(Main $plugin){\r\n        $this->plugin = $plugin;\r\n    }\r\n\r\n    public function onRun(int $currentTick) : void{\r\n        $this->plugin->getServer()->broadcastMessage(\"Hello players\");\r\n    }\r\n}\r\n```\r\nThis is very annoying especially when the `onRun()` body is merely 1 line. This can be reduced by using anonymous classes, but still causes a lot of boilerplate.\r\n\r\n## Solution\r\nWouldn't it be nice to just be able to do this...\r\n```php\r\n//Main.php\r\n$this->getScheduler()->scheduleDelayedTask(new ClosureTask(function(int $currentTick) : void{\r\n    $this->getServer()->broadcastMessage(\"Hello players\");\r\n}, 1);\r\n```\r\n\r\nClosures are extremely powerful. The main reason is because they retain the `this` scope where they were created. They can also keep variables from the call site by `use`ing them, like `function() use($var1, $var2, $var3)`.\r\n\r\n## Changes\r\n### API changes\r\n- Added a new `ClosureTask` class. The constructor accepts a `Closure` which should accept exactly ONE parameter `(int $currentTick)` and SHOULD NOT return a value.\r\n\r\n## Tests\r\n```php\r\n<?php\r\n\r\ndeclare(strict_types=1);\r\n\r\nrequire 'vendor/autoload.php';\r\n\r\n$sched = new \\pocketmine\\scheduler\\TaskScheduler(new \\SimpleLogger());\r\n\r\n$sched->scheduleTask(new \\pocketmine\\scheduler\\ClosureTask(function(int $currentTick) : void{\r\n\techo \"hello sunshine!\" . PHP_EOL;\r\n\techo $currentTick . PHP_EOL;\r\n}));\r\n\r\n$sched->mainThreadHeartbeat(0);\r\n```\r\noutputs\r\n```\r\nhello sunshine!\r\n0\r\n```\r\n\r\n### Unsolved issues\r\nTimings task names are a problem which is currently unsolved, since they'll all appear as a generic `ClosureTask`.","created_at":"2018-10-27T13:48:33Z","updated_at":"2018-10-29T03:14:12Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7a6ce7bc5a1c53f8ce85720407c9da43bb907d3f","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":454782351,"node_id":"MDU6TGFiZWw0NTQ3ODIzNTE=","url":"https://api.github.com/repos/pmmp/PocketMine-MP/labels/Category:%20API","name":"Category: API","color":"00aa55","default":false},{"id":454787972,"node_id":"MDU6TGFiZWw0NTQ3ODc5NzI=","url":"https://api.github.com/repos/pmmp/PocketMine-MP/labels/PR:%20Contribution","name":"PR: Contribution","color":"bfdadc","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497/commits","review_comments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497/comments","review_comment_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/2497/comments","statuses_url":"https://api.github.com/repos/pmmp/PocketMine-MP/statuses/3ae24408301c49342d24b7732f476423a926ed5e","head":{"label":"pmmp:feature/closure-task","ref":"feature/closure-task","sha":"3ae24408301c49342d24b7732f476423a926ed5e","user":{"login":"pmmp","id":22548559,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIyNTQ4NTU5","avatar_url":"https://avatars2.githubusercontent.com/u/22548559?v=4","gravatar_id":"","url":"https://api.github.com/users/pmmp","html_url":"https://github.com/pmmp","followers_url":"https://api.github.com/users/pmmp/followers","following_url":"https://api.github.com/users/pmmp/following{/other_user}","gists_url":"https://api.github.com/users/pmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/pmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmmp/subscriptions","organizations_url":"https://api.github.com/users/pmmp/orgs","repos_url":"https://api.github.com/users/pmmp/repos","events_url":"https://api.github.com/users/pmmp/events{/privacy}","received_events_url":"https://api.github.com/users/pmmp/received_events","type":"Organization","site_admin":false},"repo":{"id":69691727,"node_id":"MDEwOlJlcG9zaXRvcnk2OTY5MTcyNw==","name":"PocketMine-MP","full_name":"pmmp/PocketMine-MP","private":false,"owner":{"login":"pmmp","id":22548559,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIyNTQ4NTU5","avatar_url":"https://avatars2.githubusercontent.com/u/22548559?v=4","gravatar_id":"","url":"https://api.github.com/users/pmmp","html_url":"https://github.com/pmmp","followers_url":"https://api.github.com/users/pmmp/followers","following_url":"https://api.github.com/users/pmmp/following{/other_user}","gists_url":"https://api.github.com/users/pmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/pmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmmp/subscriptions","organizations_url":"https://api.github.com/users/pmmp/orgs","repos_url":"https://api.github.com/users/pmmp/repos","events_url":"https://api.github.com/users/pmmp/events{/privacy}","received_events_url":"https://api.github.com/users/pmmp/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/pmmp/PocketMine-MP","description":"A server software for Minecraft: Bedrock Edition in PHP","fork":false,"url":"https://api.github.com/repos/pmmp/PocketMine-MP","forks_url":"https://api.github.com/repos/pmmp/PocketMine-MP/forks","keys_url":"https://api.github.com/repos/pmmp/PocketMine-MP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pmmp/PocketMine-MP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pmmp/PocketMine-MP/teams","hooks_url":"https://api.github.com/repos/pmmp/PocketMine-MP/hooks","issue_events_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/events{/number}","events_url":"https://api.github.com/repos/pmmp/PocketMine-MP/events","assignees_url":"https://api.github.com/repos/pmmp/PocketMine-MP/assignees{/user}","branches_url":"https://api.github.com/repos/pmmp/PocketMine-MP/branches{/branch}","tags_url":"https://api.github.com/repos/pmmp/PocketMine-MP/tags","blobs_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/refs{/sha}","trees_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pmmp/PocketMine-MP/statuses/{sha}","languages_url":"https://api.github.com/repos/pmmp/PocketMine-MP/languages","stargazers_url":"https://api.github.com/repos/pmmp/PocketMine-MP/stargazers","contributors_url":"https://api.github.com/repos/pmmp/PocketMine-MP/contributors","subscribers_url":"https://api.github.com/repos/pmmp/PocketMine-MP/subscribers","subscription_url":"https://api.github.com/repos/pmmp/PocketMine-MP/subscription","commits_url":"https://api.github.com/repos/pmmp/PocketMine-MP/commits{/sha}","git_commits_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/commits{/sha}","comments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/comments{/number}","issue_comment_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/comments{/number}","contents_url":"https://api.github.com/repos/pmmp/PocketMine-MP/contents/{+path}","compare_url":"https://api.github.com/repos/pmmp/PocketMine-MP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pmmp/PocketMine-MP/merges","archive_url":"https://api.github.com/repos/pmmp/PocketMine-MP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pmmp/PocketMine-MP/downloads","issues_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues{/number}","pulls_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls{/number}","milestones_url":"https://api.github.com/repos/pmmp/PocketMine-MP/milestones{/number}","notifications_url":"https://api.github.com/repos/pmmp/PocketMine-MP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pmmp/PocketMine-MP/labels{/name}","releases_url":"https://api.github.com/repos/pmmp/PocketMine-MP/releases{/id}","deployments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/deployments","created_at":"2016-09-30T18:29:35Z","updated_at":"2018-10-28T16:42:41Z","pushed_at":"2018-10-28T20:00:53Z","git_url":"git://github.com/pmmp/PocketMine-MP.git","ssh_url":"git@github.com:pmmp/PocketMine-MP.git","clone_url":"https://github.com/pmmp/PocketMine-MP.git","svn_url":"https://github.com/pmmp/PocketMine-MP","homepage":"https://pmmp.io","size":22158,"stargazers_count":1198,"watchers_count":1198,"language":"PHP","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":797,"mirror_url":null,"archived":false,"open_issues_count":92,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":797,"open_issues":92,"watchers":1198,"default_branch":"master"}},"base":{"label":"pmmp:release/3.4","ref":"release/3.4","sha":"0aa30295af901827339cdd9619ea4bd23da0d1de","user":{"login":"pmmp","id":22548559,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIyNTQ4NTU5","avatar_url":"https://avatars2.githubusercontent.com/u/22548559?v=4","gravatar_id":"","url":"https://api.github.com/users/pmmp","html_url":"https://github.com/pmmp","followers_url":"https://api.github.com/users/pmmp/followers","following_url":"https://api.github.com/users/pmmp/following{/other_user}","gists_url":"https://api.github.com/users/pmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/pmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmmp/subscriptions","organizations_url":"https://api.github.com/users/pmmp/orgs","repos_url":"https://api.github.com/users/pmmp/repos","events_url":"https://api.github.com/users/pmmp/events{/privacy}","received_events_url":"https://api.github.com/users/pmmp/received_events","type":"Organization","site_admin":false},"repo":{"id":69691727,"node_id":"MDEwOlJlcG9zaXRvcnk2OTY5MTcyNw==","name":"PocketMine-MP","full_name":"pmmp/PocketMine-MP","private":false,"owner":{"login":"pmmp","id":22548559,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIyNTQ4NTU5","avatar_url":"https://avatars2.githubusercontent.com/u/22548559?v=4","gravatar_id":"","url":"https://api.github.com/users/pmmp","html_url":"https://github.com/pmmp","followers_url":"https://api.github.com/users/pmmp/followers","following_url":"https://api.github.com/users/pmmp/following{/other_user}","gists_url":"https://api.github.com/users/pmmp/gists{/gist_id}","starred_url":"https://api.github.com/users/pmmp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pmmp/subscriptions","organizations_url":"https://api.github.com/users/pmmp/orgs","repos_url":"https://api.github.com/users/pmmp/repos","events_url":"https://api.github.com/users/pmmp/events{/privacy}","received_events_url":"https://api.github.com/users/pmmp/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/pmmp/PocketMine-MP","description":"A server software for Minecraft: Bedrock Edition in PHP","fork":false,"url":"https://api.github.com/repos/pmmp/PocketMine-MP","forks_url":"https://api.github.com/repos/pmmp/PocketMine-MP/forks","keys_url":"https://api.github.com/repos/pmmp/PocketMine-MP/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pmmp/PocketMine-MP/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pmmp/PocketMine-MP/teams","hooks_url":"https://api.github.com/repos/pmmp/PocketMine-MP/hooks","issue_events_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/events{/number}","events_url":"https://api.github.com/repos/pmmp/PocketMine-MP/events","assignees_url":"https://api.github.com/repos/pmmp/PocketMine-MP/assignees{/user}","branches_url":"https://api.github.com/repos/pmmp/PocketMine-MP/branches{/branch}","tags_url":"https://api.github.com/repos/pmmp/PocketMine-MP/tags","blobs_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/refs{/sha}","trees_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pmmp/PocketMine-MP/statuses/{sha}","languages_url":"https://api.github.com/repos/pmmp/PocketMine-MP/languages","stargazers_url":"https://api.github.com/repos/pmmp/PocketMine-MP/stargazers","contributors_url":"https://api.github.com/repos/pmmp/PocketMine-MP/contributors","subscribers_url":"https://api.github.com/repos/pmmp/PocketMine-MP/subscribers","subscription_url":"https://api.github.com/repos/pmmp/PocketMine-MP/subscription","commits_url":"https://api.github.com/repos/pmmp/PocketMine-MP/commits{/sha}","git_commits_url":"https://api.github.com/repos/pmmp/PocketMine-MP/git/commits{/sha}","comments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/comments{/number}","issue_comment_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/comments{/number}","contents_url":"https://api.github.com/repos/pmmp/PocketMine-MP/contents/{+path}","compare_url":"https://api.github.com/repos/pmmp/PocketMine-MP/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pmmp/PocketMine-MP/merges","archive_url":"https://api.github.com/repos/pmmp/PocketMine-MP/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pmmp/PocketMine-MP/downloads","issues_url":"https://api.github.com/repos/pmmp/PocketMine-MP/issues{/number}","pulls_url":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls{/number}","milestones_url":"https://api.github.com/repos/pmmp/PocketMine-MP/milestones{/number}","notifications_url":"https://api.github.com/repos/pmmp/PocketMine-MP/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pmmp/PocketMine-MP/labels{/name}","releases_url":"https://api.github.com/repos/pmmp/PocketMine-MP/releases{/id}","deployments_url":"https://api.github.com/repos/pmmp/PocketMine-MP/deployments","created_at":"2016-09-30T18:29:35Z","updated_at":"2018-10-28T16:42:41Z","pushed_at":"2018-10-28T20:00:53Z","git_url":"git://github.com/pmmp/PocketMine-MP.git","ssh_url":"git@github.com:pmmp/PocketMine-MP.git","clone_url":"https://github.com/pmmp/PocketMine-MP.git","svn_url":"https://github.com/pmmp/PocketMine-MP","homepage":"https://pmmp.io","size":22158,"stargazers_count":1198,"watchers_count":1198,"language":"PHP","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":797,"mirror_url":null,"archived":false,"open_issues_count":92,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":797,"open_issues":92,"watchers":1198,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497"},"html":{"href":"https://github.com/pmmp/PocketMine-MP/pull/2497"},"issue":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/2497"},"comments":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/issues/2497/comments"},"review_comments":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497/comments"},"review_comment":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/pulls/2497/commits"},"statuses":{"href":"https://api.github.com/repos/pmmp/PocketMine-MP/statuses/3ae24408301c49342d24b7732f476423a926ed5e"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"dktapps"}}