2022-11-24 01:17:18 -05:00
var modName = "mods/save_loading.js" ;
2023-04-17 17:44:19 -04:00
2023-04-16 19:48:09 -04:00
try {
2023-04-19 20:12:37 -04:00
if ( typeof ( rebuildCurrentPixels ) !== "function" ) {
rebuildCurrentPixels = function ( ) {
var currPix = [ ] ; //rebuild currentPixels from pixelMap to try to fix bug
2023-04-19 20:08:25 -04:00
for ( pmi = 0 ; pmi < pixelMap . length ; pmi ++ ) {
var pixelMapPart = pixelMap [ pmi ] ;
for ( pmj = 0 ; pmj < pixelMapPart . length ; pmj ++ ) {
var pixelMapUnit = pixelMapPart [ pmj ] ;
if ( typeof ( pixelMapUnit ) === "object" ) {
if ( pixelMapUnit !== null ) {
currPix . push ( pixelMapUnit ) ;
} ;
} ;
} ;
} ;
currentPixels = currPix ;
2023-04-19 20:12:37 -04:00
} ;
2023-04-19 20:08:25 -04:00
} ;
2023-04-17 17:44:19 -04:00
//https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
function storageAvailable ( type ) {
let storage ;
try {
storage = window [ type ] ;
const x = "__storage_test__" ;
storage . setItem ( x , x ) ;
storage . removeItem ( x ) ;
return true ;
} catch ( e ) {
return (
e instanceof DOMException &&
// everything except Firefox
( e . code === 22 ||
// Firefox
e . code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e . name === "QuotaExceededError" ||
// Firefox
e . name === "NS_ERROR_DOM_QUOTA_REACHED" ) &&
// acknowledge QuotaExceededError only if there's something already stored
storage &&
storage . length !== 0
) ;
}
}
2023-02-14 10:00:29 -05:00
2023-04-17 17:44:19 -04:00
function zeroToNull ( val ) {
if ( val === 0 ) { return null } ;
return val ;
} ;
2023-02-14 10:00:29 -05:00
2023-04-17 17:44:19 -04:00
if ( ! localStorage . slSaveSettings ) {
localStorage . setItem ( "slSaveSettings" , '{"roundTemps":true}' ) ;
} ;
2023-02-14 10:00:29 -05:00
2023-04-17 17:44:19 -04:00
slSaveSettings = JSON . parse ( localStorage . slSaveSettings ) ;
2023-02-14 10:00:29 -05:00
2023-04-17 17:44:19 -04:00
function epsilonRound ( num , precision ) {
return Math . round ( ( num + Number . EPSILON ) * ( 10 * * precision ) ) / ( 10 * * precision ) ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
function getSimulationState ( ) {
var simulationState = {
//currentPixels: currentPixels,
pixelMap : structuredClone ? structuredClone ( pixelMap ) : JSON . parse ( JSON . stringify ( pixelMap ) ) ,
width : width ,
height : height ,
pixelSize : pixelSize ,
settings : settings ,
version : 1 ,
enabledMods : localStorage . enabledMods ,
2023-02-14 10:00:29 -05:00
} ;
for ( i = 0 ; i < simulationState . pixelMap . length ; i ++ ) {
var column = simulationState . pixelMap [ i ] ;
for ( j = 0 ; j < column . length ; j ++ ) {
2023-04-17 17:44:19 -04:00
if ( column [ j ] === null || typeof ( column [ j ] ) === "undefined" ) {
column [ j ] = 0 ;
} ;
} ;
} ;
if ( slSaveSettings . roundTemps ) {
for ( i = 0 ; i < simulationState . pixelMap . length ; i ++ ) {
var column = simulationState . pixelMap [ i ] ;
for ( j = 0 ; j < column . length ; j ++ ) {
var pixel = column [ j ] ;
if ( pixel ? . temp ) {
pixel . temp = epsilonRound ( pixel . temp , 3 ) ;
} ;
2023-02-14 10:00:29 -05:00
} ;
} ;
} ;
2023-04-17 17:44:19 -04:00
return simulationState ;
2023-02-14 10:00:29 -05:00
} ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
//https://stackoverflow.com/a/46118025
function copyToClipboard ( text ) {
var dummy = document . createElement ( "textarea" ) ;
// to avoid breaking orgain page when copying more words
// cant copy when adding below this code
// dummy.style.display = 'none'
document . body . appendChild ( dummy ) ;
//Be careful if you use textarea. setAttribute('value', value), which works with "input" does not work with "textarea". – Eduard
dummy . value = text ;
dummy . select ( ) ;
document . execCommand ( "copy" ) ;
document . body . removeChild ( dummy ) ;
}
const saveTemplateAsFile = ( filename , dataObjToWrite ) => { //from https://stackoverflow.com/a/65939108
const blob = new Blob ( [ JSON . stringify ( dataObjToWrite ) ] , { type : "text/json" } ) ;
const link = document . createElement ( "a" ) ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
link . download = filename ;
link . href = window . URL . createObjectURL ( blob ) ;
link . dataset . downloadurl = [ "text/json" , link . download , link . href ] . join ( ":" ) ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
const evt = new MouseEvent ( "click" , {
view : window ,
bubbles : true ,
cancelable : true ,
} ) ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
link . dispatchEvent ( evt ) ;
link . remove ( )
} ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
function formatCurrentDate ( ) { //derived from https://gist.github.com/Ivlyth/c4921735812dd2c0217a
var d = new Date ( ) ;
var year = d . getFullYear ( ) . toString ( ) ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
var month = ( d . getMonth ( ) + 1 ) . toString ( ) ;
if ( month . length == 1 ) { month = "0" + month } ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
var day = d . getDate ( ) . toString ( ) ;
if ( day . length == 1 ) { day = "0" + day } ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
var hour = d . getHours ( ) . toString ( ) ;
if ( hour . length == 1 ) { hour = "0" + hour } ;
var minute = d . getMinutes ( ) . toString ( ) ;
if ( minute . length == 1 ) { minute = "0" + minute } ;
2022-11-24 01:17:18 -05:00
2023-04-17 17:44:19 -04:00
var second = d . getSeconds ( ) . toString ( ) ;
if ( second . length == 1 ) { second = "0" + second } ;
var date _format _str = ` ${ year } - ${ month } - ${ day } ${ hour } - ${ minute } - ${ second } ` ;
return date _format _str ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
function savePrompt ( ) {
var filename = prompt ( "Please enter the desired filename, without the .json (defaults to current date)" ) ;
if ( filename === null ) {
return false ;
} ;
if ( filename === "" ) {
filename = ` Sandboxels save ${ formatCurrentDate ( ) } ` ;
} ;
filename += ".json" ;
downloadSave ( filename )
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
function downloadSave ( filename = null ) {
if ( filename === null ) {
filename = ` Sandboxels save ${ formatCurrentDate ( ) } .json ` ;
} ;
saveTemplateAsFile ( filename , getSimulationState ( ) ) ;
} ;
rebuildCurrentPixels ? ? = function ( ) {
var currPix = [ ] ; //rebuild currentPixels from pixelMap to try to fix bug
for ( pmi = 0 ; pmi < pixelMap . length ; pmi ++ ) {
var pixelMapPart = pixelMap [ pmi ] ;
for ( pmj = 0 ; pmj < pixelMapPart . length ; pmj ++ ) {
var pixelMapUnit = pixelMapPart [ pmj ] ;
if ( typeof ( pixelMapUnit ) === "object" ) {
if ( pixelMapUnit !== null ) {
currPix . push ( pixelMapUnit ) ;
} ;
} ;
} ;
} ;
currentPixels = currPix ;
} ;
function quicksave ( doSuccessAlert = true , doFailAlert = true ) {
if ( storageAvailable ( "localStorage" ) ) {
rebuildCurrentPixels ( ) ;
localStorage . setItem ( "quicksave" , JSON . stringify ( getSimulationState ( ) ) ) ;
if ( doSuccessAlert ) { alert ( "Quicksave saved" ) } ;
return true ;
} else {
if ( doFailAlert ) { alert ( "Could not save quicksave in localStorage" ) } ;
throw new Error ( "Could not save quicksave in localStorage" ) ;
} ;
} ;
function quickload ( pause = true , doSuccessAlert = true , doFailAlert = true ) {
clearAll ( ) ;
rebuildCurrentPixels ( ) ;
var save = localStorage . getItem ( "quicksave" ) ;
if ( ! save ) {
if ( doFailAlert ) { alert ( "No save exists" ) } ;
return false ;
} else {
importJsonState ( JSON . parse ( save ) ) ;
if ( doSuccessAlert ) { alert ( "Quicksave loaded" ) } ;
if ( pause ) {
paused = true ;
document . getElementById ( "pauseButton" ) . setAttribute ( "on" , "true" ) ;
2023-04-18 09:14:22 -04:00
} else {
paused = false ;
document . getElementById ( "pauseButton" ) . setAttribute ( "on" , "false" ) ;
2023-04-17 17:44:19 -04:00
} ;
return true ;
} ;
rebuildCurrentPixels ( ) ;
} ;
function copySaveJSON ( doAlert = true ) {
copyToClipboard ( JSON . stringify ( getSimulationState ( ) ) ) ;
if ( doAlert ) { alert ( "Save copied as JSON" ) } ;
} ;
2022-12-08 17:56:33 -05:00
2023-04-17 17:44:19 -04:00
function loadFile ( ) {
//Initialize
var json ;
//load JSON
var file = document . getElementById ( 'myfile' ) . files [ 0 ] ;
if ( file === undefined ) {
if ( document . getElementById ( "fileFormStatus" ) !== null ) {
document . getElementById ( "fileFormStatus" ) . style . color = "red" ;
document . getElementById ( "fileFormStatus" ) . innerHTML = "No file was uploaded!" ;
} ;
throw new Error ( "No file was uploaded" ) ;
} ;
var reader = new FileReader ( ) ;
reader . readAsText ( file , 'UTF-8' ) ;
//after loading
reader . onload = function ( evt ) {
json = evt . target . result ;
//validate
try {
json = JSON . parse ( json ) ;
} catch ( error ) {
if ( document . getElementById ( "fileFormStatus" ) !== null ) {
document . getElementById ( "fileFormStatus" ) . style . color = "red" ;
document . getElementById ( "fileFormStatus" ) . innerHTML = "The file wasn't valid JSON!" ;
} ;
throw error ;
} ;
if ( document . getElementById ( "fileFormStatus" ) !== null ) {
document . getElementById ( "fileFormStatus" ) . style . color = "yellow" ;
document . getElementById ( "fileFormStatus" ) . innerHTML = "JSON was parsed successfully" ;
} ;
//return json;
return importJsonState ( json ) ;
2022-11-24 01:17:18 -05:00
} ;
} ;
2023-04-17 17:44:19 -04:00
function loadText ( ) {
//Initialize
var json ;
//load JSON
var json = document . getElementById ( 'mytext' ) . value ;
if ( json === "" ) {
if ( document . getElementById ( "textFormStatus" ) !== null ) {
document . getElementById ( "textFormStatus" ) . style . color = "red" ;
document . getElementById ( "textFormStatus" ) . innerHTML = "No text was present!" ;
} ;
throw new Error ( "No text was present" ) ;
} ;
2022-11-24 01:17:18 -05:00
//validate
try {
json = JSON . parse ( json ) ;
} catch ( error ) {
2023-04-17 17:44:19 -04:00
if ( document . getElementById ( "textFormStatus" ) !== null ) {
document . getElementById ( "textFormStatus" ) . style . color = "red" ;
document . getElementById ( "textFormStatus" ) . innerHTML = "The text wasn't valid JSON!" ;
2022-11-24 01:17:18 -05:00
} ;
throw error ;
} ;
2023-04-17 17:44:19 -04:00
if ( document . getElementById ( "textFormStatus" ) !== null ) {
document . getElementById ( "textFormStatus" ) . style . color = "yellow" ;
document . getElementById ( "textFormStatus" ) . innerHTML = "JSON was parsed successfully" ;
2022-11-24 01:17:18 -05:00
} ;
//return json;
return importJsonState ( json ) ;
} ;
2022-12-08 17:56:33 -05:00
2023-04-17 17:44:19 -04:00
function importJsonState ( json ) {
//check keys
var jsonKeys = Object . keys ( json ) ;
var requiredKeys = [ /*"currentPixels", */ "pixelMap" , "width" , "height" , "pixelSize" ] ;
var hasrequiredKeys = true ;
for ( i = 0 ; i < requiredKeys . length ; i ++ ) {
var key = requiredKeys [ i ] ;
if ( ! jsonKeys . includes ( key ) ) {
hasrequiredKeys = false ;
break ;
} ;
2022-12-08 17:56:33 -05:00
} ;
2023-04-17 17:44:19 -04:00
if ( ! hasrequiredKeys ) {
if ( document . getElementById ( "fileFormStatus" ) !== null ) {
document . getElementById ( "fileFormStatus" ) . style . color = "red" ;
document . getElementById ( "fileFormStatus" ) . innerHTML = "JSON is not a valid save!" ;
} ;
throw new Error ( "JSON is missing required keys!" ) ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
//Set values
width = json . width ;
height = json . height ;
pixelSize = json . pixelSize ;
//currentPixels = json.currentPixels;
for ( i = 0 ; i < json . pixelMap . length ; i ++ ) {
json . pixelMap [ i ] = json . pixelMap [ i ] . map ( x => zeroToNull ( x ) ) ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
pixelMap = json . pixelMap ;
if ( json . settings ) {
settings = json . settings ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
//enabledMods handling {
var enMods = "[]" ;
if ( typeof ( json . enabledMods ) !== "undefined" ) {
enMods = json . enabledMods ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
enMods = JSON . parse ( enMods ) ;
//console.log(enMods);
var currentEnmods = JSON . parse ( localStorage . enabledMods ) ; //should already exist if you're using this mod in the first place
for ( emi = 0 ; emi < enMods . length ; emi ++ ) { //load mods additively to prevent self-disabling and the inconvenience of having to readd your mod list when you get bored
var mod = enMods [ emi ] ;
if ( ! currentEnmods . includes ( mod ) ) {
currentEnmods . push ( mod ) ;
} ;
} ;
localStorage . setItem ( "enabledMods" , JSON . stringify ( currentEnmods ) ) ;
if ( ( enMods . length > 0 && enMods [ 0 ] !== modName ) || enMods . length > 1 ) {
alert ( "Saves with other mods might require a reload (and then importing the save file again).\nIf you see a blank screen, try refreshing and loading the file again before you panic." ) ;
} ;
//}
var currPix = [ ] ; //rebuild currentPixels from pixelMap to try to fix bug
for ( pmi = 0 ; pmi < pixelMap . length ; pmi ++ ) {
var pixelMapPart = pixelMap [ pmi ] ;
for ( pmj = 0 ; pmj < pixelMapPart . length ; pmj ++ ) {
var pixelMapUnit = pixelMapPart [ pmj ] ;
if ( typeof ( pixelMapUnit ) === "object" ) {
if ( pixelMapUnit !== null ) {
currPix . push ( pixelMapUnit ) ;
} ;
2022-11-24 01:17:18 -05:00
} ;
} ;
} ;
2023-04-17 17:44:19 -04:00
currentPixels = currPix ;
if ( document . getElementById ( "fileFormStatus" ) !== null ) {
document . getElementById ( "fileFormStatus" ) . style . color = "green" ;
document . getElementById ( "fileFormStatus" ) . innerHTML = "JSON was loaded successfully." ;
} ;
return true ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
function setPixelSize ( size = null ) {
if ( size === null ) {
if ( document . getElementById ( "pixelSize" ) !== null ) {
size = document . getElementById ( "pixelSize" ) . value ;
} else {
throw new Error ( "No size could be read" ) ;
} ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
size = parseFloat ( size ) ;
if ( isNaN ( size ) || size <= 0 ) { //NaN check
if ( document . getElementById ( "pixelSizeStatus" ) !== null ) {
document . getElementById ( "pixelSizeStatus" ) . style . color = "red" ;
document . getElementById ( "pixelSizeStatus" ) . innerHTML = "Pixel size is empty or invalid" ;
} ;
throw new Error ( "NaN or negative size" ) ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-17 17:44:19 -04:00
if ( document . getElementById ( "pixelSizeStatus" ) !== null ) {
document . getElementById ( "pixelSizeStatus" ) . style . color = "green" ;
document . getElementById ( "pixelSizeStatus" ) . innerHTML = "Pixel size set successfully" ;
} ;
pixelSize = size ;
return true ;
2022-11-24 01:17:18 -05:00
} ;
2023-04-18 09:14:22 -04:00
var saveLoaderDescription = ` <div>
< span id = "downloadButton" onclick = savePrompt ( ) style = "color: #FF00FF;" > Download simulation < / s p a n >
< span id = "copyButton" onClick = copySaveJSON ( ) style = "color: #FF66FF;" > Alternatively , copy simulation JSON < / s p a n >
2023-04-17 17:44:19 -04:00
2023-04-18 09:14:22 -04:00
< span id = "fileFormStatus" > No file loader status < / s p a n >
One file , please : < input type = "file" name = "Save upload button" id = "myfile" >
< button id = "loadButton" onclick = loadFile ( ) style = "color: #FF00FF;" > Load File < / b u t t o n >
< span > Or paste JSON < / s p a n >
< span id = "textFormStatus" > No text loader status < / s p a n >
< input name = "Text load field" id = "mytext" >
< button id = "textLoadButton" onclick = loadText ( ) style = "color: #FF66FF;" > Load Text < / b u t t o n >
2023-04-17 17:44:19 -04:00
2023-04-18 09:14:22 -04:00
< span id = "pixelSizeStatus" > No size setter status < / s p a n >
Pixel size ( rendering only ) : < input id = "pixelSize" > ( Use if the save looks cut off )
< button id = "sizeButton" onclick = setPixelSize ( ) style = "color: #FF00FF;" > Set pixel size < / b u t t o n >
< / d i v > ` ;
2023-04-17 17:44:19 -04:00
2023-04-16 19:54:37 -04:00
elements . save _loader = {
2023-04-17 17:44:19 -04:00
behavior : behaviors . SELFDELETE ,
excludeRandom : true ,
color : "#FFFFFF" ,
desc : saveLoaderDescription ,
2023-04-16 19:54:37 -04:00
} ;
2023-04-17 17:44:19 -04:00
//Somehow, for some illogical reason, quicksaving causes updateStats to somehow disregard its if-statement and fucking TypeError when you mouse over an empty space; this is an attempt to fix it with overkill-level existence checks.
function updateStats ( ) {
var statsDiv = document . getElementById ( "stats" ) ;
var stats = "<span id='stat-pos' class='stat'>x" + mousePos . x + ",y" + mousePos . y + "</span>" ;
stats += "<span id='stat-pixels' class='stat'>Pxls:" + currentPixels . length + "</span>" ;
stats += "<span id='stat-tps' class='stat'>" + tps + "tps</span>" ;
stats += "<span id='stat-ticks' class='stat'>" + pixelTicks + "</span>" ;
if ( ( typeof pixelMap ) . length === 9 ) { return ; }
if ( pixelMap [ mousePos . x ] !== undefined ) {
var currentPixel = pixelMap [ mousePos . x ] [ mousePos . y ] ;
if ( typeof ( currentPixel ) !== "undefined" && currentPixel && currentPixel !== undefined && currentPixel . element ) {
stats += "<span id='stat-element' class='stat'>Elem:" + ( elements [ currentPixel ? . element ] ? . name || currentPixel ? . element ) + "</span>" ;
stats += "<span id='stat-temperature' class='stat'>Temp:" + formatTemp ( currentPixel . temp ) + "</span>" ;
if ( currentPixel . charge ) {
stats += "<span id='stat-charge' class='stat'>C" + currentPixel . charge + "</span>" ;
}
if ( currentPixel . burning ) {
stats += "<span id='stat-burning' class='stat'>Burning</span>" ;
}
}
}
if ( shiftDown ) {
stats += "<span id='stat-shift' class='stat'>" + shiftDownTypes [ shiftDown ] + "</span>" ;
}
// If the view is not null, show the view in all caps
if ( view !== null ) {
stats += "<span id='stat-view' class='stat'>" + viewKey [ view ] + "</span>" ;
}
statsDiv . innerHTML = stats ;
}
2023-04-18 09:14:22 -04:00
quickloadIsPaused = true ;
2023-04-17 17:44:19 -04:00
//Element-based quicksave toggle has proven impossible due to numerous irreparable illogic incidents, so have some buttons instead
var qsb = document . createElement ( "button" ) ;
qsb . setAttribute ( "id" , "quicksaveButton" ) ;
qsb . setAttribute ( "onclick" , "quicksave()" ) ;
qsb . innerText = "Quicksave" ;
document . getElementById ( "gameDiv" ) . before ( qsb ) ;
qsb . after ( document . createTextNode ( String . fromCharCode ( 160 ) ) ) ;
var qlb = document . createElement ( "button" ) ;
qlb . setAttribute ( "id" , "quickloadButton" ) ;
2023-04-18 09:14:22 -04:00
qlb . setAttribute ( "onclick" , "clearAll(); quickload(quickloadIsPaused ?? true)" ) ;
2023-04-17 17:44:19 -04:00
qlb . innerText = "Quickload" ;
document . getElementById ( "gameDiv" ) . before ( qlb ) ;
2023-04-18 09:14:22 -04:00
qlb . after ( document . createTextNode ( String . fromCharCode ( 160 , 160 ) ) ) ;
var qpc = document . createElement ( "input" ) ;
qpc . setAttribute ( "type" , "checkbox" ) ;
qpc . setAttribute ( "id" , "quickloadPausedInput" ) ;
qpc . setAttribute ( "onchange" , "quickloadIsPaused = this.checked;" ) ;
qpc . checked = true ;
var qpcd = document . createElement ( "span" ) ;
qpcd . setAttribute ( "id" , "quickloadPausedInputLabel" ) ;
qpcd . innerText = "Pause after quickloading?" ;
document . getElementById ( "gameDiv" ) . before ( qpc ) ;
qpc . after ( document . createTextNode ( String . fromCharCode ( 160 ) ) ) ;
document . getElementById ( "gameDiv" ) . before ( qpcd ) ;
2023-04-17 17:44:19 -04:00
document . getElementById ( "gameDiv" ) . before ( document . createElement ( "br" ) ) ;
2023-04-17 17:59:45 -04:00
2023-04-17 18:05:46 -04:00
quickSlDetectorLastKeys = [ ] ;
justPromptedQuickSL = false ;
2023-04-17 17:59:45 -04:00
document . addEventListener ( "keydown" , function ( e ) { //prop prompt listener
2023-04-17 18:05:46 -04:00
quickSlDetectorLastKeys . push ( e . key ) ;
if ( quickSlDetectorLastKeys . length > 3 ) {
quickSlDetectorLastKeys . shift ( ) ;
2023-04-17 17:59:45 -04:00
} ;
2023-04-17 18:05:46 -04:00
justPromptedQuickSL = false ;
2023-04-17 17:59:45 -04:00
} ) ;
document . addEventListener ( "keydown" , function ( e ) { //prop prompt listener
2023-04-17 18:05:46 -04:00
if ( quickSlDetectorLastKeys . join ( "," ) == "(,(,L" ) {
2023-04-17 17:59:45 -04:00
e . preventDefault ( ) ;
2023-04-17 18:05:46 -04:00
var confirm = prompt ( "Are you sure you want to quickLOAD? (Type 'yes' to confirm)" ) ;
2023-04-17 17:59:45 -04:00
if ( confirm == "yes" ) {
clearAll ( ) ;
quickload ( true , false , true ) ;
} ;
2023-04-17 18:05:46 -04:00
justPromptedQuickSL = true ;
quickSlDetectorLastKeys = [ ] ;
} else if ( quickSlDetectorLastKeys . join ( "," ) == "(,(,S" ) {
e . preventDefault ( ) ;
var confirm = prompt ( "Are you sure you want to quickSAVE? (Type 'yes' to confirm)" ) ;
if ( confirm == "yes" ) {
quicksave ( true , true ) ;
} ;
justPromptedQuickSL = true ;
quickSlDetectorLastKeys = [ ] ;
2023-04-17 17:59:45 -04:00
} ;
} ) ;
2023-04-16 19:48:09 -04:00
} catch ( error ) {
2023-04-19 20:12:37 -04:00
alert ( ` save_loading error: ${ error . toString ( ) } ` ) ;
2023-04-16 19:48:09 -04:00
} ;