Skip to content

Commit dc7b7f6

Browse files
committed
batman
0 parents  commit dc7b7f6

21 files changed

+1818
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Python-generated files
2+
__pycache__/
3+
*.py[oc]
4+
build/
5+
dist/
6+
wheels/
7+
*.egg-info
8+
9+
# Virtual environments
10+
.venv

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11

README.md

Whitespace-only changes.

app.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from fastapi import FastAPI
2+
from fastapi.staticfiles import StaticFiles
3+
from fastapi.responses import FileResponse
4+
5+
app = FastAPI()
6+
7+
# Mount static files at root
8+
app.mount("/", StaticFiles(directory="static", html=True), name="static")
9+
10+

docker-compose.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
version: '3.8'
2+
3+
services:
4+
game-server:
5+
build: .
6+
container_name: godot_fastapi_game
7+
ports:
8+
- "7009:7009"
9+
volumes:
10+
- .:/app
11+
restart: always

dockerfile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Use official Python image
2+
FROM python:3.11-slim
3+
4+
# Set working directory
5+
WORKDIR /app
6+
7+
# Copy dependencies and install
8+
COPY requirements.txt .
9+
RUN pip install --no-cache-dir -r requirements.txt
10+
11+
# Copy the rest of the app
12+
COPY . .
13+
14+
# Expose the port
15+
EXPOSE 8000
16+
17+
# Run the app
18+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7009"]

pyproject.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[project]
2+
name = "container-hunt"
3+
version = "0.1.0"
4+
description = "Add your description here"
5+
readme = "README.md"
6+
requires-python = ">=3.11"
7+
dependencies = [
8+
"fastapi>=0.115.13",
9+
"uvicorn>=0.34.3",
10+
]

requirements.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
annotated-types==0.7.0
2+
anyio==4.9.0
3+
click==8.2.1
4+
fastapi==0.115.13
5+
h11==0.16.0
6+
idna==3.10
7+
pydantic==2.11.7
8+
pydantic-core==2.33.2
9+
sniffio==1.3.1
10+
starlette==0.46.2
11+
typing-extensions==4.14.0
12+
typing-inspection==0.4.1
13+
uvicorn==0.34.3

