Kongregate Flash games fixer (future next version)

You can now chose between Flash and SuperNova to play Flash games on Kongregate!

As of 2022-02-09. See the latest version.

  1. // ==UserScript==
  2. // @name Kongregate Flash games fixer (future next version)
  3. // @version 3.2.3
  4. // @author Matrix4348
  5. // @namespace https://greasyfork.org/users/4818
  6. // @description You can now chose between Flash and SuperNova to play Flash games on Kongregate!
  7. // @license MIT
  8. // @match *://*.konggames.com/games/*/*/frame/*
  9. // @match *://www.kongregate.com/games/*/*
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. // Iframes part. The script must be limited to Flash iframes (the URL for the html games iframes look a bit different, but there may be some exceptions), so we will check if the iframe includes the variable kong_flash_variables.
  14. if ((document.URL.search("/frame/")>-1)&(document.body.innerHTML.search("kong_flash_variables")>-1)){
  15.  
  16. // First, we need to extract the link to the swf (the game file) and a few other things.
  17. var file_url0, file_url, file_url_base; // Basic URL.
  18. var my_first_link, my_second_link, blablabla, GameShellAPI; // For loading the games in a gameshell when they should, because in these cases the gameshell is required for submitting scores.
  19. var SNwidth, SNheight, my_bgcolor; // Parameters.
  20. var scripts=document.getElementsByTagName("script");
  21. for(var i=0; i<scripts.length;i++) {var script_text=scripts[i].text;
  22. var url_text;
  23. if(script_text.indexOf("game_swf")!== -1) {
  24. url_text=String(script_text.match(/game_swf\"\:\"(.*?)\"\,\"game_url/g));
  25. file_url0="https://"+decodeURIComponent(url_text.substring(17,(url_text.length/2)-11));
  26.  
  27. // Background color parameter for swf injection.
  28. my_bgcolor=script_text.substring(script_text.search("bgcolor")+10,script_text.search("bgcolor")+17);
  29.  
  30. // Flash, game shell and API.
  31. blablabla=String(script_text.match(/swfurl\"\:\"(.*?)\"\,\"flashvars/g));
  32. my_first_link=blablabla.substring(blablabla.search("//"),blablabla.search(".swf")+4);
  33. my_second_link=encodeURIComponent("http:"+file_url0.substring(file_url0.search("//"),file_url0.length)); // HTTPS WILL NOT MAKE THE API LOAD!
  34. var blabla=String(script_text.match(/kongregate_api_path(.*?)\"title/g));
  35. GameShellAPI=decodeURIComponent(blabla.substring(blabla.search("flash")-3,blabla.search(".swf")+4));
  36.  
  37. // Values for the SuperNova part. Note that they will only be correctly defined if they have three digits, which should always be the case.
  38. SNwidth=script_text.substring(script_text.search("width")+7,script_text.search("width")+10);
  39. SNheight=script_text.substring(script_text.search("height")+8,script_text.search("height")+11);
  40.  
  41. break;
  42. }
  43. else if(script_text.indexOf("swfurl")!== -1) {
  44. url_text=String(script_text.match(/swfurl\"\:\"(.*?)\"\,\"flashvars/g));
  45. file_url0=decodeURIComponent(url_text.substring(9,url_text.length-12));
  46.  
  47. // Background color parameter for swf injection.
  48. my_bgcolor=script_text.substring(script_text.search("bgcolor")+10,script_text.search("bgcolor")+17);
  49.  
  50. // Flash, game shell and API (even though, in this part of the loop, games do not need game shells).
  51. my_first_link=file_url0.substring(file_url0.search("//"),file_url0.length);
  52. my_second_link="";
  53. GameShellAPI="";
  54.  
  55. // Values for the SuperNova part. Note that they will only be correctly defined if they have three digits, which should always be the case.
  56. SNwidth=script_text.substring(script_text.search("width")+7,script_text.search("width")+10);
  57. SNheight=script_text.substring(script_text.search("height")+8,script_text.search("height")+11);
  58.  
  59. break;
  60. };
  61. };
  62. file_url=file_url0.substring(file_url0.search("//"),file_url0.length);
  63. if (file_url.search("/live/")>-1){
  64. file_url_base="http:"+file_url.substring(0,file_url.search("/live/")+6);
  65. }
  66. else {
  67. file_url_base="http:"+file_url.substring(0,file_url.search("/game_files/")+22);
  68. };
  69.  
  70. // Then, we build the functions that will load the games.
  71. function more_players(){
  72. var a=document.createElement("script");
  73. a.id="More choice";
  74. a.type="text/javascript";
  75. // IMPORTANT: The checkParams function (originally present in the webpage) inputs most of the flashvars into kong_flash_variables.
  76. a.innerHTML=
  77. `//<![CDATA[
  78. FlashLoader = {
  79. loadGame: function(urlOptions) {
  80. var swf_location = "`+my_first_link+`";
  81. var swfobject_flash_vars = {};
  82. if(typeof(kong_flash_variables) == "object"){
  83. for(var k in kong_flash_variables){
  84. swfobject_flash_vars[k] = encodeURIComponent(kong_flash_variables[k]);
  85. }
  86. }
  87. // Score API (re)activation part:
  88. swfobject_flash_vars.kongregate_flash_postmessage=true; // This line alone activates the API for a few (recent?) games.
  89. swfobject_flash_vars.api_path=swfobject_flash_vars.kongregate_api_path; // This one, combined with the previous one, will activate the API for most of the remaining ones.
  90. swfobject_flash_vars.api_host=swfobject_flash_vars.kongregate_api_host; // Needed? Useless?
  91. swfobject_flash_vars.game_url=swfobject_flash_vars.kongregate_game_url; // May be useless, or may reactivate API on games where we supposed it broken for good, who knows...
  92. swfobject_flash_vars.kongregate_stamp=swfobject_flash_vars.kongregate_game_auth_token; // May be useless, or may reactivate API on games where we supposed it broken for good, who knows...
  93. gameswfifgameshell="`+my_second_link+`";
  94. if(gameswfifgameshell.length!=0){
  95. swfobject_flash_vars.game_swf=gameswfifgameshell;
  96. swfobject_flash_vars.kongregate_api_path=encodeURIComponent("`+GameShellAPI+`"); // Yep, game shells need a different API file!
  97. swfobject_flash_vars.api_path=swfobject_flash_vars.kongregate_api_path;
  98. };
  99.  
  100. if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
  101. var d=document.createElement("div");
  102. d.id="gamediv";
  103. document.getElementById("game_wrapper").appendChild(d);
  104. swfobject.embedSWF(swf_location, "gamediv","100%","100%","6","/flash/expressInstall.swf",swfobject_flash_vars,{"bgcolor":"`+my_bgcolor+`","allownetworking":"all","allowscriptaccess":"always","base":"`+file_url_base+`"},{});
  105.  
  106. // Sometimes, if a browser does not support Adobe Flash Player, then swfobject.embedSWF may not work, leaving a mere black screen instead of a "this plugin is not supported" message.
  107. // Therefore, the game will be injected using another method, just so the users know that the script works.
  108. if (document.getElementById("gamediv").type==undefined){
  109. document.getElementById("gamediv").remove();
  110. var truc=document.createElement("object");
  111. truc.id="gamediv";
  112. truc.type="application/x-shockwave-flash";
  113. truc.data="`+my_first_link+`"
  114. truc.width="100%";
  115. truc.height="100%";
  116. var bgc=document.createElement("param"); bgc.name="bgcolor"; bgc.value="`+my_bgcolor+`"; truc.appendChild(bgc);
  117. var anw=document.createElement("param"); anw.name="allownetworking"; anw.value="all"; truc.appendChild(anw);
  118. var asa=document.createElement("param"); asa.name="allowscriptaccess"; asa.value="always"; truc.appendChild(asa);
  119. var b=document.createElement("param"); b.name="base"; b.value="`+file_url_base+`"; truc.appendChild(b);
  120. var fv0=""; for(var k in swfobject_flash_vars){fv0=fv0+k+"="+encodeURIComponent(swfobject_flash_vars[k])+"&"};
  121. var fv=document.createElement("param"); fv.name="flashvars"; fv.value=fv0.substring(0,fv0.length-1); truc.appendChild(fv);
  122. document.getElementById("game_wrapper").appendChild(truc);
  123. };
  124. }
  125. }
  126.  
  127. function play_with_Flash(urlOptions) {
  128. if (!urlOptions) {
  129. urlOptions = '';
  130. }
  131. FlashLoader.loadGame(urlOptions);
  132. document.fire('game:activated');
  133. };
  134.  
  135. var SNloadGame=function(A){
  136. var SNoptions = {
  137. "swfurl" : "http:`+file_url+`",
  138. "flashvars":{},
  139. "title" : ttgArgs.game_title,
  140. "width" : `+SNwidth+`,
  141. "height" : `+SNheight+`
  142. };
  143. if((typeof(kong_flash_variables) === 'object')&(typeof(supernova)==='object')){
  144. SNoptions.flashvars = $j.param(kong_flash_variables);
  145. if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
  146. var d=document.createElement("div");
  147. d.id="gamediv";
  148. document.getElementById("game_wrapper").appendChild(d);
  149. SNoptions.el = document.querySelector('#gamediv');
  150. supernova.launch(SNoptions);
  151. supernova.openGame(SNoptions);
  152. setTimeout(function(){delete SNloadGame;},1);
  153. }
  154. else if(A){setTimeout(function(B){SNloadGame(B);},10000,A--);}
  155. else{setTimeout(function(){delete SNloadGame;},1);}
  156. };
  157.  
  158. function play_with_SuperNova(){ SNloadGame(10); };
  159.  
  160. function play_with_Ruffle(){ // If it does not work, try also putting the instructions inside an onload parameters of ruffle.js, instead of loading ruffle.js, then another script.
  161. var r=document.createElement("script");
  162. r.type="text/javascript";
  163. r.src=""; // Sadly, the script must be on the Kongregate servers... Curse on that same-origin policy!
  164. document.body.appendChild(r);
  165. var swf_location = "`+file_url+`";
  166. var swfobject_flash_vars = {};
  167. if(typeof(kong_flash_variables) == "object"){
  168. for(var k in kong_flash_variables){
  169. swfobject_flash_vars[k] = encodeURIComponent(kong_flash_variables[k]);
  170. }
  171. }
  172. // In case of activation: remember to add the same extra flashvars, like for Flash, so the API will work.
  173. if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
  174. var RandomFunctionName=function(A){
  175. if(window.RufflePlayer!=null){
  176. window.RufflePlayer.config = {
  177. "publicPath": undefined,
  178. "contextMenu": true,
  179. "showSwfDownload": true,
  180. "menu": true,
  181. "quality": "high",
  182. };
  183. const ruffle = window.RufflePlayer.newest();
  184. const player = ruffle.createPlayer();
  185. const container = document.getElementById("game_wrapper");
  186. container.appendChild(player);
  187. player.load({
  188. url: swf_location,
  189. parameters: swfobject_flash_vars,
  190. allowScriptAccess: true
  191. });
  192. setTimeout(function(){delete RandomFunctionName;},1);
  193. }
  194. else if(A){setTimeout(function(B){RandomFunctionName(B);},10000,A--);}
  195. else{setTimeout(function(){delete RandomFunctionName;},1);}
  196. };
  197. RandomFunctionName(10);
  198. };
  199.  
  200. function time_to_play(){
  201. // I do not know exactly what channel_id is for. All I know is that it is in the iframe link and elsewhere, and that is is some kind of hexadecimal character string.
  202. // Thus, the presence of a modified (and unusual) channel_id in the iframes' URL will be used to tell which player we want to use.
  203. // Moreover, changing it only in the URL SEEMS not to change the value used for the flashvars.
  204.  
  205. // If we want the game to load with Flash:
  206. if(document.URL.search("me-wanna-Flash")>-1){ play_with_Flash(); }
  207. // If we want the game to load (properly!) with SuperNova:
  208. else if(document.URL.search("me-wanna-SuperNova")>-1){ play_with_SuperNova(); }
  209. // If we want the game to load with Ruffle:
  210. else if(document.URL.search("me-wanna-Ruffle")>-1){ play_with_Ruffle(); }
  211. // When the iframe loads normally (without a modified channel_id):
  212. else{
  213. function BrowVer(){ua=navigator.userAgent; return {Browser:ua.substring(ua.lastIndexOf(" ")+1,ua.lastIndexOf("/")),Version:ua.substring(ua.lastIndexOf("/")+1,ua.length)}};
  214. var b=BrowVer.Browser, v=BrowVer.Version;
  215. function FlashSupport(){
  216. var np=navigator.plugins, npl=np.length;
  217. for(var k=0;k<npl;k++){ if(np[k].name=="Shockwave Flash"){return true}; }
  218. return false;
  219. };
  220.  
  221. if(navigator.userAgent.search("Windows")==-1){ play_with_Flash(); } // Because SuperNova only works on Windows.
  222. else if(FlashSupport()==false){ play_with_SuperNova(); }
  223. else if(FlashSupport()==true){ play_with_Flash(); }
  224.  
  225. else if((b=="Edg")||(b=="Chrome")||(b=="Safari")){ play_with_SuperNova(); } // Useless but
  226. else if((b=="Basilisk")||(b=="PaleMoon")){ play_with_Flash(); } // could be useful
  227. else if((b=="Firefox")||(v<85)){ play_with_Flash(); } // in case of
  228. else if((b=="Firefox")||(v>=85)){ play_with_SuperNova(); } // a Ruffle
  229. else { play_with_Flash(); } // implementation.
  230. }
  231. };
  232. var time_to_play_but_at_the_correct_time=function(a){
  233. if(activateGame._alreadyActivated){
  234. time_to_play();
  235. setTimeout(function(){delete time_to_play_but_at_the_correct_time;},1);
  236. }
  237. else if(a){setTimeout(function(b){time_to_play_but_at_the_correct_time(b);},10000,a--);}
  238. else{setTimeout(function(){delete time_to_play_but_at_the_correct_time;},1);}
  239. };
  240. time_to_play_but_at_the_correct_time(10);
  241.  
  242. //]]>`;
  243. document.body.appendChild(a);
  244. };
  245. more_players();
  246. }
  247.  
  248. // Game pages part. Only for Flash games, so I will make sure that active_user.gameType()="flash".
  249. // I will make two "if" loops instead of one to avoid an error message in the console tab (even though this message would not break anything).
  250. else if (document.URL.search("www.kongregate.com/games/")>-1){
  251. if(active_user.gameType()=="flash"){
  252. // Useful variables.
  253. var urlstart=document.URL.substring(0,document.URL.search("://"));
  254.  
  255. var my_game_version, my_svid, my_game_width, my_game_height, my_game_left, my_game_top;
  256. var game_scripts=document.getElementById("game").getElementsByTagName("script");
  257. for(var j=0; j<game_scripts.length;j++) {var game_script_text=game_scripts[j].text;
  258. if((game_script_text.indexOf("game_version")!== -1)&(game_script_text.indexOf("svid")!== -1)) {
  259. my_game_version=game_script_text.substring(game_script_text.search("game_version")+14,game_script_text.search("flash_var_prefix")-2);
  260. my_svid=game_script_text.substring(game_script_text.search("svid")+7,game_script_text.search("game_type")-3);
  261. my_game_width=game_script_text.substring(game_script_text.search("game_width")+12,game_script_text.search("game_height")-2);
  262. my_game_height=game_script_text.substring(game_script_text.search("game_height")+13,game_script_text.search("max_game_width")-2);
  263. my_game_left=game_script_text.substring(game_script_text.search("game_left")+11,game_script_text.search("game_top")-2);
  264. my_game_top=game_script_text.substring(game_script_text.search("game_top")+10,game_script_text.search("iframe_class")-2);
  265. break;
  266. }
  267. };
  268.  
  269. // What will be inserted in the webpage, to load the different iframes we will use.
  270.  
  271. // I do not know what channel_id is used for, nor weither or not it is relevant as it changes everytime the game page is reloaded, but yet appears in the iframe link.
  272. // All I know is that is is some kind of hexadecimal characters string.
  273. // Thus, I will replace it with values that it will never take so that the script can detect which player it should load the game with.
  274.  
  275. var ic=document.createElement("script");
  276. ic.id="iframe constructors";
  277. ic.innerHTML=
  278. `//<![CDATA[
  279. FlashLoader = {
  280. loadGame: function(urlOptions) {
  281. new GameIframe({
  282. "auto_resize":null,
  283. "iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-Flash" + '/?kongregate_host=www.kongregate.com',
  284. "alternate_game_file_url":null,
  285. "game_width":`+my_game_width+`,
  286. "game_height":`+my_game_height+`,
  287. "max_game_width":null,
  288. "max_game_height":null,
  289. "game_left":`+my_game_left+`,
  290. "game_top":`+my_game_top+`,
  291. "iframe_class":"dont_hide",
  292. "host":"`+urlstart+`"+"://www.kongregate.com",
  293. "api_host":"`+urlstart+`"+"://api.kongregate.com",
  294. "api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
  295. "preview":false,
  296. "game_permalink":active_user.gamePermalink(),
  297. "game_id":active_user.gameId(),
  298. "game_url":"http://www.kongregate.com"+active_user.gamePath(),
  299. "game_version":`+my_game_version+`,
  300. "flash_var_prefix":"kv_",
  301. "post_message":true,
  302. "iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
  303. "game_host":"`+urlstart+`"+"://chat.kongregate.com",
  304. "channel_id":encodeURIComponent(channel_id),
  305. "svid":"`+my_svid+`",
  306. "game_type":"flash"
  307. },
  308. urlOptions, channel_id).createGameIframeElement();
  309.  
  310. }
  311. }
  312.  
  313. function LoadFlashIframe(urlOptions) {
  314. if (!urlOptions) {
  315. urlOptions = '';
  316. }
  317. FlashLoader.loadGame(urlOptions);
  318. document.fire('game:activated');
  319. };
  320.  
  321. SuperNovaLoader = {
  322. loadGame: function(urlOptions) {
  323. new GameIframe({
  324. "auto_resize":null,
  325. "iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-SuperNova" + '/?kongregate_host=www.kongregate.com',
  326. "alternate_game_file_url":null,
  327. "game_width":`+my_game_width+`,
  328. "game_height":`+my_game_height+`,
  329. "max_game_width":null,
  330. "max_game_height":null,
  331. "game_left":`+my_game_left+`,
  332. "game_top":`+my_game_top+`,
  333. "iframe_class":"dont_hide",
  334. "host":"`+urlstart+`"+"://www.kongregate.com",
  335. "api_host":"`+urlstart+`"+"://api.kongregate.com",
  336. "api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
  337. "preview":false,
  338. "game_permalink":active_user.gamePermalink(),
  339. "game_id":active_user.gameId(),
  340. "game_url":"http://www.kongregate.com"+active_user.gamePath(),
  341. "game_version":`+my_game_version+`,
  342. "flash_var_prefix":"kv_",
  343. "post_message":true,
  344. "iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
  345. "game_host":"`+urlstart+`"+"://chat.kongregate.com",
  346. "channel_id":encodeURIComponent(channel_id),
  347. "svid":"`+my_svid+`",
  348. "game_type":"flash"
  349. },
  350. urlOptions, channel_id).createGameIframeElement();
  351.  
  352. }
  353. }
  354.  
  355. function LoadSuperNovaIframe(urlOptions) {
  356. if (!urlOptions) {
  357. urlOptions = '';
  358. }
  359. SuperNovaLoader.loadGame(urlOptions);
  360. document.fire('game:activated');
  361. };
  362.  
  363. RuffleLoader = {
  364. loadGame: function(urlOptions) {
  365. new GameIframe({
  366. "auto_resize":null,
  367. "iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-Ruffle" + '/?kongregate_host=www.kongregate.com',
  368. "alternate_game_file_url":null,
  369. "game_width":`+my_game_width+`,
  370. "game_height":`+my_game_height+`,
  371. "max_game_width":null,
  372. "max_game_height":null,
  373. "game_left":`+my_game_left+`,
  374. "game_top":`+my_game_top+`,
  375. "iframe_class":"dont_hide",
  376. "host":"`+urlstart+`"+"://www.kongregate.com",
  377. "api_host":"`+urlstart+`"+"://api.kongregate.com",
  378. "api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
  379. "preview":false,
  380. "game_permalink":active_user.gamePermalink(),
  381. "game_id":active_user.gameId(),
  382. "game_url":"http://www.kongregate.com"+active_user.gamePath(),
  383. "game_version":`+my_game_version+`,
  384. "flash_var_prefix":"kv_",
  385. "post_message":true,
  386. "iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
  387. "game_host":"`+urlstart+`"+"://chat.kongregate.com",
  388. "channel_id":encodeURIComponent(channel_id),
  389. "svid":"`+my_svid+`",
  390. "game_type":"flash"
  391. },
  392. urlOptions, channel_id).createGameIframeElement();
  393.  
  394. }
  395. }
  396.  
  397. function LoadRuffleIframe(urlOptions) {
  398. if (!urlOptions) {
  399. urlOptions = '';
  400. }
  401. RuffleLoader.loadGame(urlOptions);
  402. document.fire('game:activated');
  403. };
  404.  
  405. //]]>`;
  406. document.getElementById("game").appendChild(ic);
  407.  
  408. // Let's make some shiny buttons!
  409. var s=document.createElement("script"), ButtonMaker;
  410. s.type="text/javascript";
  411. s.id="Shiny buttons";
  412. document.head.appendChild(s.appendChild(document.createTextNode('('+function(){
  413. ButtonMaker=function(x){
  414. var ql=document.getElementById("quicklinks");
  415. if(holodeck&&LoadFlashIframe&&ql!==null){
  416. // Flash button
  417. var FlashButton=document.createElement('li');
  418. FlashButton.id="Button to (re)load with Flash";
  419. FlashButton.innerHTML='<a href="#" onclick="LoadFlashIframe(); return false">Flash</a>';
  420. ql.insert(FlashButton,ql.firstChild);
  421. // SuperNova button
  422. var SuperNovaButton=document.createElement('li');
  423. SuperNovaButton.id="Button to (re)load with SuperNova";
  424. SuperNovaButton.innerHTML='<a href="#" onclick="LoadSuperNovaIframe(); return false">SuperNova</a>';
  425. ql.insert(SuperNovaButton,ql.firstChild);
  426. // Ruffle button
  427. var RuffleButton=document.createElement('li');
  428. RuffleButton.id="Button to (re)load with Ruffle";
  429. RuffleButton.innerHTML='<a href="#" onclick="LoadRuffleIframe(); return false">Ruffle</a>';
  430. //ql.insert(RuffleButton,ql.firstChild); //UNHIDE IF THE RUFFLE SCRIPT IS ONE DAY, BY SOME MIRACLE, UPLOADED TO THE KONGREGATE SERVERS.
  431. // No more buttons
  432. setTimeout(function(){delete ButtonMaker;},1);
  433. }
  434. else if(x){setTimeout(function(y){ButtonMaker(y);},10000,x--);}
  435. else{setTimeout(function(){delete ButtonMaker;},1);}
  436. };
  437. ButtonMaker(10);
  438. }+')()')).parentNode);
  439.  
  440. }
  441. };