// ==UserScript== // @name Papa's Save Manager // @namespace vaminta // @match https://www.coolmathgames.com/0-papas-bakeria // @match https://www.coolmathgames.com/0-papas-freezeria // @match https://www.coolmathgames.com/0-papas-burgeria // @match https://www.coolmathgames.com/0-papas-taco-mia // @match https://www.coolmathgames.com/0-papas-pancakeria // @match https://www.coolmathgames.com/0-papas-cupcakeria // @match https://www.coolmathgames.com/0-papas-cheeseria // @match https://www.coolmathgames.com/0-papas-wingeria // @match https://www.coolmathgames.com/0-papas-hot-doggeria // // @match https://www.crazygames.com/game/papa-s-burgeria // @match https://www.crazygames.com/game/papas-bakeria // @match https://www.crazygames.com/game/papas-freezeria // @match https://www.crazygames.com/game/papas-taco-mia // @match https://www.crazygames.com/game/papas-pancakeria // @match https://www.crazygames.com/game/papas-cupcakeria // @match https://www.crazygames.com/game/papas-cheeseria // @match https://www.crazygames.com/game/papas-wingeria // @match https://www.crazygames.com/game/papas-hotdoggeria // // @match https://games.crazygames.com/en_US/papa-s-burgeria/index.html // @match https://games.crazygames.com/en_US/papas-freezeria/index.html // @match https://games.crazygames.com/en_US/papas-hotdoggeria/index.html // // @match https://files.crazygames.com/* // @grant none // @version 0.5.0 // @author Vaminta // @run-at document-idle // @description Allows you to backup your save data for the Papa's series of games online // @homepageURL https://github.com/Vaminta/papas-save-manager // @downloadURL none // ==/UserScript== //04/09/2023 psm = new Object(); /* USER OPTIONS: saveTxtExt: (bool) export outputs the file with .txt extension rather than .psm - same contents forceImport: (bool) bypass validation checks (not recommended) otherPageAdjustments: (bool) allows script to change other parts of webpage to fix potential problems consoleOut: enables outputs to the console, useful for testing preventGameLoad: (bool) attempts to prevent game loading, useful for internal testing */ psm.userOptions = { saveTxtExt: false, forceImport: false, otherPageAdjustments: false, consoleOut: false, preventGameLoad: false } // -------------- psm.version = "0.5.0"; psm.saveVersion = "002"; psm.savePrefix = "PSMS"; //PSM save psm.saveExt = "psm"; psm.hostList = [ { name: "Cool Math Games", hostname: "www.coolmathgames.com", saveIdentifier: "08", saveNameSignature: "cmg" }, { name: "Crazy Games", hostname: "www.crazygames.com", saveIdentifier: "09", saveNameSignature: "cg" } ]; psm.gameList = Object.freeze([ { name:"Papa's Bakeria", pathname: "/0-papas-bakeria", saveName: "papasbakeria_save", saveIdentifier: "08", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-bakeria", lsKeys: ["//papasbakeria1","//papasbakeria2","//papasbakeria3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-bakeria", lsKeys: ["files.crazygames.com//papasbakeria1","files.crazygames.com//papasbakeria2","files.crazygames.com//papasbakeria3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Freezeria", pathname: "/0-papas-freezeria", saveName: "papasfreezeria_save", saveIdentifier: "09", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-freezeria", lsKeys: ["//papasfreezeria_1","//papasfreezeria_2","//papasfreezeria_3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-freezeria", lsKeys: ["//papasfreezeria_1","//papasfreezeria_2","//papasfreezeria_3"], iframe: ["#game-iframe"] } ] }, { name:"Papa's Burgeria", pathname: "/0-papas-burgeria", saveName: "papasburgeria_save", saveIdentifier: "10", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-burgeria", lsKeys: ["//papasburgeria_1","//papasburgeria_2","//papasburgeria_3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papa-s-burgeria", lsKeys: ["//papasburgeria_1","//papasburgeria_2","//papasburgeria_3"], iframe: ["#game-iframe"] } ] }, { name:"Papa's Taco Mia", pathname: "/0-papas-taco-mia", saveName: "papastacomia_save", saveIdentifier: "11", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-taco-mia", lsKeys: ["//papastaqueria_1","//papastaqueria_2","//papastaqueria_3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-taco-mia", lsKeys: ["files.crazygames.com//papastaqueria_1","files.crazygames.com//papastaqueria_2","files.crazygames.com//papastaqueria_3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Pancakeria", pathname: "/0-papas-pancakeria", saveName: "papaspancakeria_save", saveIdentifier: "12", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-pancakeria", lsKeys: ["//papaspancakeria_1","//papaspancakeria_2","//papaspancakeria_3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-pancakeria", lsKeys: ["files.crazygames.com//papaspancakeria_1","files.crazygames.com//papaspancakeria_2","files.crazygames.com//papaspancakeria_3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Cupcakeria", pathname: "/0-papas-cupcakeria", saveName: "papascupcakeria_save", saveIdentifier: "13", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-cupcakeria", lsKeys: ["//papascupcakeria1","//papascupcakeria2","//papascupcakeria3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-cupcakeria", lsKeys: ["files.crazygames.com//papascupcakeria1","files.crazygames.com//papascupcakeria2","files.crazygames.com//papascupcakeria3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Cheeseria", pathname: "/0-papas-cheeseria", saveName: "papascheeseria_save", saveIdentifier: "14", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-cheeseria", lsKeys: ["//papascheeseria1","//papascheeseria2","//papascheeseria3"], iframe: [] }, { hostname: "www.crazygames.com", pathname: "/game/papas-cheeseria", lsKeys: ["files.crazygames.com//papascheeseria1","files.crazygames.com//papascheeseria2","files.crazygames.com//papascheeseria3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Wingeria", saveName: "papaswingeria_save", saveIdentifier: "15", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-wingeria", lsKeys: ["//papaswingeria_1","//papaswingeria_2","//papaswingeria_3"] }, { hostname: "www.crazygames.com", pathname: "/game/papas-wingeria", lsKeys: ["files.crazygames.com//papaswingeria_1","files.crazygames.com//papaswingeria_2","files.crazygames.com//papaswingeria_3"], makeIframe: ["psm-domain-iframe","https://files.crazygames.com/"], iframe: ["#psm-domain-iframe"] } ] }, { name:"Papa's Hot Doggeria", saveName: "papashotdoggeria_save", saveIdentifier: "16", hosts:[ { hostname: "www.coolmathgames.com", pathname: "/0-papas-hot-doggeria", lsKeys: ["//papashotdoggeria1","//papashotdoggeria2","//papashotdoggeria3"] }, { hostname: "www.crazygames.com", pathname: "/game/papas-hotdoggeria", lsKeys: ["//papashotdoggeria1","//papashotdoggeria2","//papashotdoggeria3"], iframe: ["#game-iframe"] } ] } ]); psm._idCount = 0; psm.newID = () => {psm._idCount++; return psm._idCount}; psm.cout = (message) => {if(psm.userOptions.consoleOut) console.log(message)}; psm.lsCallbacks = []; // [id,callback,date] psm.game = null; psm.gameHost = null; psm.hostDetails = null; const pbsmCSS = ` .pbsm-imp-button, .pbsm-exp-button{ background-color: #1d3752; color: #ffffff; border: 1px #06203b solid; border-radius: 5px; width: 70px; height: 30px; } .pbsm-imp-button:hover, .pbsm-exp-button:hover{ background-color: #2d4762; } .crazygamesCont { border: 2px white solid; padding: 3%; border-radius: 10px; } .hidden { display:none; } `; function injectCSS(css){ let styleE = document.createElement("style"); styleE.innerText = css; document.head.appendChild(styleE); } //not working as of 0.4.0 (not async compat) function slotHasSave(slot){ return false; let result = false; const data = localStorage.getItem(psm.game.lsKeys[slot]); if(data!=null&&data.length>20) result = true; return result; } //Generic download function function download(filename, text) { let element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); } function exportSave(slot){ getSlot(slot,function(e){ const data = psm.savePrefix + psm.saveVersion + psm.game.saveIdentifier + psm.hostDetails.saveIdentifier + e; if(!e){ alert("No save in slot " + (slot+1) + " detected!"); return; } const filename = psm.game.saveName + "_" + psm.hostDetails.saveNameSignature + "." + psm.saveExt; download(filename,data); }); } function upgradeSave(data){ const saveVersion = data.slice(4,7); let upgradedSave = ""; if(saveVersion == "001"){ let header = data.slice(0,9); let body = data.slice(9); header += "08"; //version 1 only supported cmg; must be on cmg upgradedSave = header+body; } console.log("upgraded save"); return upgradedSave; } //Checks content of PSM for validity and returning results as object containing breakdown, useful for providing user feedback function isValidSave(data,expGameID){ if(!data)data = ""; if(!expGameID) expGameID = psm.game.saveIdentifier; let result = { isNotEmpty: data.length>0 ? true : false, isPSMS: data.slice(0,4)==psm.savePrefix ? true : false, isNotTimeTraveller: parseInt(data.slice(4,7)) <= parseInt(psm.saveVersion) ? true : false, //save isn't from future version of psm isCorrectGame: (expGameID=="*" || data.slice(7,9) == psm.game.saveIdentifier) ? true : false, isSupportedHost: (data.slice(9,11)==psm.hostDetails.saveIdentifier) ? true : false, isEncoded: true, //implement later conclusion: false }; result.conclusion = (result.isNotEmpty && result.isPSMS && result.isNotTimeTraveller && result.isCorrectGame && result.isSupportedHost && result.isEncoded) ? true : false; return result; } function processImport(slot,data){ const saveVersion = data.slice(4,7); if(saveVersion=="001") data = upgradeSave(data); const fileValidity = isValidSave(data); const forceLoad = psm.userOptions.forceImport; if(fileValidity.conclusion || forceLoad){ //continue to load const importData = data.slice(11); setSlot(slot,importData); //localStorage.setItem(key,importData); } else{ // do not load -> show error let errorMsg = "PSM Import Error: \n\n"; if(!fileValidity.isNotEmpty) errorMsg += " - File is empty\n"; else if(!fileValidity.isPSMS) errorMsg += " - File is unrecognised format\n"; else{ if(!fileValidity.isNotTimeTraveller) errorMsg += " - File was exported from a future version of PSM, please update\n"; if(!fileValidity.isCorrectGame) errorMsg += " - File appears to be for a different Papa's series game\n"; if(!fileValidity.isSupportedHost) errorMsg += " - Save data is for a different host\n" } errorMsg += "\nFurther information and help may be found on GitHub"; alert(errorMsg); } } // Setup file reader then send output to processImport function importSave(slot){ if(slotHasSave(slot)){ let overwrite = confirm("There is already data in slot " + (slot+1) + ". Are you sure you want to overwrite?"); if(!overwrite) return; } const file = document.getElementById("file-picker").files[0]; const reader = new FileReader(); reader.addEventListener("load",function(){ processImport(slot,reader.result); },false,); if(file) reader.readAsText(file); } /* Handles button clicks from the import and export buttons */ function handleButtonClick(e,func){ let targetSave = e.parentElement.getAttribute("data-ss")-1; if(func=="import"){ document.getElementById("file-picker").onchange = function(){importSave(targetSave)}; document.getElementById("file-picker").click(); } else if(func=="export"){ exportSave(targetSave); } } function genTableHTML(){ const impButtHTML = ''; const expButtHTML = ''; let table = ""; table += ""; table += ""; //data-saveslot table += ""; table += "
Slot 1Slot 2Slot 3
" + impButtHTML + ""+ impButtHTML + ""+impButtHTML+"
" + expButtHTML + ""+ expButtHTML + ""+expButtHTML+"
"; return table; } function addOnclicks(){ let importButtons = document.getElementsByClassName("pbsm-imp-button"); let exportButtons = document.getElementsByClassName("pbsm-exp-button"); for(let i=0;iGitHub" div.appendChild(footerP); const hostname = psm.gameHost.hostname; if(hostname=="www.coolmathgames.com"){ let parentNode = document.getElementsByClassName("game-meta-body")[0]; document.getElementsByClassName("node__content clearfix field-item")[0].insertBefore(div,parentNode); } else if(hostname=="www.crazygames.com"){ let beforeNode = document.getElementsByClassName("css-1pj32m1")[0]; document.getElementsByClassName("MuiBox-root css-1ttp6zk")[0].getElementsByTagName("div")[0].insertBefore(div,beforeNode); } addOnclicks(); } function getSlot(slot,callback){ if(!callback) return; const lsKey = String(psm.gameHost.lsKeys[slot]); if(psm.gameHost.iframe && psm.gameHost.iframe.length>0){ const entID = psm.newID(); let callbackEntry = []; callbackEntry[0] = entID; callbackEntry[1] = callback; psm.lsCallbacks.push(callbackEntry); let newMessage = { id: entID, task: "getLS", params: [lsKey] }; if(psm.gameHost.nest) newMessage.nest = psm.gameHost.nest; else newMessage.nest = 0; //console.log(newMessage); document.querySelector(psm.gameHost.iframe[0]).contentWindow.postMessage(newMessage,"*"); } else{ let data = localStorage.getItem(lsKey); callback(data); } } function setSlot(slot,value,callback){ //callback not supported yet if(!value)return; const lsKey = String(psm.gameHost.lsKeys[slot]); if(psm.gameHost.iframe && psm.gameHost.iframe.length>0){ let newMessage = { id: 0, //N/A task: "setLS", params: [lsKey,value] }; document.querySelector(psm.gameHost.iframe[0]).contentWindow.postMessage(newMessage,"*"); } else{ localStorage.setItem(lsKey,value); } } //Receive message from game iframe - handle returned localstorage data function receiveMessage(event){ const data = event.data; if(data.type=="lsReply"){ for(let i=0;i0){ data.nest--; document.getElementsByTagName("iframe")[0].contentWindow.postMessage(data,"*"); return; } if(data.type=="lsReply"){ window.parent.postMessage(data,"*"); return; } //------- let response = { id: data.id, type: "lsReply", content: null }; if(data.task=="getLS"){ let result = localStorage.getItem(data.params[0]); response.content = result; window.parent.postMessage(response,"*"); } else if(data.task=="setLS"){ localStorage.setItem(data.params[0],data.params[1]); } } //get host by key value pair. Checks all games function getHost(key,value){ let host = null; for(let i=0;i cmg_start_game_full_screen(); } } function initialise(){ psm.cout("PSM Initialise"); detectGame(); if(!psm.game){ // if iframe script window.addEventListener("message", iframeReceiveMessage, false); psm.cout("PSM iframe script loaded at: "+window.location.href); return; } window.addEventListener("message", receiveMessage, false); if(psm.gameHost.makeIframe){ let newIframe = document.createElement("iframe"); newIframe.id = psm.gameHost.makeIframe[0]; newIframe.src = psm.gameHost.makeIframe[1]; newIframe.className = "hidden"; document.body.appendChild(newIframe); } if(psm.userOptions.otherPageAdjustments) pageAdjustments(); if(psm.userOptions.saveTxtExt) psm.saveExt = "txt"; if(psm.userOptions.preventGameLoad) blockGame(); injectCSS(pbsmCSS); if(window.location.host=="www.crazygames.com"){ var interval = setInterval(function(){ //for crazygames doesn't like adding html too early! if(document.readyState=="complete"){ clearInterval(interval); generateHTML(); } },250); } else generateHTML(); } initialise();