// ==UserScript==
// @name Kongregate Flash games fixer
// @version 3.2.3
// @author Matrix4348
// @namespace https://greasyfork.org/users/4818
// @description You can now chose between Flash and SuperNova to play Flash games on Kongregate!
// @license MIT
// @match *://*.konggames.com/games/*/*/frame/*
// @match *://www.kongregate.com/games/*/*
// @grant none
// ==/UserScript==
// 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.
if ((document.URL.search("/frame/")>-1)&(document.body.innerHTML.search("kong_flash_variables")>-1)){
// First, we need to extract the link to the swf (the game file) and a few other things.
var file_url0, file_url, file_url_base; // Basic URL.
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.
var SNwidth, SNheight, my_bgcolor; // Parameters.
var scripts=document.getElementsByTagName("script");
for(var i=0; i<scripts.length;i++) {var script_text=scripts[i].text;
var url_text;
if(script_text.indexOf("game_swf")!== -1) {
url_text=String(script_text.match(/game_swf\"\:\"(.*?)\"\,\"game_url/g));
file_url0="https://"+decodeURIComponent(url_text.substring(17,(url_text.length/2)-11));
// Background color parameter for swf injection.
my_bgcolor=script_text.substring(script_text.search("bgcolor")+10,script_text.search("bgcolor")+17);
// Flash, game shell and API.
blablabla=String(script_text.match(/swfurl\"\:\"(.*?)\"\,\"flashvars/g));
my_first_link=blablabla.substring(blablabla.search("//"),blablabla.search(".swf")+4);
my_second_link=encodeURIComponent("http:"+file_url0.substring(file_url0.search("//"),file_url0.length)); // HTTPS WILL NOT MAKE THE API LOAD!
var blabla=String(script_text.match(/kongregate_api_path(.*?)\"title/g));
GameShellAPI=decodeURIComponent(blabla.substring(blabla.search("flash")-3,blabla.search(".swf")+4));
// Values for the SuperNova part. Note that they will only be correctly defined if they have three digits, which should always be the case.
SNwidth=script_text.substring(script_text.search("width")+7,script_text.search("width")+10);
SNheight=script_text.substring(script_text.search("height")+8,script_text.search("height")+11);
break;
}
else if(script_text.indexOf("swfurl")!== -1) {
url_text=String(script_text.match(/swfurl\"\:\"(.*?)\"\,\"flashvars/g));
file_url0=decodeURIComponent(url_text.substring(9,url_text.length-12));
// Background color parameter for swf injection.
my_bgcolor=script_text.substring(script_text.search("bgcolor")+10,script_text.search("bgcolor")+17);
// Flash, game shell and API (even though, in this part of the loop, games do not need game shells).
my_first_link=file_url0.substring(file_url0.search("//"),file_url0.length);
my_second_link="";
GameShellAPI="";
// Values for the SuperNova part. Note that they will only be correctly defined if they have three digits, which should always be the case.
SNwidth=script_text.substring(script_text.search("width")+7,script_text.search("width")+10);
SNheight=script_text.substring(script_text.search("height")+8,script_text.search("height")+11);
break;
};
};
file_url=file_url0.substring(file_url0.search("//"),file_url0.length);
if (file_url.search("/live/")>-1){
file_url_base="http:"+file_url.substring(0,file_url.search("/live/")+6);
}
else {
file_url_base="http:"+file_url.substring(0,file_url.search("/game_files/")+22);
};
// Then, we build the functions that will load the games.
function more_players(){
var a=document.createElement("script");
a.id="More choice";
a.type="text/javascript";
// IMPORTANT: The checkParams function (originally present in the webpage) inputs most of the flashvars into kong_flash_variables.
a.innerHTML=
`//<![CDATA[
FlashLoader = {
loadGame: function(urlOptions) {
var swf_location = "`+my_first_link+`";
var swfobject_flash_vars = {};
if(typeof(kong_flash_variables) == "object"){
for(var k in kong_flash_variables){
swfobject_flash_vars[k] = encodeURIComponent(kong_flash_variables[k]);
}
}
// Score API (re)activation part:
swfobject_flash_vars.kongregate_flash_postmessage=true; // This line alone activates the API for a few (recent?) games.
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.
swfobject_flash_vars.api_host=swfobject_flash_vars.kongregate_api_host; // Needed? Useless?
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...
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...
gameswfifgameshell="`+my_second_link+`";
if(gameswfifgameshell.length!=0){
swfobject_flash_vars.game_swf=gameswfifgameshell;
swfobject_flash_vars.kongregate_api_path=encodeURIComponent("`+GameShellAPI+`"); // Yep, game shells need a different API file!
swfobject_flash_vars.api_path=swfobject_flash_vars.kongregate_api_path;
};
if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
var d=document.createElement("div");
d.id="gamediv";
document.getElementById("game_wrapper").appendChild(d);
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+`"},{});
// 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.
// Therefore, the game will be injected using another method, just so the users know that the script works.
if (document.getElementById("gamediv").type==undefined){
document.getElementById("gamediv").remove();
var truc=document.createElement("object");
truc.id="gamediv";
truc.type="application/x-shockwave-flash";
truc.data="`+my_first_link+`"
truc.width="100%";
truc.height="100%";
var bgc=document.createElement("param"); bgc.name="bgcolor"; bgc.value="`+my_bgcolor+`"; truc.appendChild(bgc);
var anw=document.createElement("param"); anw.name="allownetworking"; anw.value="all"; truc.appendChild(anw);
var asa=document.createElement("param"); asa.name="allowscriptaccess"; asa.value="always"; truc.appendChild(asa);
var b=document.createElement("param"); b.name="base"; b.value="`+file_url_base+`"; truc.appendChild(b);
var fv0=""; for(var k in swfobject_flash_vars){fv0=fv0+k+"="+encodeURIComponent(swfobject_flash_vars[k])+"&"};
var fv=document.createElement("param"); fv.name="flashvars"; fv.value=fv0.substring(0,fv0.length-1); truc.appendChild(fv);
document.getElementById("game_wrapper").appendChild(truc);
};
}
}
function play_with_Flash(urlOptions) {
if (!urlOptions) {
urlOptions = '';
}
FlashLoader.loadGame(urlOptions);
document.fire('game:activated');
};
var SNloadGame=function(A){
var SNoptions = {
"swfurl" : "http:`+file_url+`",
"flashvars":{},
"title" : ttgArgs.game_title,
"width" : `+SNwidth+`,
"height" : `+SNheight+`
};
if((typeof(kong_flash_variables) === 'object')&(typeof(supernova)==='object')){
SNoptions.flashvars = $j.param(kong_flash_variables);
if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
var d=document.createElement("div");
d.id="gamediv";
document.getElementById("game_wrapper").appendChild(d);
SNoptions.el = document.querySelector('#gamediv');
supernova.launch(SNoptions);
supernova.openGame(SNoptions);
setTimeout(function(){delete SNloadGame;},1);
}
else if(A){setTimeout(function(B){SNloadGame(B);},10000,A--);}
else{setTimeout(function(){delete SNloadGame;},1);}
};
function play_with_SuperNova(){ SNloadGame(10); };
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.
var r=document.createElement("script");
r.type="text/javascript";
r.src=""; // Sadly, the script must be on the Kongregate servers... Curse on that same-origin policy!
document.body.appendChild(r);
var swf_location = "`+file_url+`";
var swfobject_flash_vars = {};
if(typeof(kong_flash_variables) == "object"){
for(var k in kong_flash_variables){
swfobject_flash_vars[k] = encodeURIComponent(kong_flash_variables[k]);
}
}
// In case of activation: remember to add the same extra flashvars, like for Flash, so the API will work.
if(document.getElementById("game_wrapper").firstDescendant()!=null){document.getElementById("game_wrapper").firstDescendant().remove();};
var RandomFunctionName=function(A){
if(window.RufflePlayer!=null){
window.RufflePlayer.config = {
"publicPath": undefined,
"contextMenu": true,
"showSwfDownload": true,
"menu": true,
"quality": "high",
};
const ruffle = window.RufflePlayer.newest();
const player = ruffle.createPlayer();
const container = document.getElementById("game_wrapper");
container.appendChild(player);
player.load({
url: swf_location,
parameters: swfobject_flash_vars,
allowScriptAccess: true
});
setTimeout(function(){delete RandomFunctionName;},1);
}
else if(A){setTimeout(function(B){RandomFunctionName(B);},10000,A--);}
else{setTimeout(function(){delete RandomFunctionName;},1);}
};
RandomFunctionName(10);
};
function time_to_play(){
// 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.
// 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.
// Moreover, changing it only in the URL SEEMS not to change the value used for the flashvars.
// If we want the game to load with Flash:
if(document.URL.search("me-wanna-Flash")>-1){ play_with_Flash(); }
// If we want the game to load (properly!) with SuperNova:
else if(document.URL.search("me-wanna-SuperNova")>-1){ play_with_SuperNova(); }
// If we want the game to load with Ruffle:
else if(document.URL.search("me-wanna-Ruffle")>-1){ play_with_Ruffle(); }
// When the iframe loads normally (without a modified channel_id):
else{
function BrowVer(){ua=navigator.userAgent; return {Browser:ua.substring(ua.lastIndexOf(" ")+1,ua.lastIndexOf("/")),Version:ua.substring(ua.lastIndexOf("/")+1,ua.length)}};
var b=BrowVer.Browser, v=BrowVer.Version;
function FlashSupport(){
var np=navigator.plugins, npl=np.length;
for(var k=0;k<npl;k++){ if(np[k].name=="Shockwave Flash"){return true}; }
return false;
};
if(navigator.userAgent.search("Windows")==-1){ play_with_Flash(); } // Because SuperNova only works on Windows.
else if(FlashSupport()==false){ play_with_SuperNova(); }
else if(FlashSupport()==true){ play_with_Flash(); }
else if((b=="Edg")||(b=="Chrome")||(b=="Safari")){ play_with_SuperNova(); } // Useless but
else if((b=="Basilisk")||(b=="PaleMoon")){ play_with_Flash(); } // could be useful
else if((b=="Firefox")||(v<85)){ play_with_Flash(); } // in case of
else if((b=="Firefox")||(v>=85)){ play_with_SuperNova(); } // a Ruffle
else { play_with_Flash(); } // implementation.
}
};
var time_to_play_but_at_the_correct_time=function(a){
if(activateGame._alreadyActivated){
time_to_play();
setTimeout(function(){delete time_to_play_but_at_the_correct_time;},1);
}
else if(a){setTimeout(function(b){time_to_play_but_at_the_correct_time(b);},10000,a--);}
else{setTimeout(function(){delete time_to_play_but_at_the_correct_time;},1);}
};
time_to_play_but_at_the_correct_time(10);
//]]>`;
document.body.appendChild(a);
};
more_players();
}
// Game pages part. Only for Flash games, so I will make sure that active_user.gameType()="flash".
// 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).
else if (document.URL.search("www.kongregate.com/games/")>-1){
if(active_user.gameType()=="flash"){
// Useful variables.
var urlstart=document.URL.substring(0,document.URL.search("://"));
var my_game_version, my_svid, my_game_width, my_game_height, my_game_left, my_game_top;
var game_scripts=document.getElementById("game").getElementsByTagName("script");
for(var j=0; j<game_scripts.length;j++) {var game_script_text=game_scripts[j].text;
if((game_script_text.indexOf("game_version")!== -1)&(game_script_text.indexOf("svid")!== -1)) {
my_game_version=game_script_text.substring(game_script_text.search("game_version")+14,game_script_text.search("flash_var_prefix")-2);
my_svid=game_script_text.substring(game_script_text.search("svid")+7,game_script_text.search("game_type")-3);
my_game_width=game_script_text.substring(game_script_text.search("game_width")+12,game_script_text.search("game_height")-2);
my_game_height=game_script_text.substring(game_script_text.search("game_height")+13,game_script_text.search("max_game_width")-2);
my_game_left=game_script_text.substring(game_script_text.search("game_left")+11,game_script_text.search("game_top")-2);
my_game_top=game_script_text.substring(game_script_text.search("game_top")+10,game_script_text.search("iframe_class")-2);
break;
}
};
// What will be inserted in the webpage, to load the different iframes we will use.
// 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.
// All I know is that is is some kind of hexadecimal characters string.
// 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.
var ic=document.createElement("script");
ic.id="iframe constructors";
ic.innerHTML=
`//<![CDATA[
FlashLoader = {
loadGame: function(urlOptions) {
new GameIframe({
"auto_resize":null,
"iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-Flash" + '/?kongregate_host=www.kongregate.com',
"alternate_game_file_url":null,
"game_width":`+my_game_width+`,
"game_height":`+my_game_height+`,
"max_game_width":null,
"max_game_height":null,
"game_left":`+my_game_left+`,
"game_top":`+my_game_top+`,
"iframe_class":"dont_hide",
"host":"`+urlstart+`"+"://www.kongregate.com",
"api_host":"`+urlstart+`"+"://api.kongregate.com",
"api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
"preview":false,
"game_permalink":active_user.gamePermalink(),
"game_id":active_user.gameId(),
"game_url":"http://www.kongregate.com"+active_user.gamePath(),
"game_version":`+my_game_version+`,
"flash_var_prefix":"kv_",
"post_message":true,
"iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
"game_host":"`+urlstart+`"+"://chat.kongregate.com",
"channel_id":encodeURIComponent(channel_id),
"svid":"`+my_svid+`",
"game_type":"flash"
},
urlOptions, channel_id).createGameIframeElement();
}
}
function LoadFlashIframe(urlOptions) {
if (!urlOptions) {
urlOptions = '';
}
FlashLoader.loadGame(urlOptions);
document.fire('game:activated');
};
SuperNovaLoader = {
loadGame: function(urlOptions) {
new GameIframe({
"auto_resize":null,
"iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-SuperNova" + '/?kongregate_host=www.kongregate.com',
"alternate_game_file_url":null,
"game_width":`+my_game_width+`,
"game_height":`+my_game_height+`,
"max_game_width":null,
"max_game_height":null,
"game_left":`+my_game_left+`,
"game_top":`+my_game_top+`,
"iframe_class":"dont_hide",
"host":"`+urlstart+`"+"://www.kongregate.com",
"api_host":"`+urlstart+`"+"://api.kongregate.com",
"api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
"preview":false,
"game_permalink":active_user.gamePermalink(),
"game_id":active_user.gameId(),
"game_url":"http://www.kongregate.com"+active_user.gamePath(),
"game_version":`+my_game_version+`,
"flash_var_prefix":"kv_",
"post_message":true,
"iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
"game_host":"`+urlstart+`"+"://chat.kongregate.com",
"channel_id":encodeURIComponent(channel_id),
"svid":"`+my_svid+`",
"game_type":"flash"
},
urlOptions, channel_id).createGameIframeElement();
}
}
function LoadSuperNovaIframe(urlOptions) {
if (!urlOptions) {
urlOptions = '';
}
SuperNovaLoader.loadGame(urlOptions);
document.fire('game:activated');
};
RuffleLoader = {
loadGame: function(urlOptions) {
new GameIframe({
"auto_resize":null,
"iframe_url":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com"+active_user.gamePath()+'/frame/' + "me-wanna-Ruffle" + '/?kongregate_host=www.kongregate.com',
"alternate_game_file_url":null,
"game_width":`+my_game_width+`,
"game_height":`+my_game_height+`,
"max_game_width":null,
"max_game_height":null,
"game_left":`+my_game_left+`,
"game_top":`+my_game_top+`,
"iframe_class":"dont_hide",
"host":"`+urlstart+`"+"://www.kongregate.com",
"api_host":"`+urlstart+`"+"://api.kongregate.com",
"api_path":"https://chat.kongregate.com/flash/API_AS3_d43c4b859e74432475c1627346078677.swf",
"preview":false,
"game_permalink":active_user.gamePermalink(),
"game_id":active_user.gameId(),
"game_url":"http://www.kongregate.com"+active_user.gamePath(),
"game_version":`+my_game_version+`,
"flash_var_prefix":"kv_",
"post_message":true,
"iframe_host":"`+urlstart+`"+"://game"+active_user.gameId()+".konggames.com",
"game_host":"`+urlstart+`"+"://chat.kongregate.com",
"channel_id":encodeURIComponent(channel_id),
"svid":"`+my_svid+`",
"game_type":"flash"
},
urlOptions, channel_id).createGameIframeElement();
}
}
function LoadRuffleIframe(urlOptions) {
if (!urlOptions) {
urlOptions = '';
}
RuffleLoader.loadGame(urlOptions);
document.fire('game:activated');
};
//]]>`;
document.getElementById("game").appendChild(ic);
// Let's make some shiny buttons!
var s=document.createElement("script"), ButtonMaker;
s.type="text/javascript";
s.id="Shiny buttons";
document.head.appendChild(s.appendChild(document.createTextNode('('+function(){
ButtonMaker=function(x){
var ql=document.getElementById("quicklinks");
if(holodeck&&LoadFlashIframe&&ql!==null){
// Flash button
var FlashButton=document.createElement('li');
FlashButton.id="Button to (re)load with Flash";
FlashButton.innerHTML='<a href="#" onclick="LoadFlashIframe(); return false">Flash</a>';
ql.insert(FlashButton,ql.firstChild);
// SuperNova button
var SuperNovaButton=document.createElement('li');
SuperNovaButton.id="Button to (re)load with SuperNova";
SuperNovaButton.innerHTML='<a href="#" onclick="LoadSuperNovaIframe(); return false">SuperNova</a>';
ql.insert(SuperNovaButton,ql.firstChild);
// Ruffle button
var RuffleButton=document.createElement('li');
RuffleButton.id="Button to (re)load with Ruffle";
RuffleButton.innerHTML='<a href="#" onclick="LoadRuffleIframe(); return false">Ruffle</a>';
//ql.insert(RuffleButton,ql.firstChild); //UNHIDE IF THE RUFFLE SCRIPT IS ONE DAY, BY SOME MIRACLE, UPLOADED TO THE KONGREGATE SERVERS.
// No more buttons
setTimeout(function(){delete ButtonMaker;},1);
}
else if(x){setTimeout(function(y){ButtonMaker(y);},10000,x--);}
else{setTimeout(function(){delete ButtonMaker;},1);}
};
ButtonMaker(10);
}+')()')).parentNode);
}
};