Prepping save file support
This commit is contained in:
@ -25,6 +25,7 @@
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js" integrity="sha512-a+SUDuwNzXDvz4XrIcXHuCf089/iJAoN4lmrXJg18XnduKK6YlDHNRalv4yd1N40OKI80tFidF+rqTFKGPoWFQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -85,6 +86,29 @@
|
|||||||
clearInterval(initInterval);
|
clearInterval(initInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const md5File = async path => {
|
||||||
|
const buffer = EJS_emulator.gameManager.FS.readFile(path);
|
||||||
|
const hash = await crypto.subtle.digest('SHA-256', buffer);
|
||||||
|
const hashArray = Array.from(new Uint8Array(hash));
|
||||||
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
return hashHex;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emulatorSave = async () => {
|
||||||
|
// First, we get the currently saved MD5 hash of all files in the save
|
||||||
|
// directory
|
||||||
|
const contents = EJS_emulator.gameManager.FS.readdir('/homeplay/saves').filter(f => !f.startsWith('.'));
|
||||||
|
const hashes = await Promise.all(contents.map(f => md5File(`/homeplay/saves/${f}`)));
|
||||||
|
EJS_emulator.gameManager.saveSaveFiles();
|
||||||
|
const newHashes = await Promise.all(contents.map(f => md5File(`/homeplay/saves/${f}`)));
|
||||||
|
const changedFiles = contents.filter((f, i) => hashes[i] !== newHashes[i]);
|
||||||
|
console.log('Changed files', changedFiles);
|
||||||
|
|
||||||
|
send({
|
||||||
|
message: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const send = data => {
|
const send = data => {
|
||||||
window.parent.postMessage(data, '*');
|
window.parent.postMessage(data, '*');
|
||||||
}
|
}
|
||||||
@ -107,6 +131,10 @@
|
|||||||
EJS_emulator.setVolume(data.volume);
|
EJS_emulator.setVolume(data.volume);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'save':
|
||||||
|
emulatorSave();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.error('Unknown message', message);
|
console.error('Unknown message', message);
|
||||||
}
|
}
|
||||||
@ -142,11 +170,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
EJS_onSaveState = () => {
|
EJS_onSaveState = () => {
|
||||||
send({ message: 'save' });
|
send({ message: 'save_state' });
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onLoadState = () => {
|
EJS_onLoadState = () => {
|
||||||
send({ message: 'load' });
|
send({ message: 'load_state' });
|
||||||
}
|
}
|
||||||
|
|
||||||
EJS_onGameStart = () => {
|
EJS_onGameStart = () => {
|
||||||
|
@ -18,15 +18,16 @@ type SendEmulatorMessageVolume = {
|
|||||||
|
|
||||||
type SendEmulatorMessage = (
|
type SendEmulatorMessage = (
|
||||||
SendEmulatorMessageInit |
|
SendEmulatorMessageInit |
|
||||||
SendEmulatorMessageVolume
|
SendEmulatorMessageVolume |
|
||||||
|
{ message: 'save' }
|
||||||
);
|
);
|
||||||
|
|
||||||
type ReceiveEmulatorMessage = (
|
type ReceiveEmulatorMessage = (
|
||||||
{ message: 'iframe_loaded' } |
|
{ message: 'iframe_loaded' } |
|
||||||
{ message: 'start' } |
|
{ message: 'start' } |
|
||||||
{ message: 'ready' } |
|
{ message: 'ready' } |
|
||||||
{ message: 'save' } |
|
{ message: 'save_state' } |
|
||||||
{ message: 'load' }
|
{ message: 'load_state' }
|
||||||
);
|
);
|
||||||
|
|
||||||
export type EmulatorProps = {
|
export type EmulatorProps = {
|
||||||
@ -69,8 +70,8 @@ export const Emulator:React.FC<EmulatorProps> = props => {
|
|||||||
|
|
||||||
case 'start':
|
case 'start':
|
||||||
case 'ready':
|
case 'ready':
|
||||||
case 'load':
|
case 'load_state':
|
||||||
case 'save':
|
case 'save_state':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('Invalid message received:', msg);
|
console.error('Invalid message received:', msg);
|
||||||
|
@ -7,12 +7,6 @@ import Error500, { Error500Props } from '../500';
|
|||||||
import { extendFragment, includeFragment } from '@/lib/fragment';
|
import { extendFragment, includeFragment } from '@/lib/fragment';
|
||||||
import { Paginated, paginationQuery } from '@/lib/page';
|
import { Paginated, paginationQuery } from '@/lib/page';
|
||||||
|
|
||||||
type Game = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
system: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type PageProps = {
|
type PageProps = {
|
||||||
games:Paginated<GameLight>|null;
|
games:Paginated<GameLight>|null;
|
||||||
} | Error500Props;
|
} | Error500Props;
|
||||||
@ -21,7 +15,9 @@ export const getServerSideProps: GetServerSideProps<PageProps> = async () => {
|
|||||||
try {
|
try {
|
||||||
const client = await apiClientGet();
|
const client = await apiClientGet();
|
||||||
const res = await client.query<{ games:Paginated<GameLight> }>({
|
const res = await client.query<{ games:Paginated<GameLight> }>({
|
||||||
variables: { },
|
variables: {
|
||||||
|
after: null,
|
||||||
|
},
|
||||||
query: gql`
|
query: gql`
|
||||||
${includeFragment(GameLightFragment)}
|
${includeFragment(GameLightFragment)}
|
||||||
query getGames {
|
query getGames {
|
||||||
|
Reference in New Issue
Block a user