Add files via upload
This commit is contained in:
parent
1fa2e66f34
commit
96ebb2c8e2
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
|
|
@ -18,7 +18,8 @@
|
|||
<nav>
|
||||
<a href="index.html">Home</a> |
|
||||
<a href="servermanager.html">Server Manager</a> |
|
||||
<a href="shardwalker.html">Shardwalker</a>
|
||||
<a href="shardwalker.html">Shardwalker</a> |
|
||||
<a href="indie_game_roadmap.html">Indie Game Roadmap</a>
|
||||
</nav>
|
||||
<header>
|
||||
<h1>Obli.Studios</h1>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,183 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Indie Game Roadmap</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', sans-serif;
|
||||
background-color: #121212;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #00bfff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.timeline {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.phase {
|
||||
background-color: #1f1f1f;
|
||||
padding: 1rem 1.5rem;
|
||||
border-left: 5px solid #00bfff;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 0 8px rgba(0, 191, 255, 0.2);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.phase h3 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
color: #00e0ff;
|
||||
}
|
||||
|
||||
.dates {
|
||||
font-size: 0.9rem;
|
||||
color: #aaaaaa;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 1rem;
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-size: 0.8rem;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
margin-left: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.status.done {
|
||||
background: #28a745;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.status.progress {
|
||||
background: #ffc107;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.status.not-started {
|
||||
background: #dc3545;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
font-size: 0.9rem;
|
||||
cursor: pointer;
|
||||
background-color: #2d2d2d;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
padding: 0.3rem 0.6rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
async function login() {
|
||||
const password = document.getElementById('password').value;
|
||||
const res = await fetch('/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password })
|
||||
});
|
||||
const result = await res.json();
|
||||
if (result.success) {
|
||||
document.getElementById('login-status').textContent = '✅ Logged in';
|
||||
document.getElementById('login-form').style.display = 'none';
|
||||
loadRoadmap();
|
||||
} else {
|
||||
document.getElementById('login-status').textContent = '❌ Incorrect password';
|
||||
}
|
||||
}
|
||||
|
||||
async function loadRoadmap() {
|
||||
const res = await fetch('/api/roadmap');
|
||||
const data = await res.json();
|
||||
const container = document.getElementById('roadmap');
|
||||
container.innerHTML = '';
|
||||
data.forEach(phase => {
|
||||
const el = document.createElement('div');
|
||||
el.className = 'phase';
|
||||
el.innerHTML = `
|
||||
<strong>${phase.title}</strong>
|
||||
<span class="status">[${phase.status}]</span>
|
||||
<select onchange="updateStatus(${phase.id}, this.value)">
|
||||
<option value="not started" ${phase.status === 'not started' ? 'selected' : ''}>Not Started</option>
|
||||
<option value="in progress" ${phase.status === 'in progress' ? 'selected' : ''}>In Progress</option>
|
||||
<option value="done" ${phase.status === 'done' ? 'selected' : ''}>Done</option>
|
||||
</select>
|
||||
`;
|
||||
container.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
||||
async function updateStatus(id, newStatus) {
|
||||
await fetch('/api/roadmap', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ id, status: newStatus })
|
||||
});
|
||||
loadRoadmap();
|
||||
}
|
||||
|
||||
// Auto-login check
|
||||
fetch('/check-auth')
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.authenticated) {
|
||||
document.getElementById('login-form').style.display = 'none';
|
||||
loadRoadmap();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<a href="index.html">Home</a> |
|
||||
<a href="servermanager.html">Server Manager</a> |
|
||||
<a href="shardwalker.html">Shardwalker</a> |
|
||||
<a href="indie_game_roadmap.html">Indie Game Roadmap</a>
|
||||
</nav>
|
||||
|
||||
<h1>Shardwalker: The Mirror's Edge</h1>
|
||||
<div id="login-panel" style="text-align:center; margin-bottom:2rem;">
|
||||
<input type="password" id="admin-pass" placeholder="Enter admin password" />
|
||||
<button onclick="login()">Login</button>
|
||||
<p id="login-status" style="color:#00bfff;"></p>
|
||||
</div>
|
||||
|
||||
<h2>Indie Dev Production Roadmap</h2>
|
||||
<div class="timeline" id="roadmap">
|
||||
<div class="phase"><h3>Pre-Production <span class="status done">Done</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">Start: [Today] — End: +30 Days</div><div class="description">Design docs, game concept, visual target, core loop</div></div>
|
||||
<div class="phase"><h3>Blockout Maps & Prototypes <span class="status progress">In Progress</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+31 Days — +75 Days</div><div class="description">Build test maps, whitebox environments, establish movement/combat feel</div></div>
|
||||
<div class="phase"><h3>Core Mechanics Development <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+76 Days — +135 Days</div><div class="description">Implement combat, shard-switching, attunement system</div></div>
|
||||
<div class="phase"><h3>First Playable (Vertical Slice) <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+136 Days — +165 Days</div><div class="description">Basic UI, combat, single map, testable state</div></div>
|
||||
<div class="phase"><h3>Story & World Design <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+166 Days — +210 Days</div><div class="description">Write lore, quests, dialogue, map flow</div></div>
|
||||
<div class="phase"><h3>Environment Art & Level Design <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+211 Days — +285 Days</div><div class="description">Model, texture, and populate maps</div></div>
|
||||
<div class="phase"><h3>Multiplayer Networking Setup <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+286 Days — +330 Days</div><div class="description">Mirror or FishNet implementation, lobby & match start logic</div></div>
|
||||
<div class="phase"><h3>UI/UX Polish <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+331 Days — +360 Days</div><div class="description">Final HUD, menus, pause screens</div></div>
|
||||
<div class="phase"><h3>Sound, Music & VFX <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+361 Days — +390 Days</div><div class="description">Placeholders replaced with final effects, transitions</div></div>
|
||||
<div class="phase"><h3>Beta Playtesting <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+391 Days — +420 Days</div><div class="description">Gather feedback on PvP and solo campaign</div></div>
|
||||
<div class="phase"><h3>Final Polish & Optimization <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+421 Days — +450 Days</div><div class="description">Bug fixing, performance, controller support</div></div>
|
||||
<div class="phase"><h3>Marketing & Steam Page Prep <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+451 Days — +471 Days</div><div class="description">Trailer, screenshots, copywriting</div></div>
|
||||
<div class="phase"><h3>Launch <span class="status not-started">Not Started</span><button class="toggle" onclick="toggleStatus(this)">Toggle</button></h3><div class="dates">+472 Days — +479 Days</div><div class="description">Push to Steam, promote, manage release</div></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
{ "id": 1, "title": "Pre-Production", "status": "done" },
|
||||
{ "id": 2, "title": "Blockout Maps & Prototypes", "status": "in progress" },
|
||||
{ "id": 3, "title": "Core Mechanics Development", "status": "not started" },
|
||||
{ "id": 4, "title": "First Playable (Vertical Slice)", "status": "not started" },
|
||||
{ "id": 5, "title": "Story & World Design", "status": "not started" },
|
||||
{ "id": 6, "title": "Environment Art & Level Design", "status": "not started" },
|
||||
{ "id": 7, "title": "Multiplayer Networking Setup", "status": "not started" },
|
||||
{ "id": 8, "title": "UI/UX Polish", "status": "not started" },
|
||||
{ "id": 9, "title": "Sound, Music & VFX", "status": "not started" },
|
||||
{ "id": 10, "title": "Beta Playtesting", "status": "not started" },
|
||||
{ "id": 11, "title": "Final Polish & Optimization", "status": "not started" },
|
||||
{ "id": 12, "title": "Marketing & Steam Page Prep", "status": "not started" },
|
||||
{ "id": 13, "title": "Launch", "status": "not started" }
|
||||
]
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
// server.js (Node.js + Express backend)
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const bodyParser = require('body-parser');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const app = express();
|
||||
|
||||
const SECRET_KEY = 'your_super_secret_key';
|
||||
const PASSWORD = 'shardwalker2025'; // set your password here
|
||||
const PORT = 3000;
|
||||
|
||||
app.use(express.static('public'));
|
||||
app.use(bodyParser.json());
|
||||
app.use(cookieParser());
|
||||
|
||||
// Serve login check
|
||||
app.get('/check-auth', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if (!token) return res.status(401).json({ authenticated: false });
|
||||
|
||||
try {
|
||||
jwt.verify(token, SECRET_KEY);
|
||||
res.json({ authenticated: true });
|
||||
} catch (err) {
|
||||
res.status(403).json({ authenticated: false });
|
||||
}
|
||||
});
|
||||
|
||||
// Login route
|
||||
app.post('/login', (req, res) => {
|
||||
const { password } = req.body;
|
||||
if (password === PASSWORD) {
|
||||
const token = jwt.sign({ user: 'admin' }, SECRET_KEY, { expiresIn: '1d' });
|
||||
res.cookie('token', token, { httpOnly: true });
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
res.status(403).json({ success: false });
|
||||
}
|
||||
});
|
||||
|
||||
// Get current roadmap
|
||||
app.get('/api/roadmap', (req, res) => {
|
||||
const data = fs.readFileSync(path.join(__dirname, 'roadmap.json'));
|
||||
res.json(JSON.parse(data));
|
||||
});
|
||||
|
||||
// Update roadmap status
|
||||
app.post('/api/roadmap', (req, res) => {
|
||||
const token = req.cookies.token;
|
||||
if (!token || !jwt.verify(token, SECRET_KEY)) {
|
||||
return res.status(403).json({ success: false });
|
||||
}
|
||||
const { id, status } = req.body;
|
||||
const filePath = path.join(__dirname, 'roadmap.json');
|
||||
const roadmap = JSON.parse(fs.readFileSync(filePath));
|
||||
const phase = roadmap.find(p => p.id === id);
|
||||
if (phase) {
|
||||
phase.status = status;
|
||||
fs.writeFileSync(filePath, JSON.stringify(roadmap, null, 2));
|
||||
res.json({ success: true });
|
||||
} else {
|
||||
res.status(404).json({ success: false });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`));
|
||||
|
|
@ -11,7 +11,8 @@
|
|||
<nav class="navbar">
|
||||
<a href="index.html">Home</a> |
|
||||
<a href="servermanager.html">Server Manager</a> |
|
||||
<a href="shardwalker.html">Shardwalker</a>
|
||||
<a href="shardwalker.html">Shardwalker</a> |
|
||||
<a href="indie_game_roadmap.html">Indie Game Roadmap</a>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Shardwalker: The Mirror's Edge</title>
|
||||
<link rel="stylesheet" href="shardwalkerMain.css">
|
||||
<meta charset="UTF-8">
|
||||
|
||||
|
||||
|
||||
|
||||
<title>Shardwalker: The Mirror's Edge</title>
|
||||
<link rel="stylesheet" href="shardwalkerMain.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar">
|
||||
<a href="index.html">Home</a> |
|
||||
<a href="servermanager.html">Server Manager</a> |
|
||||
<a href="shardwalker.html">Shardwalker</a>
|
||||
</nav>
|
||||
<nav class="navbar">
|
||||
<a href="index.html">Home</a> |
|
||||
<a href="servermanager.html">Server Manager</a> |
|
||||
<a href="shardwalker.html">Shardwalker</a> |
|
||||
<a href="indie_game_roadmap.html">Indie Game Roadmap</a>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
<header>
|
||||
|
|
|
|||
Loading…
Reference in New Issue