{"action":"created","comment":{"url":"https://api.github.com/repos/otland/forgottenserver/pulls/comments/51511511","id":51511511,"diff_hunk":"@@ -0,0 +1,229 @@\n+local function pushSeparated(buffer, sep, ...)\n+\tlocal argv = {...}\n+\tlocal argc = #argv\n+\tfor k, v in ipairs(argv) do\n+\t\ttable.insert(buffer, v)\n+\t\tif k < argc and sep then\n+\t\t\ttable.insert(buffer, sep)\n+\t\tend\n+\tend\n+end\n+\n+local function insertItems(buffer, info, parent, items)\n+\tlocal start = info.running\n+\tfor _, item in ipairs(items) do\n+\t\tif _ ~= 1 or parent > 100 then\n+\t\t\ttable.insert(buffer, \",\")\n+\t\tend\n+\n+\t\tinfo.running = info.running + 1\n+\t\ttable.insert(buffer, \"(\")        \n+\t\tpushSeparated(buffer, \",\", info.playerGuid, parent, info.running, item:getId(), item:getSubType(), db.escapeBlob(item:serializeAttributes()))\n+\t\ttable.insert(buffer, \")\")\n+\n+\t\tif item:isContainer() then\n+\t\t\tlocal size = item:getSize()\n+\t\t\tif size > 0 then              \n+\t\t\t\tlocal subItems = {}\n+\t\t\t\tfor i = 1, size do\n+\t\t\t\t\ttable.insert(subItems, item:getItem(i - 1))\n+\t\t\t\tend\n+\n+\t\t\t\tinsertItems(buffer, info, info.running, subItems)\n+\t\t\tend\n+\t\tend\n+\tend\n+\treturn info.running - start\n+end\n+\n+local function insertRewardItems(playerGuid, timestamp, itemList)\n+\tdb.asyncStoreQuery('SELECT `pid`, `sid` FROM `player_rewards` WHERE player_id = ' .. playerGuid .. ' ORDER BY `sid` ASC;', \n+\t\tfunction(query)\n+\t\t\tlocal lastReward = 0\n+\t\t\tlocal lastStoreId   \n+\t\t\tif query then             \n+\t\t\t\trepeat\n+\t\t\t\t\tlocal sid = result.getDataInt(query, 'sid')\n+\t\t\t\t\tlocal pid = result.getDataInt(query, 'pid')\n+\n+\t\t\t\t\tif pid < 100 then\n+\t\t\t\t\t\tlastReward = pid\n+\t\t\t\t\tend\n+\t\t\t\t\tlastStoreId = sid\n+\t\t\t\tuntil not result.next(query)\n+\t\t\tend\n+\n+\t\t\tlocal buffer = {'INSERT INTO `player_rewards` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES'}\n+\n+\t\t\t--reward bag\n+\t\t\tlocal info = {\n+\t\t\t\tplayerGuid = playerGuid,\n+\t\t\t\trunning = lastStoreId or 100\n+\t\t\t}\n+\n+\t\t\tlocal bag = Game.createItem(ITEM_REWARD_CONTAINER)\n+\t\t\tbag:setAttribute(ITEM_ATTRIBUTE_DATE, timestamp)\n+\n+\t\t\tif itemList then\n+\t\t\t\tfor _, item in ipairs(itemList) do\n+\t\t\t\t\tbag:addItem(item[1], item[2])\n+\t\t\t\tend\n+\t\t\tend\n+\n+\t\t\tlocal total = insertItems(buffer, info, lastReward + 1, {bag})\n+\t\t\ttable.insert(buffer, \";\")\n+\n+\t\t\tif total ~= 0 then\n+\t\t\t\tdb.query(table.concat(buffer))\n+\t\t\tend\n+\t\tend\n+\t)\n+end\n+\n+local function getPlayerStats(bossId, playerGuid, autocreate)\n+\tlocal ret = globalBosses[bossId][playerGuid]\n+\tif not ret and autocreate then\n+\t\tret = {\n+\t\t\tbossId = bossId, \n+\t\t\tdamageIn = 0, -- damage taken from the boss\n+\t\t\thealing = 0, -- healing (other players) done\n+\t\t}\n+\t\tglobalBosses[bossId][playerGuid] = ret\n+\t\treturn ret\n+\tend\n+\treturn ret\n+end\n+\n+function onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)\n+\tlocal monsterType = creature:getType()\n+\tif monsterType:isRewardBoss() then -- Make sure it is a boss\n+\t\tlocal bossId = creature:getId()\n+\t\tlocal timestamp = os.time()\n+\n+\t\tlocal totalDamageOut, totalDamageIn, totalHealing = 0.1, 0.1, 0.1 -- avoid dividing by zero\n+\n+\t\tlocal scores = {}\n+\t\tlocal info = globalBosses[bossId]\n+\t\tlocal damageMap = creature:getDamageMap()\n+\n+\t\tfor guid, stats in pairs(info) do\n+\t\t\tlocal player = Player(stats.playerId)\n+\t\t\tlocal part = damageMap[stats.playerId]\n+\t\t\tlocal damageOut, damageIn, healing = (stats.damageOut or 0) + (part and part.total or 0), stats.damageIn or 0, stats.healing or 0\n+\n+\t\t\ttotalDamageOut = totalDamageOut + damageOut\n+\t\t\ttotalDamageIn = totalDamageIn + damageIn\n+\t\t\ttotalHealing = totalHealing + healing\n+\n+\t\t\ttable.insert(scores, {\n+\t\t\t\tplayer = player, \n+\t\t\t\tguid = guid,\n+\t\t\t\tdamageOut = damageOut, \n+\t\t\t\tdamageIn = damageIn,\n+\t\t\t\thealing = healing,\n+\t\t\t})            \n+\t\tend\n+\n+\t\tlocal participants = 0\n+\t\tfor _, con in ipairs(scores) do\n+\t\t\tlocal score = (con.damageOut / totalDamageOut) + (con.damageIn / totalDamageIn) + (con.healing / totalHealing)\n+\t\t\tcon.score = score / 3 -- normalize to 0-1\n+\t\t\tif score ~= 0 then\n+\t\t\t\tparticipants = participants + 1\n+\t\t\tend\n+\t\tend\n+\t\ttable.sort(scores, function(a, b) return a.score > b.score end)\n+\n+\t\tlocal expectedScore = 1 / participants\n+\n+\t\tfor _, con in ipairs(scores) do","path":"data/creaturescripts/scripts/boss.lua","position":139,"original_position":139,"commit_id":"2eb1cfd80661f856fc6bd32837f7d837d62a279f","original_commit_id":"2eb1cfd80661f856fc6bd32837f7d837d62a279f","user":{"login":"socket2810","id":7633179,"avatar_url":"https://avatars.githubusercontent.com/u/7633179?v=3","gravatar_id":"","url":"https://api.github.com/users/socket2810","html_url":"https://github.com/socket2810","followers_url":"https://api.github.com/users/socket2810/followers","following_url":"https://api.github.com/users/socket2810/following{/other_user}","gists_url":"https://api.github.com/users/socket2810/gists{/gist_id}","starred_url":"https://api.github.com/users/socket2810/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/socket2810/subscriptions","organizations_url":"https://api.github.com/users/socket2810/orgs","repos_url":"https://api.github.com/users/socket2810/repos","events_url":"https://api.github.com/users/socket2810/events{/privacy}","received_events_url":"https://api.github.com/users/socket2810/received_events","type":"User","site_admin":false},"body":"I do not find the idiom score.score appealing.","created_at":"2016-02-02T01:52:11Z","updated_at":"2016-02-02T01:52:11Z","html_url":"https://github.com/otland/forgottenserver/pull/1641#discussion_r51511511","pull_request_url":"https://api.github.com/repos/otland/forgottenserver/pulls/1641","_links":{"self":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/comments/51511511"},"html":{"href":"https://github.com/otland/forgottenserver/pull/1641#discussion_r51511511"},"pull_request":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/1641"}}},"pull_request":{"url":"https://api.github.com/repos/otland/forgottenserver/pulls/1641","id":53782442,"html_url":"https://github.com/otland/forgottenserver/pull/1641","diff_url":"https://github.com/otland/forgottenserver/pull/1641.diff","patch_url":"https://github.com/otland/forgottenserver/pull/1641.patch","issue_url":"https://api.github.com/repos/otland/forgottenserver/issues/1641","number":1641,"state":"open","locked":false,"title":"Reward System [remake of #1628]","user":{"login":"socket2810","id":7633179,"avatar_url":"https://avatars.githubusercontent.com/u/7633179?v=3","gravatar_id":"","url":"https://api.github.com/users/socket2810","html_url":"https://github.com/socket2810","followers_url":"https://api.github.com/users/socket2810/followers","following_url":"https://api.github.com/users/socket2810/following{/other_user}","gists_url":"https://api.github.com/users/socket2810/gists{/gist_id}","starred_url":"https://api.github.com/users/socket2810/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/socket2810/subscriptions","organizations_url":"https://api.github.com/users/socket2810/orgs","repos_url":"https://api.github.com/users/socket2810/repos","events_url":"https://api.github.com/users/socket2810/events{/privacy}","received_events_url":"https://api.github.com/users/socket2810/received_events","type":"User","site_admin":false},"body":"Remake of #1628 \r\n\r\n## Reasoning\r\nAfter seeing a few reward systems on [OTLand](https://otland.net/) try and fail to replicate the original one, I decided to give it a try myself. Some images of the result:\r\n![Boss Loot](http://i.imgur.com/1QtRIGX.png) ![Reward Chest](http://i.imgur.com/bB4a2I3.png)       ![Reward Chest 2](http://i.imgur.com/N5GCeGN.png)\r\n\r\n## How I did it\r\n### Boss Corpses\r\nThe difference between a normal monster corpse and a corpse that should yield individual rewards to players that participated in the fight is its attributes. **ITEM_ATTRIBUTE_CORPSEOWNER** is set to 2^31-1 and **ITEM_ATTRIBUTE_DATE** stores the time it was killed. \r\n### New class: Reward\r\nIt's the *Reward* class responsibility to store the different rewards a player may receive and, just like a depot chest, its contents are stored into the database when the player logs out and again loaded when they log back.\r\n### New class: Reward Chest\r\nAnalogous to the Depot Locker, the *Reward Chest* contains the *Reward* (that inside the game is a [reward container](http://tibia.wikia.com/wiki/Reward_Container). However, it contains all the *Rewards*. They are inserted into the chest during the player load phase and every time another *Reward* is created via:\r\n````\r\nPlayer::getReward(uint32_t timestamp, bool autoCreate);\r\n// or\r\nPlayer.getReward(self, timestamp, autoCreate)\r\n````\r\n\r\n## Specifics\r\n### Timestamps\r\nTimestamps are set both on the boss corpse and on the in-game *reward container* / *Reward* object. They're used to identify the *Reward* and to limit how long the reward is stored in the database (Tibia chose a maximum of 7 days).\r\n### How is each player attributed a different ~~corpse~~reward container?\r\n~~The *Player* class now holds a *rewardCorpses* map that stores each corpse, which are instantiated the first time that the player opens the body and are collected in the player destructor (together with the player's *Rewards*).~~ (Not anymore: 7db6344)\r\nThe boss now drops a *proxy* reward container, meaning it is **not** a *Reward* object, but simply an item with the same id. Whenever a player tries to open this container, he will actually open his own *Reward*, this way there is no need to store unique corpses objects for each player.\r\n### How is the loot handled?\r\nEach player's contribution is measured by an *onHealthChange* event. The player will be considered **active** in the fight if he is currently in the boss' **targetList** - or whenever he heals someone that is currently active. The contribution is kept stored even if the player disconnects during the fight. If during the loot distribution phase the player is offline, he'll still receive his reward (Lua implementation: [insertRewardBag(guid, timestamp, itemList)](https://github.com/socket2810/forgottenserver/blob/master/data/creaturescripts/scripts/boss.lua#L188)).\r\n### How to enable reward distribution to a boss\r\nSet the **rewardboss* flag to true on the monster .xml file:\r\n````xml\r\n<flag rewardboss=\"1\" />\r\n````\r\nTo make a loot unique and awarded to the highest scoring player:\r\n````xml\r\n<item id=\"5903\" chance=\"100000\" unique=\"1\"/><!-- ferumbras' hat -->\r\n````\r\nAnd register the corresponding events by calling *Monster.setReward(self, enable)* whenever a boss is summoned (e.g [place_monster.lua](https://github.com/socket2810/forgottenserver/blob/master/data/talkactions/scripts/place_monster.lua#L14)).\r\n### Player contribution\r\nPlayer contribution is currently calculated like this:\r\n````lua\r\nlocal score = (playerDamageOut / totalDamageOut) + (playerDamageIn / totalDamageIn) + (player.Healing / totalHealing)\r\nscore = score / 3 -- normalize to 0-1\r\nlocal expectedScore = 1 / participants\r\nlocal lootFactor = 1\r\nlootFactor = lootFactor / participants ^ (1 / 3) -- tone down the loot a notch if there are many participants\r\nlootFactor = lootFactor * (1 + lootFactor) ^ (score / expectedScore) -- increase the loot multiplicatively by how many times the player surpassed the expected score\r\n````\r\nEach *lootBlock* is therefore **lootFactor** times more probable to be awarded to a specific player. However it is far from being optimal if we want to achieve a result similar to Tibia's and *only* with the community help we will manage that.\r\n ","created_at":"2015-12-16T00:17:09Z","updated_at":"2016-02-02T01:52:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"49ca21eb68659fdfa9e5d417e5fa5f684aa3c560","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/otland/forgottenserver/pulls/1641/commits","review_comments_url":"https://api.github.com/repos/otland/forgottenserver/pulls/1641/comments","review_comment_url":"https://api.github.com/repos/otland/forgottenserver/pulls/comments{/number}","comments_url":"https://api.github.com/repos/otland/forgottenserver/issues/1641/comments","statuses_url":"https://api.github.com/repos/otland/forgottenserver/statuses/2eb1cfd80661f856fc6bd32837f7d837d62a279f","head":{"label":"socket2810:reward_system","ref":"reward_system","sha":"2eb1cfd80661f856fc6bd32837f7d837d62a279f","user":{"login":"socket2810","id":7633179,"avatar_url":"https://avatars.githubusercontent.com/u/7633179?v=3","gravatar_id":"","url":"https://api.github.com/users/socket2810","html_url":"https://github.com/socket2810","followers_url":"https://api.github.com/users/socket2810/followers","following_url":"https://api.github.com/users/socket2810/following{/other_user}","gists_url":"https://api.github.com/users/socket2810/gists{/gist_id}","starred_url":"https://api.github.com/users/socket2810/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/socket2810/subscriptions","organizations_url":"https://api.github.com/users/socket2810/orgs","repos_url":"https://api.github.com/users/socket2810/repos","events_url":"https://api.github.com/users/socket2810/events{/privacy}","received_events_url":"https://api.github.com/users/socket2810/received_events","type":"User","site_admin":false},"repo":{"id":47339834,"name":"forgottenserver","full_name":"socket2810/forgottenserver","owner":{"login":"socket2810","id":7633179,"avatar_url":"https://avatars.githubusercontent.com/u/7633179?v=3","gravatar_id":"","url":"https://api.github.com/users/socket2810","html_url":"https://github.com/socket2810","followers_url":"https://api.github.com/users/socket2810/followers","following_url":"https://api.github.com/users/socket2810/following{/other_user}","gists_url":"https://api.github.com/users/socket2810/gists{/gist_id}","starred_url":"https://api.github.com/users/socket2810/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/socket2810/subscriptions","organizations_url":"https://api.github.com/users/socket2810/orgs","repos_url":"https://api.github.com/users/socket2810/repos","events_url":"https://api.github.com/users/socket2810/events{/privacy}","received_events_url":"https://api.github.com/users/socket2810/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/socket2810/forgottenserver","description":"A free and open-source MMORPG server emulator written in C++","fork":true,"url":"https://api.github.com/repos/socket2810/forgottenserver","forks_url":"https://api.github.com/repos/socket2810/forgottenserver/forks","keys_url":"https://api.github.com/repos/socket2810/forgottenserver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/socket2810/forgottenserver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/socket2810/forgottenserver/teams","hooks_url":"https://api.github.com/repos/socket2810/forgottenserver/hooks","issue_events_url":"https://api.github.com/repos/socket2810/forgottenserver/issues/events{/number}","events_url":"https://api.github.com/repos/socket2810/forgottenserver/events","assignees_url":"https://api.github.com/repos/socket2810/forgottenserver/assignees{/user}","branches_url":"https://api.github.com/repos/socket2810/forgottenserver/branches{/branch}","tags_url":"https://api.github.com/repos/socket2810/forgottenserver/tags","blobs_url":"https://api.github.com/repos/socket2810/forgottenserver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/socket2810/forgottenserver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/socket2810/forgottenserver/git/refs{/sha}","trees_url":"https://api.github.com/repos/socket2810/forgottenserver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/socket2810/forgottenserver/statuses/{sha}","languages_url":"https://api.github.com/repos/socket2810/forgottenserver/languages","stargazers_url":"https://api.github.com/repos/socket2810/forgottenserver/stargazers","contributors_url":"https://api.github.com/repos/socket2810/forgottenserver/contributors","subscribers_url":"https://api.github.com/repos/socket2810/forgottenserver/subscribers","subscription_url":"https://api.github.com/repos/socket2810/forgottenserver/subscription","commits_url":"https://api.github.com/repos/socket2810/forgottenserver/commits{/sha}","git_commits_url":"https://api.github.com/repos/socket2810/forgottenserver/git/commits{/sha}","comments_url":"https://api.github.com/repos/socket2810/forgottenserver/comments{/number}","issue_comment_url":"https://api.github.com/repos/socket2810/forgottenserver/issues/comments{/number}","contents_url":"https://api.github.com/repos/socket2810/forgottenserver/contents/{+path}","compare_url":"https://api.github.com/repos/socket2810/forgottenserver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/socket2810/forgottenserver/merges","archive_url":"https://api.github.com/repos/socket2810/forgottenserver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/socket2810/forgottenserver/downloads","issues_url":"https://api.github.com/repos/socket2810/forgottenserver/issues{/number}","pulls_url":"https://api.github.com/repos/socket2810/forgottenserver/pulls{/number}","milestones_url":"https://api.github.com/repos/socket2810/forgottenserver/milestones{/number}","notifications_url":"https://api.github.com/repos/socket2810/forgottenserver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/socket2810/forgottenserver/labels{/name}","releases_url":"https://api.github.com/repos/socket2810/forgottenserver/releases{/id}","deployments_url":"https://api.github.com/repos/socket2810/forgottenserver/deployments","created_at":"2015-12-03T15:14:41Z","updated_at":"2016-01-19T16:24:31Z","pushed_at":"2016-01-31T14:10:50Z","git_url":"git://github.com/socket2810/forgottenserver.git","ssh_url":"git@github.com:socket2810/forgottenserver.git","clone_url":"https://github.com/socket2810/forgottenserver.git","svn_url":"https://github.com/socket2810/forgottenserver","homepage":"","size":12595,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"otland:master","ref":"master","sha":"4e1bf88a6a926e076cbdd933dd77c77da89115db","user":{"login":"otland","id":4956302,"avatar_url":"https://avatars.githubusercontent.com/u/4956302?v=3","gravatar_id":"","url":"https://api.github.com/users/otland","html_url":"https://github.com/otland","followers_url":"https://api.github.com/users/otland/followers","following_url":"https://api.github.com/users/otland/following{/other_user}","gists_url":"https://api.github.com/users/otland/gists{/gist_id}","starred_url":"https://api.github.com/users/otland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/otland/subscriptions","organizations_url":"https://api.github.com/users/otland/orgs","repos_url":"https://api.github.com/users/otland/repos","events_url":"https://api.github.com/users/otland/events{/privacy}","received_events_url":"https://api.github.com/users/otland/received_events","type":"Organization","site_admin":false},"repo":{"id":11081909,"name":"forgottenserver","full_name":"otland/forgottenserver","owner":{"login":"otland","id":4956302,"avatar_url":"https://avatars.githubusercontent.com/u/4956302?v=3","gravatar_id":"","url":"https://api.github.com/users/otland","html_url":"https://github.com/otland","followers_url":"https://api.github.com/users/otland/followers","following_url":"https://api.github.com/users/otland/following{/other_user}","gists_url":"https://api.github.com/users/otland/gists{/gist_id}","starred_url":"https://api.github.com/users/otland/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/otland/subscriptions","organizations_url":"https://api.github.com/users/otland/orgs","repos_url":"https://api.github.com/users/otland/repos","events_url":"https://api.github.com/users/otland/events{/privacy}","received_events_url":"https://api.github.com/users/otland/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/otland/forgottenserver","description":"A free and open-source MMORPG server emulator written in C++","fork":false,"url":"https://api.github.com/repos/otland/forgottenserver","forks_url":"https://api.github.com/repos/otland/forgottenserver/forks","keys_url":"https://api.github.com/repos/otland/forgottenserver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/otland/forgottenserver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/otland/forgottenserver/teams","hooks_url":"https://api.github.com/repos/otland/forgottenserver/hooks","issue_events_url":"https://api.github.com/repos/otland/forgottenserver/issues/events{/number}","events_url":"https://api.github.com/repos/otland/forgottenserver/events","assignees_url":"https://api.github.com/repos/otland/forgottenserver/assignees{/user}","branches_url":"https://api.github.com/repos/otland/forgottenserver/branches{/branch}","tags_url":"https://api.github.com/repos/otland/forgottenserver/tags","blobs_url":"https://api.github.com/repos/otland/forgottenserver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/otland/forgottenserver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/otland/forgottenserver/git/refs{/sha}","trees_url":"https://api.github.com/repos/otland/forgottenserver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/otland/forgottenserver/statuses/{sha}","languages_url":"https://api.github.com/repos/otland/forgottenserver/languages","stargazers_url":"https://api.github.com/repos/otland/forgottenserver/stargazers","contributors_url":"https://api.github.com/repos/otland/forgottenserver/contributors","subscribers_url":"https://api.github.com/repos/otland/forgottenserver/subscribers","subscription_url":"https://api.github.com/repos/otland/forgottenserver/subscription","commits_url":"https://api.github.com/repos/otland/forgottenserver/commits{/sha}","git_commits_url":"https://api.github.com/repos/otland/forgottenserver/git/commits{/sha}","comments_url":"https://api.github.com/repos/otland/forgottenserver/comments{/number}","issue_comment_url":"https://api.github.com/repos/otland/forgottenserver/issues/comments{/number}","contents_url":"https://api.github.com/repos/otland/forgottenserver/contents/{+path}","compare_url":"https://api.github.com/repos/otland/forgottenserver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/otland/forgottenserver/merges","archive_url":"https://api.github.com/repos/otland/forgottenserver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/otland/forgottenserver/downloads","issues_url":"https://api.github.com/repos/otland/forgottenserver/issues{/number}","pulls_url":"https://api.github.com/repos/otland/forgottenserver/pulls{/number}","milestones_url":"https://api.github.com/repos/otland/forgottenserver/milestones{/number}","notifications_url":"https://api.github.com/repos/otland/forgottenserver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/otland/forgottenserver/labels{/name}","releases_url":"https://api.github.com/repos/otland/forgottenserver/releases{/id}","deployments_url":"https://api.github.com/repos/otland/forgottenserver/deployments","created_at":"2013-07-01T01:57:06Z","updated_at":"2016-01-27T10:34:51Z","pushed_at":"2016-01-31T16:37:28Z","git_url":"git://github.com/otland/forgottenserver.git","ssh_url":"git@github.com:otland/forgottenserver.git","clone_url":"https://github.com/otland/forgottenserver.git","svn_url":"https://github.com/otland/forgottenserver","homepage":"","size":17521,"stargazers_count":298,"watchers_count":298,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":327,"mirror_url":null,"open_issues_count":134,"forks":327,"open_issues":134,"watchers":298,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/1641"},"html":{"href":"https://github.com/otland/forgottenserver/pull/1641"},"issue":{"href":"https://api.github.com/repos/otland/forgottenserver/issues/1641"},"comments":{"href":"https://api.github.com/repos/otland/forgottenserver/issues/1641/comments"},"review_comments":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/1641/comments"},"review_comment":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/otland/forgottenserver/pulls/1641/commits"},"statuses":{"href":"https://api.github.com/repos/otland/forgottenserver/statuses/2eb1cfd80661f856fc6bd32837f7d837d62a279f"}}}}