Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: CI

on:
push:
branches: ['main']
pull_request:
branches: ['main']

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7.0.0
- name: Install Node.js
uses: actions/setup-node@v6.4.0
with:
node-version: 22.20.0
- name: Install Dependencies
run: npm install --no-fund
- parallel:
- name: Typecheck
run: npm run test:types
- name: Lint
run: npm run lint
- name: Unit Test
run: npm run test:unit
- name: Build
run: npm run build
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@
"type": "module",
"scripts": {
"build": "vite build",
"deploy": "npm run type-check && npm run lint && devvit upload",
"deploy": "npm run test:types && npm run lint && devvit upload",
"dev": "devvit playtest",
"launch": "npm run deploy && devvit publish",
"lint": "eslint 'src/**/*.{ts,tsx}'",
"login": "devvit login",
"prettier": "prettier --write .",
"type-check": "tsc --build"
"test:types": "tsc --build",
"test:unit": "node --experimental-strip-types --no-warnings=ExperimentalWarning --test \"src/**/*.test.ts\""
},
"engines": {
"node": ">=22.2.0"
"node": ">=22.12.0"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i didn't follow why the version of Node is incremented but differs in some of the templates. can we unify these?

},
"dependencies": {
"@devvit/start": "0.13.10",
Expand All @@ -30,7 +31,7 @@
"eslint": "10.8.0",
"globals": "17.8.0",
"prettier": "3.9.6",
"typescript": "7.0.2",
"typescript": "6.0.3",
"typescript-eslint": "8.65.0",
"vite": "8.1.5"
}
Expand Down
68 changes: 48 additions & 20 deletions src/client/main.ts

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

this patterns seems questionable but i recognize fixing it is out of scope for this PR.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { InitResponse } from '../shared/api';

declare global {
interface Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Module: any;
GM_tick?: (time: number) => void;
onGameSetWindowSize?: (width: number, height: number) => void;
Expand All @@ -10,19 +11,28 @@ declare global {
log_next_game_state?: () => void;
wallpaper_update_config?: (config: string) => void;
wallpaper_reset_config?: () => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setAddAsyncMethod?: (method: any) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setJSExceptionHandler?: (handler: any) => void;
hasJSExceptionHandler?: () => boolean;
doJSExceptionHandler?: (exceptionJSON: string) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setWadLoadCallback?: (callback: any) => void;
onFirstFrameRendered?: () => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
triggerAd?: (adId: string, ...callbacks: any[]) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
triggerPayment?: (itemId: string, callback: any) => void;
toggleElement?: (id: string) => void;
set_acceptable_rollback?: (frames: number) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
report_stats?: (statsData: any) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
g_pAddAsyncMethod?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
g_pJSExceptionHandler?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
g_pWadLoadCallback?: any;
}
}
Expand All @@ -45,7 +55,8 @@ class GameLoader {
private loadingElement: HTMLElement;
private startingHeight?: number;
private startingWidth?: number;
private startingAspect?: number;
// Used by the aspect-ratio example in ensureAspectRatio (see below).
// private startingAspect?: number;

constructor() {
this.statusElement = document.getElementById('status') as HTMLElement;
Expand All @@ -62,7 +73,7 @@ class GameLoader {

this.setupModule();
this.setupResizeObserver();
this.loadGame();
void this.loadGame();
}

private setupModule() {
Expand Down Expand Up @@ -150,7 +161,7 @@ class GameLoader {
console.log(`Window size set to width: ${width}, height: ${height}`);
this.startingHeight = height;
this.startingWidth = width;
this.startingAspect = this.startingWidth / this.startingHeight;
// this.startingAspect = this.startingWidth / this.startingHeight;
};

const resizeObserver = new ResizeObserver(() => {
Expand All @@ -174,23 +185,30 @@ class GameLoader {

this.canvasElement.classList.add('active');

const maxWidth = window.innerWidth;
const maxHeight = window.innerHeight;
let newHeight: number, newWidth: number;

const heightQuotient = this.startingHeight / maxHeight;
const widthQuotient = this.startingWidth / maxWidth;

if (heightQuotient > widthQuotient) {
newHeight = maxHeight;
newWidth = newHeight * this.startingAspect!;
} else {
newWidth = maxWidth;
newHeight = newWidth / this.startingAspect!;
}

this.canvasElement.style.height = '100%'; //`${newHeight}px`;
this.canvasElement.style.width = '100%'; //`${newWidth}px`;
// Example: compute dimensions that preserve the game's starting aspect

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we need this for GameMaker to function properly?

// ratio within the current viewport. Currently the canvas is simply
// stretched to 100%, but this snippet is kept for reference.
//
// const maxWidth = window.innerWidth;
// const maxHeight = window.innerHeight;
// let newHeight: number, newWidth: number;
//
// const heightQuotient = this.startingHeight / maxHeight;
// const widthQuotient = this.startingWidth / maxWidth;
//
// if (heightQuotient > widthQuotient) {
// newHeight = maxHeight;
// newWidth = newHeight * this.startingAspect!;
// } else {
// newWidth = maxWidth;
// newHeight = newWidth / this.startingAspect!;
// }
//
// this.canvasElement.style.height = `${newHeight}px`;
// this.canvasElement.style.width = `${newWidth}px`;

this.canvasElement.style.height = '100%';
this.canvasElement.style.width = '100%';
}

private async loadRunnerManifest(): Promise<void> {
Expand Down Expand Up @@ -247,13 +265,15 @@ class GameLoader {
private setupGameMakerGlobals() {
// GameMaker async method support - make variables globally accessible
window.g_pAddAsyncMethod = -1;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.setAddAsyncMethod = (asyncMethod: any) => {
window.g_pAddAsyncMethod = asyncMethod;
console.log('setAddAsyncMethod called with:', asyncMethod);
};

// Exception handling - make variables globally accessible
window.g_pJSExceptionHandler = undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.setJSExceptionHandler = (exceptionHandler: any) => {
if (typeof exceptionHandler === 'function') {
window.g_pJSExceptionHandler = exceptionHandler;
Expand All @@ -276,6 +296,7 @@ class GameLoader {

// WAD/Resource loading - make variables globally accessible
window.g_pWadLoadCallback = undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.setWadLoadCallback = (wadLoadCallback: any) => {
window.g_pWadLoadCallback = wadLoadCallback;
};
Expand All @@ -285,6 +306,7 @@ class GameLoader {
};

// Ad system stubs
// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.triggerAd = (adId: string, ...callbacks: any[]) => {
console.log('triggerAd called with adId:', adId);
// For now, just call the callbacks to simulate ad completion
Expand All @@ -293,6 +315,7 @@ class GameLoader {
}
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.triggerPayment = (itemId: string, callback: any) => {
console.log('triggerPayment called with itemId:', itemId);
// Simulate payment completion
Expand All @@ -317,6 +340,7 @@ class GameLoader {
console.log('Set acceptable rollback frames:', frames);
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
window.report_stats = (statsData: any) => {
console.log('Game stats reported:', statsData);
};
Expand All @@ -335,18 +359,22 @@ class GameLoader {

// Mock accelerometer API to prevent permissions policy violations
if (!('DeviceMotionEvent' in window)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).DeviceMotionEvent = class MockDeviceMotionEvent extends (
Event
) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(type: string, eventInitDict?: any) {
super(type, eventInitDict);
}
};
}

if (!('DeviceOrientationEvent' in window)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).DeviceOrientationEvent =
class MockDeviceOrientationEvent extends Event {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(type: string, eventInitDict?: any) {
super(type, eventInitDict);
}
Expand Down