static/index.html

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
6+
<title>space_odyssey</title>
7+
<style>
8+
html, body, #canvas {
9+
margin: 0;
10+
padding: 0;
11+
border: 0;
12+
}
13+
14+
body {
15+
color: white;
16+
background-color: black;
17+
overflow: hidden;
18+
touch-action: none;
19+
}
20+
21+
#canvas {
22+
display: block;
23+
}
24+
25+
#canvas:focus {
26+
outline: none;
27+
}
28+
29+
#status, #status-splash, #status-progress {
30+
position: absolute;
31+
left: 0;
32+
right: 0;
33+
}
34+
35+
#status, #status-splash {
36+
top: 0;
37+
bottom: 0;
38+
}
39+
40+
#status {
41+
background-color: #242424;
42+
display: flex;
43+
flex-direction: column;
44+
justify-content: center;
45+
align-items: center;
46+
visibility: hidden;
47+
}
48+
49+
#status-splash {
50+
max-height: 100%;
51+
max-width: 100%;
52+
margin: auto;
53+
}
54+
55+
#status-splash.show-image--false {
56+
display: none;
57+
}
58+
59+
#status-splash.fullsize--true {
60+
height: 100%;
61+
width: 100%;
62+
object-fit: contain;
63+
}
64+
65+
#status-splash.use-filter--false {
66+
image-rendering: pixelated;
67+
}
68+
69+
#status-progress, #status-notice {
70+
display: none;
71+
}
72+
73+
#status-progress {
74+
bottom: 10%;
75+
width: 50%;
76+
margin: 0 auto;
77+
}
78+
79+
#status-notice {
80+
background-color: #5b3943;
81+
border-radius: 0.5rem;
82+
border: 1px solid #9b3943;
83+
color: #e0e0e0;
84+
font-family: 'Noto Sans', 'Droid Sans', Arial, sans-serif;
85+
line-height: 1.3;
86+
margin: 0 2rem;
87+
overflow: hidden;
88+
padding: 1rem;
89+
text-align: center;
90+
z-index: 1;
91+
}
92+
</style>
93+
<link id="-gd-engine-icon" rel="icon" type="image/png" href="space_odyssey.icon.png" />
94+
<link rel="apple-touch-icon" href="space_odyssey.apple-touch-icon.png"/>
95+
96+
</head>
97+
<body>
98+
<canvas id="canvas">
99+
Your browser does not support the canvas tag.
100+
</canvas>
101+
102+
<noscript>
103+
Your browser does not support JavaScript.
104+
</noscript>
105+
106+
<div id="status">
107+
<img id="status-splash" class="show-image--true fullsize--true use-filter--true" src="space_odyssey.png" alt="">
108+
<progress id="status-progress"></progress>
109+
<div id="status-notice"></div>
110+
</div>
111+
112+
<script src="space_odyssey.js"></script>
113+
<script>
114+
const GODOT_CONFIG = {"args":[],"canvasResizePolicy":2,"ensureCrossOriginIsolationHeaders":true,"executable":"space_odyssey","experimentalVK":false,"fileSizes":{"space_odyssey.pck":946064,"space_odyssey.wasm":43699190},"focusCanvas":true,"gdextensionLibs":[]};
115+
const GODOT_THREADS_ENABLED = false;
116+
const engine = new Engine(GODOT_CONFIG);
117+
118+
(function () {
119+
const statusOverlay = document.getElementById('status');
120+
const statusProgress = document.getElementById('status-progress');
121+
const statusNotice = document.getElementById('status-notice');
122+
123+
let initializing = true;
124+
let statusMode = '';
125+
126+
function setStatusMode(mode) {
127+
if (statusMode === mode || !initializing) {
128+
return;
129+
}
130+
if (mode === 'hidden') {
131+
statusOverlay.remove();
132+
initializing = false;
133+
return;
134+
}
135+
statusOverlay.style.visibility = 'visible';
136+
statusProgress.style.display = mode === 'progress' ? 'block' : 'none';
137+
statusNotice.style.display = mode === 'notice' ? 'block' : 'none';
138+
statusMode = mode;
139+
}
140+
141+
function setStatusNotice(text) {
142+
while (statusNotice.lastChild) {
143+
statusNotice.removeChild(statusNotice.lastChild);
144+
}
145+
const lines = text.split('\n');
146+
lines.forEach((line) => {
147+
statusNotice.appendChild(document.createTextNode(line));
148+
statusNotice.appendChild(document.createElement('br'));
149+
});
150+
}
151+
152+
function displayFailureNotice(err) {
153+
console.error(err);
154+
if (err instanceof Error) {
155+
setStatusNotice(err.message);
156+
} else if (typeof err === 'string') {
157+
setStatusNotice(err);
158+
} else {
159+
setStatusNotice('An unknown error occurred.');
160+
}
161+
setStatusMode('notice');
162+
initializing = false;
163+
}
164+
165+
const missing = Engine.getMissingFeatures({
166+
threads: GODOT_THREADS_ENABLED,
167+
});
168+
169+
if (missing.length !== 0) {
170+
if (GODOT_CONFIG['serviceWorker'] && GODOT_CONFIG['ensureCrossOriginIsolationHeaders'] && 'serviceWorker' in navigator) {
171+
let serviceWorkerRegistrationPromise;
172+
try {
173+
serviceWorkerRegistrationPromise = navigator.serviceWorker.getRegistration();
174+
} catch (err) {
175+
serviceWorkerRegistrationPromise = Promise.reject(new Error('Service worker registration failed.'));
176+
}
177+
// There's a chance that installing the service worker would fix the issue
178+
Promise.race([
179+
serviceWorkerRegistrationPromise.then((registration) => {
180+
if (registration != null) {
181+
return Promise.reject(new Error('Service worker already exists.'));
182+
}
183+
return registration;
184+
}).then(() => engine.installServiceWorker()),
185+
// For some reason, `getRegistration()` can stall
186+
new Promise((resolve) => {
187+
setTimeout(() => resolve(), 2000);
188+
}),
189+
]).then(() => {
190+
// Reload if there was no error.
191+
window.location.reload();
192+
}).catch((err) => {
193+
console.error('Error while registering service worker:', err);
194+
});
195+
} else {
196+
// Display the message as usual
197+
const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n';
198+
displayFailureNotice(missingMsg + missing.join('\n'));
199+
}
200+
} else {
201+
setStatusMode('progress');
202+
engine.startGame({
203+
'onProgress': function (current, total) {
204+
if (current > 0 && total > 0) {
205+
statusProgress.value = current;
206+
statusProgress.max = total;
207+
} else {
208+
statusProgress.removeAttribute('value');
209+
statusProgress.removeAttribute('max');
210+
}
211+
},
212+
}).then(() => {
213+
setStatusMode('hidden');
214+
}, displayFailureNotice);
215+
}
216+
}());
217+
</script>
218+
</body>
219+
</html>
220+
11.6 KB
Loading

0 commit comments

Comments
 (0)