{"action":"created","issue":{"url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/955","labels_url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/955/labels{/name}","comments_url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/955/comments","events_url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/955/events","html_url":"https://github.com/OpenMeridian/Meridian59/pull/955","id":66333954,"number":955,"title":"Add multi-language support for resources to compiler, server and client. Add proper C-style for and do-while loops, switch-case and elseif statements to kod. Add pre/post increment-decrement operators.","user":{"login":"skittles1","id":4743083,"avatar_url":"https://avatars.githubusercontent.com/u/4743083?v=3","gravatar_id":"","url":"https://api.github.com/users/skittles1","html_url":"https://github.com/skittles1","followers_url":"https://api.github.com/users/skittles1/followers","following_url":"https://api.github.com/users/skittles1/following{/other_user}","gists_url":"https://api.github.com/users/skittles1/gists{/gist_id}","starred_url":"https://api.github.com/users/skittles1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skittles1/subscriptions","organizations_url":"https://api.github.com/users/skittles1/orgs","repos_url":"https://api.github.com/users/skittles1/repos","events_url":"https://api.github.com/users/skittles1/events{/privacy}","received_events_url":"https://api.github.com/users/skittles1/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/OpenMeridian/Meridian59/milestones/91","html_url":"https://github.com/OpenMeridian/Meridian59/milestones/1.0.15.0","labels_url":"https://api.github.com/repos/OpenMeridian/Meridian59/milestones/91/labels","id":1217328,"number":91,"title":"1.0.15.0","description":"","creator":{"login":"skittles1","id":4743083,"avatar_url":"https://avatars.githubusercontent.com/u/4743083?v=3","gravatar_id":"","url":"https://api.github.com/users/skittles1","html_url":"https://github.com/skittles1","followers_url":"https://api.github.com/users/skittles1/followers","following_url":"https://api.github.com/users/skittles1/following{/other_user}","gists_url":"https://api.github.com/users/skittles1/gists{/gist_id}","starred_url":"https://api.github.com/users/skittles1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/skittles1/subscriptions","organizations_url":"https://api.github.com/users/skittles1/orgs","repos_url":"https://api.github.com/users/skittles1/repos","events_url":"https://api.github.com/users/skittles1/events{/privacy}","received_events_url":"https://api.github.com/users/skittles1/received_events","type":"User","site_admin":false},"open_issues":0,"closed_issues":9,"state":"closed","created_at":"2015-07-21T03:44:10Z","updated_at":"2015-08-18T15:49:32Z","due_on":null,"closed_at":"2015-08-18T15:49:32Z"},"comments":5,"created_at":"2015-04-04T15:42:30Z","updated_at":"2015-08-18T20:56:35Z","closed_at":"2015-08-18T15:48:11Z","pull_request":{"url":"https://api.github.com/repos/OpenMeridian/Meridian59/pulls/955","html_url":"https://github.com/OpenMeridian/Meridian59/pull/955","diff_url":"https://github.com/OpenMeridian/Meridian59/pull/955.diff","patch_url":"https://github.com/OpenMeridian/Meridian59/pull/955.patch"},"body":"### Language/resource changes ###\r\nThis pull request adds support for 184 different languages to kod. The compiler looks for a language identifier string (ISO 639-1, e.g. de, ko, sv) and if present the resource string is stored at that position in an array of const_type in the resource_type struct. If no language ID string is present, the English one is assigned by default. Multiple language resources can be defined for the same resource name, as long as they are defined in the same class (same name in different classes will throw an error to help prevent mistakes).\r\n\r\nResources can now be added to a separate file which can be added as an include in the resources: section of the kod code, with the same syntax as other include directives. Support has been added for kod recompilation if a file with the extension .lkod and the same filename is modified, but include files with other names will not cause a recompilation if modified (i.e. the kod file itself should be touched to force nmake to recompile it). The included file must end with a blank line.\r\n\r\nThe client has a new menu in the toolbar, Language, in which the user can select which display language they would like to use out of the available languages. When the client reads in resources from the rsc or rsb files, it keeps track of which languages have been seen to later populate this menu (so one string for a language would allow that language to be selected). If a language is selected but not all resources are present for that language, it will default to English. Menu example: http://i.imgur.com/uyTJa3R.png. This menu will likely be moved out of the top level in the future, but for now I would like it to have visibility among players (who often do not read update notes).\r\n\r\nThe StringContain and StringEqual C functions will perform string comparisons using every available language if a resource is passed in as one of the parameters, so that the server can successfully match both English and German commands to the correct resource. Other string-handling C functions use the server's language choice, settable using the Language config field (integer, same values as the language ID table). The command for this is:\r\n```\r\nset config int [Resource] language 1\r\n```\r\nfor German, and:\r\n```\r\nset config int [Resource] language 0\r\n```\r\nfor English (the default).\r\n\r\nResource example:\r\n```\r\nobject_name_rsc = \"something\"\r\nobject_name_rsc = de \"etwas\"\r\n```\r\n\r\nmake_resource now adds its (new) completed resources to the resource list for the current class, and when each new resource is created it is first checked against this list. If a duplicate resource ID is encountered, the appropriate language ID (resource array position) is checked and if a string with the same language ID is already present, an error is thrown. New resources are returned to the parser, ones that existed already are not.\r\n\r\n### Other compiler changes ###\r\nSeveral other new features have been added to the compiler.\r\n#### pre/post increment/decrement operators ####\r\nSyntax: i++, --i.\r\nPre-inc/decrement increments or decrements the value of the variable by 1, assigns it to the variable then uses the new value in the expression. Post-inc/decrement uses the old value of the variable in the expression, but increments or decrements the variable by 1 after it is used.\r\n#### for i in list changed to foreach in list ####\r\nThe keyword for list iteration has been changed from \"for\" to \"foreach\". \"for\" will no longer work in this context, to remove any future confusion with the new for loop.\r\n#### C-style for loop ####\r\nSyntax: for(assignments; expression; assignments) { statements }\r\nAny of these fields can be blank (i.e. for(;;){}). Multiple comma-separated assignments can be performed in either assignment field. The first field of assignments are performed prior to executing the loop or checking the expression, the second field after the loop has executed (i.e. iteration).\r\n#### C-style do-while loop ####\r\nSyntax: do{statements} while expression;\r\nSame as a while loop, except the statements inside the loop are performed once before the expression is checked.\r\n#### C-style switch-case statement ####\r\nSyntax: switch(expression) { case expression: statements }\r\nWorks the same as in C - the value of the expression in the switch is matched to that in the cases. Default can also be used (with no expression) and is checked last. Break will exit the switch statement (as will continue) and the absence of a break will cause fallthrough to the next case (or the default) in order of how the code is written (i.e. a default placed in the middle of a block of cases with no break will fallthrough to the next case, even though the default is the last evaluation checked).\r\n#### else if statement ####\r\nSyntax: if expression { statements } else if expression {statements } else { statements }\r\nWorks as might be expected, expressions are checked in order and if successful, no other expressions are checked. \"else if\" cannot come after an \"else\", and the terminal \"else\" is optional.\r\n\r\n### Message and call timing/blakod interpreting performance ###\r\nCode has been added to track run time on every C call and kod message executed. This uses QueryPerformanceCounter for accurate microsecond or better timing. The timing can be activated using the \"Timecalls\" server config (boolean) and is off by default due to incompatibility with Amazon's VMs (a QPC call on the VM requires ~4 microseconds, unacceptable for tracking every call). Existing timing of top-level messages and overall interpreting time has been upgraded to use microseconds instead of milliseconds, as keeping track of interpreting time in milliseconds is inaccurate. The QPC overhead exists for this also, but is unavoidable in this case.\r\nTwo config checks have been removed from the InterpretAtMessage function (DEBUG_INITLOCALS and BLAKOD_MAX_STATEMENTS). The max statements config option is now a define. The removal of both config checks reduces interpreting time by ~35%.\r\n\r\n### API/Protocol changes\r\n#### RSC format changes\r\nPrevious RSC format:\r\nRSC header bytes (0x52, 0x53, 0x43, 0x01), RSC_VERSION, num_resources,\r\nRSC_ID, STRING, RSC_ID, STRING...\r\n\r\nNew RSC format:\r\nRSB header bytes (0x52, 0x53, 0x43, 0x01), RSC_VERSION, num_resources,\r\nRSC_ID, LANGUAGE_ID, STRING, RSC_ID, LANGUAGE_ID, STRING...\r\n\r\n#### Number parameters for inline variables\r\nExample message from server: (4 byte rsc_id_one, 4 byte rsc_id_two, 4 byte rsc_id_three)\r\nExample resource string 1: \"You hit the %s%s with your %s\"\r\nClient displays resources in order.\r\nExample resource string 2, same server message: \"You use your %s$3 to hit the %s$0%s$1\"\r\nClient reorders the message so that rsc_id_one is in the third position and rsc_id_three is in the first. rsc_id_two is not reordered, but is skipped when displaying the resources. Any reordering done during a recursive CheckMessageOrder call is preserved (but does not affect anything outside the scope of its own call). If the %r has the number parameter, everything it references is moved to the new position.\r\n\r\n#### Player description fixed-strings (age, guild, faction, etc.) sent as resources.\r\nThe fixed-strings at the top of the player description were previously sent in one string, after the actual editable description part and before the URL. This is now sent as (mostly) resources, so the client should process it as it would any other resource. The description drawing is handled by BP_USER_COMMAND sub-protocol UC_LOOK_PLAYER.\r\n\r\n### KOD changes ###\r\n* Any system that used AppendTempString to build up a string to send to the client has been modified to build a packet with resource IDs instead. This is most apparent in spell and item descriptions where the structure of the code for displaying the description has been completely changed.\r\n* A new message in room.kod, SendCopyPacketAllInRoom(), has been added to use the C function SendCopyPacket() to send a packet to all users in the room, to avoid rebuilding packets where possible (the equivalent to sending everyone the same built-up temp string).\r\n* The System object has a new table, phSkills, which keeps track of skills in the same way as spells. Previously skills were only kept as a list (likely due to the small number of them) but skill lookup is frequent enough to require a table (imo).\r\n* RecalcLightAndWeather() in room.kod has been modified to make less message calls (calls which iterate through the same list). System.NewHour() calls this message and is one of the slowest frequently called messages.\r\n* The LightDiscipleRobe class was nearly entirely duplicated from DiscipleRobe, and has been made a child class with the duplicated code removed. Also, all disciple robes now give 5 spellpower instead of 4 as the first level spellpower bonus to the same school (removing the unwanted scenario where an off-school robe is better for level 1).\r\n* Added GetRegion() overrides to several rooms (performance).\r\n* GetSpellAbility() and GetSkillAbility() in player.kod no longer make message calls (performance).\r\n* Many areas of code have been converted to use else if or switches for performance reasons and/or code readability.\r\n\r\nSeveral systems still need to be modified and will build up strings/temp strings to send to users. These systems will be affected by the server's language choice, so the server admin can default them to use either English or German. The systems not yet modified are:\r\n* Quest NPC text.\r\n* Guildmaster's war book and Caramo's Book of Jala (Justicar book).\r\n* Honor strings (except the \"newbie tag\", which is sent as a resource separately).\r\n* The frenzy War Event.\r\n* Necromancer guild name (and guild/player names in general).\r\n* Debug/GodLog strings.\r\n* Cardinal/ordinal strings in system.kod."},"comment":{"url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/comments/132348275","html_url":"https://github.com/OpenMeridian/Meridian59/pull/955#issuecomment-132348275","issue_url":"https://api.github.com/repos/OpenMeridian/Meridian59/issues/955","id":132348275,"user":{"login":"Meridian59","id":2267041,"avatar_url":"https://avatars.githubusercontent.com/u/2267041?v=3","gravatar_id":"","url":"https://api.github.com/users/Meridian59","html_url":"https://github.com/Meridian59","followers_url":"https://api.github.com/users/Meridian59/followers","following_url":"https://api.github.com/users/Meridian59/following{/other_user}","gists_url":"https://api.github.com/users/Meridian59/gists{/gist_id}","starred_url":"https://api.github.com/users/Meridian59/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Meridian59/subscriptions","organizations_url":"https://api.github.com/users/Meridian59/orgs","repos_url":"https://api.github.com/users/Meridian59/repos","events_url":"https://api.github.com/users/Meridian59/events{/privacy}","received_events_url":"https://api.github.com/users/Meridian59/received_events","type":"User","site_admin":false},"created_at":"2015-08-18T20:56:35Z","updated_at":"2015-08-18T20:56:35Z","body":"I don't see the language changes as worth the amount of time it would take\nfor me to update everything.  With the amount of work you guys were doing,\nit was probably inevitable that there would be a major incompatibility like\nthis at some point.\n\nOn Tue, Aug 18, 2015 at 12:18 PM, Daenks <notifications@github.com> wrote:\n\n> We discussed the new KOD features and decided that they are so common\n> across every beginner language that exists these days that it no longer\n> makes a ton of difference. Plus to effectively code in KOD you already have\n> to deal with an event system, OOP concepts, and all kinds of \"programming\"\n> concepts.\n>\n> I think the benefits outweigh the detriments in this case.\n>\n> I can only speak for myself, but I think we would be willing to help you\n> convert your kod code to this new format.\n>\n> —\n> Reply to this email directly or view it on GitHub\n> <https://github.com/OpenMeridian/Meridian59/pull/955#issuecomment-132322868>\n> .\n>\n"}}