Skip to content

Commit

Permalink
Multiple gallery fixes (#1323)
Browse files Browse the repository at this point in the history
* Load game content (code + images) from local instead of github.  Fix metadata issues resulting in 404's.  Fix client-side thumbnail caching

* Try to get the path correctly?

* Trying something

* adding debug log statement to understand dir hierarchy

* Attempt fixing paths in vercel

* Terminal dungeon was causing internal issues

* Reduces chattiness, and improves reliability of site initialization when run locally

* Add missing img that causes errors
  • Loading branch information
grymmy committed Dec 22, 2023
1 parent fa7e090 commit d9bf92d
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 27 deletions.
Binary file added games/img/AmongTheStars.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added games/img/Mario_Kart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions games/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -1219,15 +1219,15 @@
"filename": "BoxCubeGuy",
"title": "BoxCubeGuy",
"author": "CaptainATW",
"img": "CaptainATW",
"img": "BoxCubeGuy",
"tags": ["sokoban-style"],
"addedOn": "2022-11-25"
},
{
"filename": "Asteroid_Field",
"title": "Asteroid_Field",
"author": "Kaitlyn",
"img": "CaptainATW",
"img": "",
"tags": ["catch"],
"addedOn": "2022-11-25"
},
Expand Down Expand Up @@ -1491,7 +1491,7 @@
"filename": "Terminal-Dungeon",
"title": "Terminal-Dungeon",
"author": "adadyer",
"img": "terminal-dungeon",
"img": "",
"tags": ["puzzle-npc"],
"addedOn": "2022-12-20"
},
Expand Down Expand Up @@ -1819,7 +1819,7 @@
"filename": "Mario_Kart",
"title": "Mario_Kart",
"author": "nucleiav",
"img": "sprig_mario",
"img": "",
"tags": ["endless"],
"addedOn": "2023-01-13"
},
Expand Down Expand Up @@ -2107,7 +2107,7 @@
"filename": "The_Maze_of_Sprig",
"title": "The_Maze_of_Sprig",
"author": "SahilD",
"img": "TheMazeOfSprig",
"img": "",
"tags": ["sokoban-style"],
"addedOn": "2023-02-14"
},
Expand Down Expand Up @@ -2835,7 +2835,7 @@
"filename": "thunder_bowl",
"title": "thunder_bowl",
"author": "Alex",
"img": "thunderball",
"img": "",
"tags": [],
"addedOn": "2023-08-03"
},
Expand Down Expand Up @@ -3139,7 +3139,7 @@
"filename": "Musi",
"title": "Musi",
"author": "levi - blockish",
"img": "image_2023-10-22_152001392",
"img": "",
"tags": ["memory"],
"addedOn": "2023-10-25"
},
Expand Down
7 changes: 5 additions & 2 deletions src/lib/remaining-consoles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export async function getConsolesRemaining(): Promise<number> {
const data = await fetch('https://airbridge.hackclub.com/v0.1/Sprig%20Waitlist/Requests').then(r => r.json())
if (!data) throw 'Failed to Fetch'
const jsonText = await fetch('https://airbridge.hackclub.com/v0.1/Sprig%20Waitlist/Requests')
const data = await jsonText.json()
if (!data) {
throw 'Failed to Fetch'
}
const consoleCount = data.filter((console: any) => {
let status = console.fields.Status
return (status === 'Pending' || status === 'Approved')
Expand Down
56 changes: 43 additions & 13 deletions src/pages/api/thumbnail.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import type { APIRoute } from 'astro'
import { baseEngine, palette } from 'sprig/base'
import { RawThumbnail, Thumbnail } from '../../lib/thumbnail'
import fs from 'fs'
import path from 'path'
import { dirname } from 'path'
import { fileURLToPath } from 'url'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename);

const evalGameScript = (script: string) => {
const { api } = baseEngine()
Expand All @@ -25,7 +32,9 @@ const evalGameScript = (script: string) => {
const fn = new Function(...Object.keys(patchedApi), script)
fn(...Object.values(patchedApi))
} catch (err) {
console.log(err)
// NOTE: We hide this error, because it currently serves no purpose other than muddying the log
// HOWEVER, generally this is probably an excellent place to detect broken games in the future
//console.log(err)
}

return {
Expand Down Expand Up @@ -65,7 +74,9 @@ const blitSprite = (data: Uint8Array, width: number, bitmap: number[], tx: numbe

const drawGameImage = (src: string): RawThumbnail => {
const { legend, map, background } = evalGameScript(src)
if (!map) throw new Error('No map found')
if (!map) {
throw new Error('No map found')
}

const mapWidth = map.trim().split('\n')[0]!.trim().length
const mapHeight = map.trim().split('\n').length
Expand Down Expand Up @@ -93,23 +104,26 @@ const drawGameImage = (src: string): RawThumbnail => {

export const get: APIRoute = async ({ url }) => {
const name = url.searchParams.get('key') || ''
const srcUrl = `https://raw.githubusercontent.com/hackclub/sprig/main/games/${encodeURIComponent(name)}.js`
let gameContentString = loadGameContentFromDisk(name)
let gameImageBase64 = loadImageBase64FromDisk(name)

let thumbnail: Thumbnail
try {
// Try fetching a custom image (PNG only)
const imgUrl = `https://raw.githubusercontent.com/hackclub/sprig/main/games/img/${encodeURIComponent(name)}.png`
const image = await fetch(imgUrl)
if (image.status === 200) {
if (gameImageBase64 != null)
{
// Try fetching a custom image (PNG only)
thumbnail = {
kind: 'png',
data: Buffer.from(await image.arrayBuffer()).toString('base64')
data: gameImageBase64
}
} else {
// Fetch the script and try to run the game
const src = await fetch(srcUrl).then((res) => res.text())
thumbnail = drawGameImage(src)
}
if (gameContentString == null) {
throw new Error('No image found, no game content found - weird')
} else {
// Fetch the script and try to run the game
thumbnail = drawGameImage(gameContentString as string)
}
}
} catch (error) {
// If everything breaks, use a default image
console.error(error)
Expand All @@ -127,7 +141,23 @@ export const get: APIRoute = async ({ url }) => {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,OPTIONS',
'Access-Control-Allow-Headers': '*',
'Cache-Control': 's-maxage=60, stale-while-revalidate=604800'
'Cache-Control': 'max-age=86400'
}
})
}
function loadImageBase64FromDisk(name: string) {
try {
let imgPath = path.resolve(__dirname, `../../../games/img/${name}.png`)
if (!fs.existsSync(imgPath)) return null
return fs.readFileSync(imgPath).toString("base64")
} catch {
return null
}
}

function loadGameContentFromDisk(name: string) {
let gameContentPath = path.resolve(__dirname, `../../../games/${name}.js`)
if (!fs.existsSync(gameContentPath)) return null
return fs.readFileSync(gameContentPath).toString()
}

16 changes: 13 additions & 3 deletions src/pages/gallery/[filename].astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,23 @@ import { getSession } from '../../lib/game-saving/account'
import { getGalleryGames } from '../../lib/game-saving/gallery'
import MobilePlayer from '../../components/big-interactive-pages/mobile-player'
import { mobileUserAgent } from '../../lib/utils/mobile'
import fs from 'fs'
import path from 'path'
import { dirname } from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename);
const session = await getSession(Astro.cookies)
const filename = Astro.params.filename ?? ''
const res = await fetch(`https://raw.githubusercontent.com/hackclub/sprig/main/games/${encodeURIComponent(filename)}.js`)
if (!res.ok) return Astro.redirect('/404', 302)
const code = await res.text()
const gameContentPath = path.resolve(__dirname, `../../../games/${filename}.js`)
const code = fs.readFileSync(gameContentPath).toString()
if (code == null) {
return Astro.redirect('/404', 302)
}
const fileRegexp = /^.*\/(.+)-(\d+)\.md$/
Expand Down
4 changes: 2 additions & 2 deletions src/pages/gallery/gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export default function Gallery({ games, tags }: { games: GameMetadata[], tags:

<div id="games">
{
gamesState.map((game: GalleryGameMetadata) => (
gamesState.map((game: GalleryGameMetadata) => (
<a
style={`display:${game.show ? "block" : "none"}`}
class="game"
Expand All @@ -191,7 +191,7 @@ export default function Gallery({ games, tags }: { games: GameMetadata[], tags:
) : null}

<img
src={game.img}
src={`gallery/${game.img}`}
alt={`preview of ${game.filename}.js`}
/>
<h3>{game.title}</h3>
Expand Down

1 comment on commit d9bf92d

@vercel
Copy link

@vercel vercel bot commented on d9bf92d Dec 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

sprig – ./

sprig-git-main-gamer.vercel.app
sprig.vercel.app
sprig-gamer.vercel.app

Please sign in to comment.