{"action":"created","comment":{"url":"https://api.github.com/repos/minetest/minetest/pulls/comments/54994259","id":54994259,"diff_hunk":"@@ -271,6 +271,238 @@ ABMWithState::ABMWithState(ActiveBlockModifier *abm_):\n }\n \n /*\n+\tLBMManager\n+*/\n+\n+LBMContentMapping::~LBMContentMapping()\n+{\n+\tfor (std::vector<LoadingBlockModifierDef *>::iterator it = lbm_list.begin();\n+\t\t\tit != lbm_list.end(); ++it) {\n+\t\tdelete *it;\n+\t}\n+}\n+\n+void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef)\n+{\n+\t// Add the lbm_def to the LBMContentMapping.\n+\t// Unknown names get added to the global NameIdMapping.\n+\tINodeDefManager *nodedef = gamedef->ndef();\n+\n+\tlbm_list.push_back(lbm_def);\n+\n+\tfor (std::set<std::string>::const_iterator it = lbm_def->trigger_contents.begin();\n+\t\t\tit != lbm_def->trigger_contents.end(); ++it) {\n+\t\tstd::set<content_t> c_ids;\n+\t\tbool found = nodedef->getIds(*it, c_ids);\n+\t\tif (!found) {\n+\t\t\tcontent_t c_id = gamedef->allocateUnknownNodeId(*it);\n+\t\t\tif (c_id == CONTENT_IGNORE) {\n+\t\t\t\t// Seems it can't be allocated.\n+\t\t\t\twarningstream << \"Could not internalize node name \\\"\" << *it\n+\t\t\t\t\t<< \"\\\" while loading LBM \\\"\" << lbm_def->name << \"\\\".\" << std::endl;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tc_ids.insert(c_id);\n+\t\t}\n+\n+\t\tfor (std::set<content_t>::const_iterator iit =\n+\t\t\t\tc_ids.begin(); iit != c_ids.end(); ++iit) {\n+\t\t\tcontent_t c_id = *iit;\n+\t\t\tcontainer_map::iterator jt = map.find(c_id);\n+\t\t\tif (jt == map.end()) {\n+\t\t\t\tstd::vector<LoadingBlockModifierDef *> def_list;\n+\t\t\t\tmap[c_id] = def_list;\n+\t\t\t\tjt = map.find(c_id);\n+\t\t\t}\n+\t\t\tjt->second.push_back(lbm_def);\n+\t\t}\n+\t}\n+}\n+\n+const std::vector<LoadingBlockModifierDef *> *\n+\t\tLBMContentMapping::lookup(content_t c) const\n+{\n+\tcontainer_map::const_iterator it = map.find(c);\n+\tif (it == map.end())\n+\t\treturn NULL;\n+\t// This first dereferences the iterator, returning\n+\t// a std::vector<LoadingBlockModifierDef *>\n+\t// reference, then we convert it to a pointer.\n+\treturn &(it->second);\n+}\n+\n+LBMManager::~LBMManager()\n+{\n+\tfor (std::map<u64, LoadingBlockModifierDef *>::iterator it = m_lbm_defs.begin();\n+\t\t\tit != m_lbm_defs.end(); ++it) {\n+\t\tdelete it->second;\n+\t}\n+}\n+\n+void LBMManager::addLBMDef(LoadingBlockModifierDef *lbm_def)\n+{\n+\t// Precondition, in query mode the map isn't used anymore\n+\tFATAL_ERROR_IF(m_query_mode == true,\n+\t\t\"attempted to modify LBMManager in query mode\");\n+\tm_lbm_defs[lbm_def->nameHash] = lbm_def;\n+}\n+\n+void LBMManager::loadIntroductionTimes(const std::string &times,\n+\t\tIGameDef *gamedef, u32 now)\n+{\n+\tm_query_mode = true;\n+\n+\t// nameHash -> time map.\n+\t// Storing it in a map first instead of\n+\t// handling the stuff directly in the loop\n+\t// removes all duplicate entries.\n+\tstd::map<u64, u32> introduction_times;\n+\n+\t/*\n+\tThe introduction times string consists of nameHash:time entries,\n+\twith each entry terminated by a semicolon.\n+\tnameHash and time are decimal.\n+\t */\n+\n+\tsize_t idx = 0;\n+\tsize_t idx_new;\n+\twhile ((idx_new = times.find(\";\", idx)) != std::string::npos) {\n+\t\t// use stoi64 because stoi returns\n+\t\t// s32 not u32, that bit _can_ be set","path":"src/environment.cpp","position":101,"original_position":101,"commit_id":"dad0791fe482da9596bd83450a95a8f2a0f77db6","original_commit_id":"dad0791fe482da9596bd83450a95a8f2a0f77db6","user":{"login":"ShadowNinja","id":3399154,"avatar_url":"https://avatars.githubusercontent.com/u/3399154?v=3","gravatar_id":"","url":"https://api.github.com/users/ShadowNinja","html_url":"https://github.com/ShadowNinja","followers_url":"https://api.github.com/users/ShadowNinja/followers","following_url":"https://api.github.com/users/ShadowNinja/following{/other_user}","gists_url":"https://api.github.com/users/ShadowNinja/gists{/gist_id}","starred_url":"https://api.github.com/users/ShadowNinja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ShadowNinja/subscriptions","organizations_url":"https://api.github.com/users/ShadowNinja/orgs","repos_url":"https://api.github.com/users/ShadowNinja/repos","events_url":"https://api.github.com/users/ShadowNinja/events{/privacy}","received_events_url":"https://api.github.com/users/ShadowNinja/received_events","type":"User","site_admin":false},"body":"Old comment.","created_at":"2016-03-04T06:23:23Z","updated_at":"2016-03-04T06:23:23Z","html_url":"https://github.com/minetest/minetest/pull/3677#discussion_r54994259","pull_request_url":"https://api.github.com/repos/minetest/minetest/pulls/3677","_links":{"self":{"href":"https://api.github.com/repos/minetest/minetest/pulls/comments/54994259"},"html":{"href":"https://github.com/minetest/minetest/pull/3677#discussion_r54994259"},"pull_request":{"href":"https://api.github.com/repos/minetest/minetest/pulls/3677"}}},"pull_request":{"url":"https://api.github.com/repos/minetest/minetest/pulls/3677","id":58712344,"html_url":"https://github.com/minetest/minetest/pull/3677","diff_url":"https://github.com/minetest/minetest/pull/3677.diff","patch_url":"https://github.com/minetest/minetest/pull/3677.patch","issue_url":"https://api.github.com/repos/minetest/minetest/issues/3677","number":3677,"state":"open","locked":false,"title":"Add minetest.register_lbm() to run code on block load only","user":{"login":"est31","id":8872119,"avatar_url":"https://avatars.githubusercontent.com/u/8872119?v=3","gravatar_id":"","url":"https://api.github.com/users/est31","html_url":"https://github.com/est31","followers_url":"https://api.github.com/users/est31/followers","following_url":"https://api.github.com/users/est31/following{/other_user}","gists_url":"https://api.github.com/users/est31/gists{/gist_id}","starred_url":"https://api.github.com/users/est31/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/est31/subscriptions","organizations_url":"https://api.github.com/users/est31/orgs","repos_url":"https://api.github.com/users/est31/repos","events_url":"https://api.github.com/users/est31/events{/privacy}","received_events_url":"https://api.github.com/users/est31/received_events","type":"User","site_admin":false},"body":"Adds a new callback `minetest.register_lbm(def)` which can be used by mods to execute code when blocks load only.\r\n\r\nIt is intended to give a faster alternative for ABMs for the \"replacement ABM\" usecase. For such usecase, the block modifier only has to be run on blocks once. ABMs have a very wasteful behaviour here: they run on the block multiple times, in regular intervals. Increasing the interval helps, but the ABM still gets executed repeatedly.\r\n\r\nThe new LBM (loading block modifier) mechanism improves upon this in two ways from a speed standpoint:\r\n\r\n1. The callback only gets executed if a block gets loaded. No more intervals.\r\n\r\n1. There is an additional check (\"introducement time optimisation\") built in which tracks when the LBM was added to the environment, and only executes the callback if the block is from before the LBM addition. If the LBM got removed in the meantime, the engine tracks this and resets the counter.\r\n\r\n#### FAQ\r\n\r\n*Why not make it a part of ABMs?* : LBMs and ABMs are very similar in many regards, but are too different if you do a closer look.\r\n\r\nHalf of the ABM definition table entries are about the trigger mechanism (chance, interval, etc) which is entirely different from LBMs. LBMs on the other hand are named. Names are required for LBMs due to the \"introducement time optimisation\", imposing this on ABMs isn't possible for backwards compat reasons.\r\n\r\nAlso, ABMs have additional features LBMs lack (neighbouring nodes, the count params in the callback). This is because these features aren't really useful for the LBM use cases (which is mainly replacing replacement ABMs). And it allows for a simpler design in the engine, which is already complicated enough due to optimisation.\r\n\r\nSo if you have `def` tables which are almost completely different, you can of course unify them by force, but it will make docs more complicated, where every entry has a comment \"only applies for ABMs\" or \"required for LBMs\" etc. It would make things more complicated to the modder, which is the opposite of what the API should try to achieve.\r\n\r\n#### TODO:\r\n\r\n- [x] Test it, I only know it compiles, nothing more\r\n- [x] Investigate whether it might be possible to allow both group usage and unregistered node usage in the LBM definition *DONE it should work now with implementing @kahrl 's idea*\r\n- [x] Add a version field to the env vars encoding the version of the introducement times format. This ensures future compatibility. *DONE*\r\n- [x] ~~Support `chance` param? It would enable the \"adding new ores to existing world\" use case.~~ *decided not to. such a param can still be added later on, adding ores to existing maps would most probably benefit more from an api specific to that purpose that looks a lot like `register_ore`, perhaps even a simple bool param to `register_ore` is enough. *\r\n- [x] Add `run_at_every_load` param. If set to true, the introducement time optimisation gets turned off, meaning that the LBM is executed every time the block is loaded.\r\n- [x] Somehow handle to LBMs of the same name being specified. Either disallow, or take the more recent one. *seems to be DONE: the most recent one seems to be taken*","created_at":"2016-02-09T07:14:28Z","updated_at":"2016-03-04T06:23:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b0e7718f91da5cff0185c24b7b3057a5fb48da37","assignee":null,"milestone":{"url":"https://api.github.com/repos/minetest/minetest/milestones/7","html_url":"https://github.com/minetest/minetest/milestones/0.4.14","labels_url":"https://api.github.com/repos/minetest/minetest/milestones/7/labels","id":1601315,"number":7,"title":"0.4.14","description":"This milestone for issues which should get resolved before the 0.4.14 release.","creator":{"login":"kahrl","id":630411,"avatar_url":"https://avatars.githubusercontent.com/u/630411?v=3","gravatar_id":"","url":"https://api.github.com/users/kahrl","html_url":"https://github.com/kahrl","followers_url":"https://api.github.com/users/kahrl/followers","following_url":"https://api.github.com/users/kahrl/following{/other_user}","gists_url":"https://api.github.com/users/kahrl/gists{/gist_id}","starred_url":"https://api.github.com/users/kahrl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kahrl/subscriptions","organizations_url":"https://api.github.com/users/kahrl/orgs","repos_url":"https://api.github.com/users/kahrl/repos","events_url":"https://api.github.com/users/kahrl/events{/privacy}","received_events_url":"https://api.github.com/users/kahrl/received_events","type":"User","site_admin":false},"open_issues":19,"closed_issues":13,"state":"open","created_at":"2016-02-23T23:07:27Z","updated_at":"2016-03-04T02:42:54Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/minetest/minetest/pulls/3677/commits","review_comments_url":"https://api.github.com/repos/minetest/minetest/pulls/3677/comments","review_comment_url":"https://api.github.com/repos/minetest/minetest/pulls/comments{/number}","comments_url":"https://api.github.com/repos/minetest/minetest/issues/3677/comments","statuses_url":"https://api.github.com/repos/minetest/minetest/statuses/dad0791fe482da9596bd83450a95a8f2a0f77db6","head":{"label":"est31:loading_bm","ref":"loading_bm","sha":"dad0791fe482da9596bd83450a95a8f2a0f77db6","user":{"login":"est31","id":8872119,"avatar_url":"https://avatars.githubusercontent.com/u/8872119?v=3","gravatar_id":"","url":"https://api.github.com/users/est31","html_url":"https://github.com/est31","followers_url":"https://api.github.com/users/est31/followers","following_url":"https://api.github.com/users/est31/following{/other_user}","gists_url":"https://api.github.com/users/est31/gists{/gist_id}","starred_url":"https://api.github.com/users/est31/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/est31/subscriptions","organizations_url":"https://api.github.com/users/est31/orgs","repos_url":"https://api.github.com/users/est31/repos","events_url":"https://api.github.com/users/est31/events{/privacy}","received_events_url":"https://api.github.com/users/est31/received_events","type":"User","site_admin":false},"repo":{"id":28881630,"name":"minetest","full_name":"est31/minetest","owner":{"login":"est31","id":8872119,"avatar_url":"https://avatars.githubusercontent.com/u/8872119?v=3","gravatar_id":"","url":"https://api.github.com/users/est31","html_url":"https://github.com/est31","followers_url":"https://api.github.com/users/est31/followers","following_url":"https://api.github.com/users/est31/following{/other_user}","gists_url":"https://api.github.com/users/est31/gists{/gist_id}","starred_url":"https://api.github.com/users/est31/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/est31/subscriptions","organizations_url":"https://api.github.com/users/est31/orgs","repos_url":"https://api.github.com/users/est31/repos","events_url":"https://api.github.com/users/est31/events{/privacy}","received_events_url":"https://api.github.com/users/est31/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/est31/minetest","description":"Minetest, an open source infinite-world block sandbox game with survival and crafting. [also [minetest_game](https://github.com/minetest/minetest_game)]","fork":true,"url":"https://api.github.com/repos/est31/minetest","forks_url":"https://api.github.com/repos/est31/minetest/forks","keys_url":"https://api.github.com/repos/est31/minetest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/est31/minetest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/est31/minetest/teams","hooks_url":"https://api.github.com/repos/est31/minetest/hooks","issue_events_url":"https://api.github.com/repos/est31/minetest/issues/events{/number}","events_url":"https://api.github.com/repos/est31/minetest/events","assignees_url":"https://api.github.com/repos/est31/minetest/assignees{/user}","branches_url":"https://api.github.com/repos/est31/minetest/branches{/branch}","tags_url":"https://api.github.com/repos/est31/minetest/tags","blobs_url":"https://api.github.com/repos/est31/minetest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/est31/minetest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/est31/minetest/git/refs{/sha}","trees_url":"https://api.github.com/repos/est31/minetest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/est31/minetest/statuses/{sha}","languages_url":"https://api.github.com/repos/est31/minetest/languages","stargazers_url":"https://api.github.com/repos/est31/minetest/stargazers","contributors_url":"https://api.github.com/repos/est31/minetest/contributors","subscribers_url":"https://api.github.com/repos/est31/minetest/subscribers","subscription_url":"https://api.github.com/repos/est31/minetest/subscription","commits_url":"https://api.github.com/repos/est31/minetest/commits{/sha}","git_commits_url":"https://api.github.com/repos/est31/minetest/git/commits{/sha}","comments_url":"https://api.github.com/repos/est31/minetest/comments{/number}","issue_comment_url":"https://api.github.com/repos/est31/minetest/issues/comments{/number}","contents_url":"https://api.github.com/repos/est31/minetest/contents/{+path}","compare_url":"https://api.github.com/repos/est31/minetest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/est31/minetest/merges","archive_url":"https://api.github.com/repos/est31/minetest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/est31/minetest/downloads","issues_url":"https://api.github.com/repos/est31/minetest/issues{/number}","pulls_url":"https://api.github.com/repos/est31/minetest/pulls{/number}","milestones_url":"https://api.github.com/repos/est31/minetest/milestones{/number}","notifications_url":"https://api.github.com/repos/est31/minetest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/est31/minetest/labels{/name}","releases_url":"https://api.github.com/repos/est31/minetest/releases{/id}","deployments_url":"https://api.github.com/repos/est31/minetest/deployments","created_at":"2015-01-06T20:18:47Z","updated_at":"2016-03-03T07:19:14Z","pushed_at":"2016-03-03T17:31:32Z","git_url":"git://github.com/est31/minetest.git","ssh_url":"git@github.com:est31/minetest.git","clone_url":"https://github.com/est31/minetest.git","svn_url":"https://github.com/est31/minetest","homepage":"http://minetest.net/","size":45656,"stargazers_count":3,"watchers_count":3,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":3,"default_branch":"github_stupid_forcepush_annoying"}},"base":{"label":"minetest:master","ref":"master","sha":"7bcbc0105b3e67b7e066be6fd77775769cffdd16","user":{"login":"minetest","id":2624745,"avatar_url":"https://avatars.githubusercontent.com/u/2624745?v=3","gravatar_id":"","url":"https://api.github.com/users/minetest","html_url":"https://github.com/minetest","followers_url":"https://api.github.com/users/minetest/followers","following_url":"https://api.github.com/users/minetest/following{/other_user}","gists_url":"https://api.github.com/users/minetest/gists{/gist_id}","starred_url":"https://api.github.com/users/minetest/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/minetest/subscriptions","organizations_url":"https://api.github.com/users/minetest/orgs","repos_url":"https://api.github.com/users/minetest/repos","events_url":"https://api.github.com/users/minetest/events{/privacy}","received_events_url":"https://api.github.com/users/minetest/received_events","type":"Organization","site_admin":false},"repo":{"id":2168780,"name":"minetest","full_name":"minetest/minetest","owner":{"login":"minetest","id":2624745,"avatar_url":"https://avatars.githubusercontent.com/u/2624745?v=3","gravatar_id":"","url":"https://api.github.com/users/minetest","html_url":"https://github.com/minetest","followers_url":"https://api.github.com/users/minetest/followers","following_url":"https://api.github.com/users/minetest/following{/other_user}","gists_url":"https://api.github.com/users/minetest/gists{/gist_id}","starred_url":"https://api.github.com/users/minetest/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/minetest/subscriptions","organizations_url":"https://api.github.com/users/minetest/orgs","repos_url":"https://api.github.com/users/minetest/repos","events_url":"https://api.github.com/users/minetest/events{/privacy}","received_events_url":"https://api.github.com/users/minetest/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/minetest/minetest","description":"Minetest, an open source infinite-world block sandbox game with survival and crafting. [also https://github.com/minetest/minetest_game]","fork":false,"url":"https://api.github.com/repos/minetest/minetest","forks_url":"https://api.github.com/repos/minetest/minetest/forks","keys_url":"https://api.github.com/repos/minetest/minetest/keys{/key_id}","collaborators_url":"https://api.github.com/repos/minetest/minetest/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/minetest/minetest/teams","hooks_url":"https://api.github.com/repos/minetest/minetest/hooks","issue_events_url":"https://api.github.com/repos/minetest/minetest/issues/events{/number}","events_url":"https://api.github.com/repos/minetest/minetest/events","assignees_url":"https://api.github.com/repos/minetest/minetest/assignees{/user}","branches_url":"https://api.github.com/repos/minetest/minetest/branches{/branch}","tags_url":"https://api.github.com/repos/minetest/minetest/tags","blobs_url":"https://api.github.com/repos/minetest/minetest/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/minetest/minetest/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/minetest/minetest/git/refs{/sha}","trees_url":"https://api.github.com/repos/minetest/minetest/git/trees{/sha}","statuses_url":"https://api.github.com/repos/minetest/minetest/statuses/{sha}","languages_url":"https://api.github.com/repos/minetest/minetest/languages","stargazers_url":"https://api.github.com/repos/minetest/minetest/stargazers","contributors_url":"https://api.github.com/repos/minetest/minetest/contributors","subscribers_url":"https://api.github.com/repos/minetest/minetest/subscribers","subscription_url":"https://api.github.com/repos/minetest/minetest/subscription","commits_url":"https://api.github.com/repos/minetest/minetest/commits{/sha}","git_commits_url":"https://api.github.com/repos/minetest/minetest/git/commits{/sha}","comments_url":"https://api.github.com/repos/minetest/minetest/comments{/number}","issue_comment_url":"https://api.github.com/repos/minetest/minetest/issues/comments{/number}","contents_url":"https://api.github.com/repos/minetest/minetest/contents/{+path}","compare_url":"https://api.github.com/repos/minetest/minetest/compare/{base}...{head}","merges_url":"https://api.github.com/repos/minetest/minetest/merges","archive_url":"https://api.github.com/repos/minetest/minetest/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/minetest/minetest/downloads","issues_url":"https://api.github.com/repos/minetest/minetest/issues{/number}","pulls_url":"https://api.github.com/repos/minetest/minetest/pulls{/number}","milestones_url":"https://api.github.com/repos/minetest/minetest/milestones{/number}","notifications_url":"https://api.github.com/repos/minetest/minetest/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/minetest/minetest/labels{/name}","releases_url":"https://api.github.com/repos/minetest/minetest/releases{/id}","deployments_url":"https://api.github.com/repos/minetest/minetest/deployments","created_at":"2011-08-07T13:48:36Z","updated_at":"2016-03-04T04:39:11Z","pushed_at":"2016-03-04T04:26:00Z","git_url":"git://github.com/minetest/minetest.git","ssh_url":"git@github.com:minetest/minetest.git","clone_url":"https://github.com/minetest/minetest.git","svn_url":"https://github.com/minetest/minetest","homepage":"http://minetest.net/","size":92477,"stargazers_count":1834,"watchers_count":1834,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":601,"mirror_url":null,"open_issues_count":746,"forks":601,"open_issues":746,"watchers":1834,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/minetest/minetest/pulls/3677"},"html":{"href":"https://github.com/minetest/minetest/pull/3677"},"issue":{"href":"https://api.github.com/repos/minetest/minetest/issues/3677"},"comments":{"href":"https://api.github.com/repos/minetest/minetest/issues/3677/comments"},"review_comments":{"href":"https://api.github.com/repos/minetest/minetest/pulls/3677/comments"},"review_comment":{"href":"https://api.github.com/repos/minetest/minetest/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/minetest/minetest/pulls/3677/commits"},"statuses":{"href":"https://api.github.com/repos/minetest/minetest/statuses/dad0791fe482da9596bd83450a95a8f2a0f77db6"}}}}