diff options
Diffstat (limited to 'gaming')
50 files changed, 2996 insertions, 0 deletions
diff --git a/gaming/collection/_lib.php b/gaming/collection/_lib.php new file mode 100644 index 0000000..6208465 --- /dev/null +++ b/gaming/collection/_lib.php @@ -0,0 +1,366 @@ +<?php +// Shared helpers for /gaming/collection/ catalog pages. +// Structure inspired by small-web collection catalogs; content & style are SillyLaird's. + +require_once __DIR__ . '/../../partials/i18n.php'; + +function collection_lang(): string { + return _i18n_lang(); +} + +function collection_h(string $k): string { + return htmlspecialchars(t($k), ENT_QUOTES, 'UTF-8'); +} + +function collection_he(string $s): string { + return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); +} + +function collection_load(?string $path = null): array { + $path = $path ?? (__DIR__ . '/games.json'); + $empty = ['consoles' => [], 'hardware' => [], 'systems' => [], 'online' => []]; + if (!is_file($path)) { + return $empty; + } + $raw = file_get_contents($path); + if ($raw === false || trim($raw) === '') { + return $empty; + } + $data = json_decode($raw, true); + if (!is_array($data)) { + return $empty; + } + // Prefer consoles; fall back to legacy videogames key. + $consoles = $data['consoles'] ?? $data['videogames'] ?? []; + return [ + 'consoles' => is_array($consoles) ? $consoles : [], + 'hardware' => is_array($data['hardware'] ?? null) ? $data['hardware'] : [], + 'systems' => is_array($data['systems'] ?? null) ? $data['systems'] : [], + 'online' => is_array($data['online'] ?? null) ? $data['online'] : [], + ]; +} + +function collection_image_src(string $image): string { + $image = trim($image); + if ($image === '') { + return ''; + } + if (str_starts_with($image, 'http://') || str_starts_with($image, 'https://') || str_starts_with($image, '/')) { + return $image; + } + if (str_contains($image, '..') || str_contains($image, "\0")) { + return ''; + } + return '/gaming/collection/images/' . rawurlencode(basename($image)); +} + +function collection_status_class(string $status): string { + $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '-', $status) ?? ''); + $slug = trim($slug, '-'); + return $slug !== '' ? 'status-' . $slug : 'status-other'; +} + +function collection_safe_href(string $url): string { + $url = trim($url); + if ($url === '') { + return ''; + } + if (str_starts_with($url, '/')) { + return str_starts_with($url, '//') ? '' : $url; + } + $scheme = strtolower((string)(parse_url($url, PHP_URL_SCHEME) ?? '')); + if (in_array($scheme, ['http', 'https', 'gemini', 'gopher'], true)) { + return $url; + } + return ''; +} + +/** + * Inventory rows (name :: model) from a flat list (consoles or hardware). + * @param list<array<string,mixed>> $items + * @return list<array{left:string,right:string,status:string,notes:string,image:string,url:string,specs:array<int,array{label:string,value:string}>}> + */ +function collection_inventory_rows(array $items): array { + $rows = []; + foreach ($items as $item) { + if (!is_array($item)) continue; + $name = trim((string)($item['name'] ?? '')); + $model = trim((string)($item['model'] ?? '')); + if ($name === '') continue; + if ($model === '') $model = $name; + $status = (string)($item['status'] ?? 'Owned'); + $rows[] = [ + 'left' => $name, + 'right' => $model, + 'status' => $status, + 'notes' => (string)($item['notes'] ?? ''), + 'image' => (string)($item['image'] ?? ''), + 'url' => '', + 'specs' => [ + ['label' => t('collection.spec_system'), 'value' => $name], + ['label' => t('collection.spec_status'), 'value' => $status], + ], + ]; + } + return $rows; +} + +/** Consoles inventory. */ +function collection_console_rows(array $data): array { + return collection_inventory_rows($data['consoles'] ?? []); +} + +/** Hardware inventory. */ +function collection_hardware_inventory_rows(array $data): array { + return collection_inventory_rows($data['hardware'] ?? []); +} + +/** @deprecated use collection_console_rows */ +function collection_videogame_rows(array $data): array { + return collection_console_rows($data); +} + +/** + * Video games library: titles under systems (system :: title). + * @return list<array{left:string,right:string,status:string,notes:string,image:string,url:string,specs:array<int,array{label:string,value:string}>}> + */ +function collection_games_library_rows(array $data): array { + $rows = []; + foreach (($data['systems'] ?? []) as $sys) { + if (!is_array($sys)) continue; + $left = (string)($sys['name'] ?? ''); + foreach (($sys['games'] ?? []) as $game) { + if (!is_array($game)) continue; + $title = trim((string)($game['title'] ?? '')); + if ($title === '') continue; + $status = (string)($game['status'] ?? 'Owned'); + $rows[] = [ + 'left' => $left, + 'right' => $title, + 'status' => $status, + 'notes' => (string)($game['notes'] ?? ''), + 'image' => (string)($game['image'] ?? ''), + 'url' => '', + 'specs' => [ + ['label' => t('collection.spec_system'), 'value' => $left], + ['label' => t('collection.spec_status'), 'value' => $status], + ], + ]; + } + } + return $rows; +} + +/** @deprecated */ +function collection_tech_rows(array $data): array { + return collection_games_library_rows($data); +} + +/** @deprecated */ +function collection_hardware_rows(array $data): array { + return collection_games_library_rows($data); +} + +/** + * Flatten online song packs into catalog rows. + * @return list<array{left:string,right:string,status:string,notes:string,image:string,url:string,specs:array<int,array{label:string,value:string}>}> + */ +function collection_pack_rows(array $data): array { + $rows = []; + foreach ($data['online'] as $cat) { + if (!is_array($cat)) continue; + $left = (string)($cat['name'] ?? ''); + foreach (($cat['entries'] ?? []) as $entry) { + if (!is_array($entry)) continue; + $title = trim((string)($entry['title'] ?? '')); + if ($title === '') continue; + $status = (string)($entry['status'] ?? 'Owned'); + $url = (string)($entry['url'] ?? ''); + $specs = [ + ['label' => t('collection.spec_game'), 'value' => $left], + ['label' => t('collection.spec_status'), 'value' => $status], + ]; + if ($url !== '') { + $specs[] = ['label' => t('collection.spec_link'), 'value' => t('collection.spec_link_yes')]; + } + $rows[] = [ + 'left' => $left, + 'right' => $title, + 'status' => $status, + 'notes' => (string)($entry['notes'] ?? ''), + 'image' => (string)($entry['image'] ?? ''), + 'url' => $url, + 'specs' => $specs, + ]; + } + } + return $rows; +} + +/** + * @param list<array{left:string,right:string,status:string,notes:string,image:string,url:string,specs:array}> $rows + * @return list<array{left:string,right:string,status:string,notes:string,image:string,url:string,specs:array}> + */ +function collection_filter_wishlist(array $rows): array { + return array_values(array_filter( + $rows, + static fn(array $r) => strcasecmp((string)($r['status'] ?? ''), 'Wishlist') === 0 + )); +} + +/** + * Render one catalog row (photo + name + icon-style specs). + * @param array{left:string,right:string,status:string,notes:string,image:string,url:string,specs?:array} $row + */ +function collection_render_row(array $row): void { + $left = (string)($row['left'] ?? ''); + $right = (string)($row['right'] ?? ''); + $status = (string)($row['status'] ?? 'Owned'); + $notes = (string)($row['notes'] ?? ''); + $img = collection_image_src((string)($row['image'] ?? '')); + $href = collection_safe_href((string)($row['url'] ?? '')); + $specs = is_array($row['specs'] ?? null) ? $row['specs'] : []; + $he = 'collection_he'; + $h = 'collection_h'; + ?> + <div class="gc-row"> + <div class="gc-pic"> + <?php if ($img !== ''): ?> + <a href="<?= $he($img) ?>" target="_blank" rel="noopener noreferrer"> + <img src="<?= $he($img) ?>" alt="" loading="lazy" decoding="async" width="200" height="150" /> + </a> + <?php else: ?> + <div class="gc-pic-empty" aria-hidden="true">no photo</div> + <?php endif; ?> + </div> + <div class="gc-body"> + <p class="gc-name"> + <?php if ($href !== ''): ?> + <a href="<?= $he($href) ?>" target="_blank" rel="noopener noreferrer"><?= $he($left) ?></a> + <span class="gc-colon">::</span> + <a href="<?= $he($href) ?>" target="_blank" rel="noopener noreferrer"><?= $he($right) ?></a> + <?php else: ?> + <span class="gc-nick"><?= $he($left) ?></span> + <span class="gc-colon">::</span> + <span class="gc-model"><?= $he($right) ?></span> + <?php endif; ?> + </p> + <?php if ($notes !== ''): ?> + <p class="gc-note"><em><?= nl2br($he($notes)) ?></em></p> + <?php endif; ?> + <p class="gc-specs"> + <?php foreach ($specs as $spec): + $label = (string)($spec['label'] ?? ''); + $value = (string)($spec['value'] ?? ''); + if ($value === '') continue; + ?> + <span class="gc-spec"> + <span class="gc-spec-ico" title="<?= $he($label) ?>" aria-hidden="true"><?= $he(mb_substr($label, 0, 1)) ?></span> + <span class="gc-spec-val"><?= $he($value) ?></span> + </span> + <?php endforeach; ?> + <?php if ($href !== ''): ?> + <span class="gc-spec"> + <span class="gc-spec-ico" aria-hidden="true">↗</span> + <a class="gc-spec-val" href="<?= $he($href) ?>" target="_blank" rel="noopener noreferrer"><?= $h('collection.visit_product') ?></a> + </span> + <?php endif; ?> + </p> + </div> + </div> + <?php +} + +/** + * Shared page shell open (head + header + title + menu). + * @param 'games'|'consoles'|'hardware'|'packs'|'wishlist' $active + */ +function collection_page_open(string $active, string $pageTitle, string $pageDesc, string $baseFile): void { + $lang = collection_lang(); + $langAttr = ['en' => 'en', 'ja' => 'ja', 'zh' => 'zh'][$lang] ?? 'en'; + $suffix = ['en' => '', 'ja' => '_jp', 'zh' => '_zh'][$lang] ?? ''; + $selfName = $baseFile . $suffix . '.php'; + if ($baseFile === 'index' && $lang === 'en') { + $selfUrl = 'https://www.sillylaird.ca/gaming/collection/'; + $enUrl = 'https://www.sillylaird.ca/gaming/collection/'; + } else { + $selfUrl = 'https://www.sillylaird.ca/gaming/collection/' . $selfName; + $enUrl = 'https://www.sillylaird.ca/gaming/collection/' . ($baseFile === 'index' ? '' : $baseFile . '.php'); + if ($baseFile === 'index') { + $enUrl = 'https://www.sillylaird.ca/gaming/collection/'; + } + } + $jaUrl = 'https://www.sillylaird.ca/gaming/collection/' . $baseFile . '_jp.php'; + $zhUrl = 'https://www.sillylaird.ca/gaming/collection/' . $baseFile . '_zh.php'; + if ($baseFile === 'index') { + $jaUrl = 'https://www.sillylaird.ca/gaming/collection/index_jp.php'; + $zhUrl = 'https://www.sillylaird.ca/gaming/collection/index_zh.php'; + } + $h = 'collection_h'; + // Video Games / Consoles / Hardware / Song Packs / Wishlist + if ($lang === 'ja') { + $hrefGames = '/gaming/collection/index_jp.php'; + $hrefCons = '/gaming/collection/consoles_jp.php'; + $hrefHw = '/gaming/collection/hardware_jp.php'; + $hrefPk = '/gaming/collection/packs_jp.php'; + $hrefWl = '/gaming/collection/wishlist_jp.php'; + } elseif ($lang === 'zh') { + $hrefGames = '/gaming/collection/index_zh.php'; + $hrefCons = '/gaming/collection/consoles_zh.php'; + $hrefHw = '/gaming/collection/hardware_zh.php'; + $hrefPk = '/gaming/collection/packs_zh.php'; + $hrefWl = '/gaming/collection/wishlist_zh.php'; + } else { + $hrefGames = '/gaming/collection/'; + $hrefCons = '/gaming/collection/consoles.php'; + $hrefHw = '/gaming/collection/hardware.php'; + $hrefPk = '/gaming/collection/packs.php'; + $hrefWl = '/gaming/collection/wishlist.php'; + } + $act = static fn(string $key) => $active === $key ? ' class="gc-menu-active" id="gc-main"' : ''; + ?> +<!doctype html> +<html lang="<?= $langAttr ?>"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title><?= collection_he($pageTitle) ?></title> + <?php + $meta = [ + 'lang' => $lang, + 'title' => $pageTitle, + 'desc' => $pageDesc, + 'base' => 'gaming/collection/' . $baseFile, + 'self_url' => $selfUrl, + 'en_url' => $enUrl, + 'x_default' => $enUrl, + 'ja_url' => $jaUrl, + 'zh_url' => $zhUrl, + ]; + include __DIR__ . '/../../partials/head_meta.php'; + ?> + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> + <link rel="stylesheet" href="/assets/css/pages/collection.css" /> +</head> +<body class="gc-page"> + <a class="skip-link" href="#main"><?= $h('common.skip') ?></a> + <?php include __DIR__ . '/../../partials/header.php'; ?> + + <main id="main" class="wrap gc-wrap"> + <p class="gc-title"><?= $h('collection.h1') ?></p> + <nav class="gc-menu" aria-label="<?= $h('collection.jump_nav') ?>"> + <a href="<?= collection_he($hrefGames) ?>"<?= $act('games') ?>><?= $h('collection.menu_games') ?></a><span class="gc-menu-sep">/</span><a href="<?= collection_he($hrefCons) ?>"<?= $act('consoles') ?>><?= $h('collection.menu_consoles') ?></a><span class="gc-menu-sep">/</span><a href="<?= collection_he($hrefHw) ?>"<?= $act('hardware') ?>><?= $h('collection.menu_hardware') ?></a><span class="gc-menu-sep">/</span><a href="<?= collection_he($hrefPk) ?>"<?= $act('packs') ?>><?= $h('collection.menu_packs') ?></a><span class="gc-menu-sep">/</span><a href="<?= collection_he($hrefWl) ?>"<?= $act('wishlist') ?>><?= $h('collection.menu_wishlist') ?></a> + </nav> + <?php +} + +function collection_page_close(): void { + ?> + </main> + <?php include __DIR__ . '/../../partials/footer.php'; ?> +</body> +</html> + <?php +} diff --git a/gaming/collection/admin.php b/gaming/collection/admin.php new file mode 100644 index 0000000..487e181 --- /dev/null +++ b/gaming/collection/admin.php @@ -0,0 +1 @@ +<?php header('Location: /admin.php?section=collection', true, 302); exit; diff --git a/gaming/collection/consoles.php b/gaming/collection/consoles.php new file mode 100644 index 0000000..d0aae70 --- /dev/null +++ b/gaming/collection/consoles.php @@ -0,0 +1,36 @@ +<?php +/** + * Consoles inventory (name :: model). + */ +require_once __DIR__ . '/_lib.php'; + +$data = collection_load(); +$rows = collection_console_rows($data); + +collection_page_open( + 'consoles', + t('collection.consoles_title'), + t('collection.consoles_blurb'), + 'consoles' +); +?> + <p class="gc-page-blurb"><?= collection_h('collection.consoles_blurb') ?></p> + <p class="gc-count"><?= count($rows) ?> <?= collection_h('collection.consoles_label') ?></p> + +<?php if (!$rows): ?> + <p class="gc-empty"><?= collection_h('collection.consoles_empty') ?></p> +<?php else: ?> + <div class="gc-catalog"> +<?php foreach ($rows as $row) { + collection_render_row($row); +} ?> + </div> +<?php endif; ?> + + <p class="gc-footer-hint"> + <a href="/gaming/collection/"><?= collection_h('collection.menu_games') ?></a> + · + <a href="/gaming/"><?= collection_h('collection.back_gaming') ?></a> + </p> +<?php +collection_page_close(); diff --git a/gaming/collection/consoles_jp.php b/gaming/collection/consoles_jp.php new file mode 100644 index 0000000..af85a23 --- /dev/null +++ b/gaming/collection/consoles_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/consoles.php'; diff --git a/gaming/collection/consoles_zh.php b/gaming/collection/consoles_zh.php new file mode 100644 index 0000000..af85a23 --- /dev/null +++ b/gaming/collection/consoles_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/consoles.php'; diff --git a/gaming/collection/games.json b/gaming/collection/games.json new file mode 100644 index 0000000..f60562d --- /dev/null +++ b/gaming/collection/games.json @@ -0,0 +1,145 @@ +{ + "consoles": [ + { + "id": "snes", + "name": "SNES", + "model": "Super Nintendo Entertainment System", + "status": "Owned", + "notes": "Retro living-room console", + "image": "" + }, + { + "id": "popn-cab", + "name": "Pop'n Music", + "model": "Cabinet / controller setup", + "status": "Owned", + "notes": "Pop'n buttons / cabinet or sim", + "image": "" + } + ], + "hardware": [ + { + "id": "dtx-cab", + "name": "DTXMania", + "model": "Drum cabinet / sim rig", + "status": "Playing", + "notes": "Local DTX drum hardware setup", + "image": "" + } + ], + "systems": [ + { + "id": "snes", + "name": "SNES", + "games": [ + { + "id": "smw", + "title": "Super Mario World", + "status": "Owned", + "notes": "Super Scope ready", + "image": "" + } + ] + }, + { + "id": "dtxmania", + "name": "DTXMania", + "games": [ + { + "id": "dtx-setup", + "title": "DTXMania NX", + "status": "Playing", + "notes": "Software / setup notes", + "image": "" + } + ] + }, + { + "id": "popn", + "name": "Pop'n Music", + "games": [ + { + "id": "popn-cabinet", + "title": "Pop'n Music (cabinet / sim)", + "status": "Owned", + "notes": "Cabinet / sim title entry", + "image": "" + } + ] + } + ], + "online": [ + { + "id": "popn-lively", + "name": "Pop'n Music Lively", + "entries": [ + { + "id": "popn-starter", + "title": "Starter Pack", + "url": "https://p.eagate.573.jp/game/popn/lively/", + "status": "Owned", + "notes": "Base song set", + "image": "" + }, + { + "id": "popn-music-pack-1", + "title": "Music Pack", + "url": "https://p.eagate.573.jp/game/popn/lively/", + "status": "Wishlist", + "notes": "DLC song pack", + "image": "" + } + ] + }, + { + "id": "gitadora", + "name": "GITADORA", + "entries": [ + { + "id": "gfdm-music-pack-1", + "title": "Music Pack", + "url": "https://p.eagate.573.jp/game/gfdm/", + "status": "Wishlist", + "notes": "GITADORA song pack", + "image": "" + } + ] + }, + { + "id": "iidx-infinitas", + "name": "beatmania IIDX INFINITAS", + "entries": [ + { + "id": "iidx-music-pack-1", + "title": "Music Pack", + "url": "https://p.eagate.573.jp/game/2dx/inf/", + "status": "Wishlist", + "notes": "INFINITAS song pack", + "image": "" + } + ] + }, + { + "id": "simulators", + "name": "Simulators & tools", + "entries": [ + { + "id": "dtxmania-nx", + "title": "DTXMania NX", + "url": "https://github.com/limyz/DTXManiaNX", + "status": "Playing", + "notes": "Open-source DTX drum simulator", + "image": "" + }, + { + "id": "stepmania", + "title": "StepMania", + "url": "https://www.stepmania.com/", + "status": "Owned", + "notes": "Open-source dance game engine", + "image": "" + } + ] + } + ] +} diff --git a/gaming/collection/hardware.php b/gaming/collection/hardware.php new file mode 100644 index 0000000..62cae6e --- /dev/null +++ b/gaming/collection/hardware.php @@ -0,0 +1,36 @@ +<?php +/** + * Hardware inventory (name :: model). + */ +require_once __DIR__ . '/_lib.php'; + +$data = collection_load(); +$rows = collection_hardware_inventory_rows($data); + +collection_page_open( + 'hardware', + t('collection.hardware_title'), + t('collection.hardware_page_blurb'), + 'hardware' +); +?> + <p class="gc-page-blurb"><?= collection_h('collection.hardware_page_blurb') ?></p> + <p class="gc-count"><?= count($rows) ?> <?= collection_h('collection.hardware_label') ?></p> + +<?php if (!$rows): ?> + <p class="gc-empty"><?= collection_h('collection.hardware_empty') ?></p> +<?php else: ?> + <div class="gc-catalog"> +<?php foreach ($rows as $row) { + collection_render_row($row); +} ?> + </div> +<?php endif; ?> + + <p class="gc-footer-hint"> + <a href="/gaming/collection/"><?= collection_h('collection.menu_games') ?></a> + · + <a href="/gaming/"><?= collection_h('collection.back_gaming') ?></a> + </p> +<?php +collection_page_close(); diff --git a/gaming/collection/hardware_jp.php b/gaming/collection/hardware_jp.php new file mode 100644 index 0000000..bc9dcf4 --- /dev/null +++ b/gaming/collection/hardware_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/hardware.php'; diff --git a/gaming/collection/hardware_zh.php b/gaming/collection/hardware_zh.php new file mode 100644 index 0000000..bc9dcf4 --- /dev/null +++ b/gaming/collection/hardware_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/hardware.php'; diff --git a/gaming/collection/images/.gitkeep b/gaming/collection/images/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gaming/collection/images/.gitkeep diff --git a/gaming/collection/index.php b/gaming/collection/index.php new file mode 100644 index 0000000..a2e3fa7 --- /dev/null +++ b/gaming/collection/index.php @@ -0,0 +1,36 @@ +<?php +/** + * Video Games — title library (system :: title). + */ +require_once __DIR__ . '/_lib.php'; + +$data = collection_load(); +$rows = collection_games_library_rows($data); + +collection_page_open( + 'games', + t('collection.title'), + t('collection.desc'), + 'index' +); +?> + <p class="gc-page-blurb"><?= collection_h('collection.games_blurb') ?></p> + <p class="gc-count"><?= count($rows) ?> <?= collection_h('collection.games_label') ?></p> + +<?php if (!$rows): ?> + <p class="gc-empty"><?= collection_h('collection.empty') ?></p> +<?php else: ?> + <div class="gc-catalog"> +<?php foreach ($rows as $row) { + collection_render_row($row); +} ?> + </div> +<?php endif; ?> + + <p class="gc-footer-hint"> + <a href="/gaming/"><?= collection_h('collection.back_gaming') ?></a> + · + <a href="/"><?= collection_h('collection.back_home') ?></a> + </p> +<?php +collection_page_close(); diff --git a/gaming/collection/index_jp.php b/gaming/collection/index_jp.php new file mode 100644 index 0000000..50bbcec --- /dev/null +++ b/gaming/collection/index_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/index.php'; diff --git a/gaming/collection/index_zh.php b/gaming/collection/index_zh.php new file mode 100644 index 0000000..50bbcec --- /dev/null +++ b/gaming/collection/index_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/index.php'; diff --git a/gaming/collection/packs.php b/gaming/collection/packs.php new file mode 100644 index 0000000..a8e216f --- /dev/null +++ b/gaming/collection/packs.php @@ -0,0 +1,36 @@ +<?php +/** + * Song packs catalog page. + */ +require_once __DIR__ . '/_lib.php'; + +$data = collection_load(); +$rows = collection_pack_rows($data); + +collection_page_open( + 'packs', + t('collection.packs_title'), + t('collection.online_subtitle'), + 'packs' +); +?> + <p class="gc-page-blurb"><?= collection_h('collection.online_subtitle') ?></p> + <p class="gc-count"><?= count($rows) ?> <?= collection_h('collection.online_links_label') ?></p> + +<?php if (!$rows): ?> + <p class="gc-empty"><?= collection_h('collection.online_empty') ?></p> +<?php else: ?> + <div class="gc-catalog"> +<?php foreach ($rows as $row) { + collection_render_row($row); +} ?> + </div> +<?php endif; ?> + + <p class="gc-footer-hint"> + <a href="/gaming/collection/"><?= collection_h('collection.menu_hardware') ?></a> + · + <a href="/gaming/"><?= collection_h('collection.back_gaming') ?></a> + </p> +<?php +collection_page_close(); diff --git a/gaming/collection/packs_jp.php b/gaming/collection/packs_jp.php new file mode 100644 index 0000000..3ffa479 --- /dev/null +++ b/gaming/collection/packs_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/packs.php'; diff --git a/gaming/collection/packs_zh.php b/gaming/collection/packs_zh.php new file mode 100644 index 0000000..3ffa479 --- /dev/null +++ b/gaming/collection/packs_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/packs.php'; diff --git a/gaming/collection/tech.php b/gaming/collection/tech.php new file mode 100644 index 0000000..1e158ee --- /dev/null +++ b/gaming/collection/tech.php @@ -0,0 +1,4 @@ +<?php +// Legacy URL: former Library/Tech page → Video Games (title library). +header('Location: /gaming/collection/', true, 302); +exit; diff --git a/gaming/collection/tech_jp.php b/gaming/collection/tech_jp.php new file mode 100644 index 0000000..103a452 --- /dev/null +++ b/gaming/collection/tech_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/tech.php'; diff --git a/gaming/collection/tech_zh.php b/gaming/collection/tech_zh.php new file mode 100644 index 0000000..103a452 --- /dev/null +++ b/gaming/collection/tech_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/tech.php'; diff --git a/gaming/collection/wishlist.php b/gaming/collection/wishlist.php new file mode 100644 index 0000000..47fa2a4 --- /dev/null +++ b/gaming/collection/wishlist.php @@ -0,0 +1,45 @@ +<?php +/** + * Wishlist — games, consoles, hardware, and song packs marked Wishlist. + */ +require_once __DIR__ . '/_lib.php'; + +$data = collection_load(); +$rows = collection_filter_wishlist(array_merge( + collection_games_library_rows($data), + collection_console_rows($data), + collection_hardware_inventory_rows($data), + collection_pack_rows($data) +)); + +collection_page_open( + 'wishlist', + t('collection.wishlist_title'), + t('collection.wishlist_blurb'), + 'wishlist' +); +?> + <p class="gc-page-blurb"><?= collection_h('collection.wishlist_blurb') ?></p> + <p class="gc-count"><?= count($rows) ?> <?= collection_h('collection.wishlist_count') ?></p> + +<?php if (!$rows): ?> + <p class="gc-empty"><?= collection_h('collection.wishlist_empty') ?></p> +<?php else: ?> + <div class="gc-catalog"> +<?php foreach ($rows as $row) { + collection_render_row($row); +} ?> + </div> +<?php endif; ?> + + <p class="gc-footer-hint"> + <a href="/gaming/collection/"><?= collection_h('collection.menu_games') ?></a> + · + <a href="/gaming/collection/consoles.php"><?= collection_h('collection.menu_consoles') ?></a> + · + <a href="/gaming/collection/hardware.php"><?= collection_h('collection.menu_hardware') ?></a> + · + <a href="/gaming/collection/packs.php"><?= collection_h('collection.menu_packs') ?></a> + </p> +<?php +collection_page_close(); diff --git a/gaming/collection/wishlist_jp.php b/gaming/collection/wishlist_jp.php new file mode 100644 index 0000000..8ed194a --- /dev/null +++ b/gaming/collection/wishlist_jp.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/wishlist.php'; diff --git a/gaming/collection/wishlist_zh.php b/gaming/collection/wishlist_zh.php new file mode 100644 index 0000000..8ed194a --- /dev/null +++ b/gaming/collection/wishlist_zh.php @@ -0,0 +1 @@ +<?php require __DIR__ . '/wishlist.php'; diff --git a/gaming/index.php b/gaming/index.php new file mode 100644 index 0000000..a07b279 --- /dev/null +++ b/gaming/index.php @@ -0,0 +1,78 @@ +<!doctype html> +<html lang="en"> + +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Gaming — SillyLaird</title> + +<?php + $meta = [ + 'lang' => 'en', + 'title' => 'Gaming — SillyLaird', + 'desc' => 'Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more.', + 'base' => 'gaming/index', + 'self_url' => 'https://www.sillylaird.ca/gaming/', + 'en_url' => 'https://www.sillylaird.ca/gaming/', + 'x_default' => 'https://www.sillylaird.ca/gaming/', + 'ja_url' => 'https://www.sillylaird.ca/gaming/index_jp.php', + 'zh_url' => 'https://www.sillylaird.ca/gaming/index_zh.php', + ]; + include __DIR__ . '/../partials/head_meta.php'; +?> + + + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> + <link rel="stylesheet" href="/assets/css/pages/computers.css" /> + +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="gaming-title"> + <h1 id="gaming-title">Gaming</h1> + <p class="muted">Pages for games and projects.</p> + + <div class="machine" style="margin:var(--space-lg) 0;"> + <div class="machine-info"> + <div class="machine-title"><a href="/gaming/collection/">Game Collection</a></div> + Video Games / Consoles / Hardware / Song Packs / Wishlist.<br> + <a href="/gaming/collection/">Video Games</a> + / <a href="/gaming/collection/consoles.php">Consoles</a> + / <a href="/gaming/collection/hardware.php">Hardware</a> + / <a href="/gaming/collection/packs.php">Song Packs</a> + / <a href="/gaming/collection/wishlist.php">Wishlist</a> + </div> + </div> + + <div class="machine machine--notes"> + <div class="machine-info"> + <div class="machine-title">Rhythm-game bench</div> + Current setup notes live alongside the collection: DTXMania / GITADORA configurations, pop'n music links, StepMania, and the occasional Super Scope session. + <br><a href="/gaming/collection/packs.php">Browse song packs</a> · <a href="/gaming/stepmania/">Open StepMania</a> + </div> + </div> + + <ul class="tile-grid"> + <li><a href="/gaming/runescape/"><img src="/assets/img/runescape.png" alt="RuneScape" loading="lazy" decoding="async"></a> + </li> + <li><a href="/gaming/specialforce/"><img src="/assets/img/soldierfront.png" alt="SpecialForce / SoldierFront" + loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/stepmania/"><img src="/assets/img/stepmania.png" alt="StepMania" loading="lazy" decoding="async"></a> + </li> + <li><a href="/gaming/multibox/"><img src="/assets/img/multibox.png" alt="MMO Multibox" loading="lazy" decoding="async"></a> + </li> + </ul> + </section> + </main> + + <?php include '../partials/footer.php'; ?> +</body> + +</html> diff --git a/gaming/index_jp.php b/gaming/index_jp.php new file mode 100644 index 0000000..553a981 --- /dev/null +++ b/gaming/index_jp.php @@ -0,0 +1,65 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>ゲーム — SillyLaird</title> + <meta name="description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta property="og:title" content="ゲーム — SillyLaird" /> + <meta property="og:description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="ゲーム — SillyLaird" /> + <meta name="twitter:description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> + <link rel="stylesheet" href="/assets/css/pages/computers.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="gaming-title"> + <h1 id="gaming-title">ゲーム</h1> + <p class="muted">Pages for games and projects.</p> + + <div class="machine" style="margin:var(--space-lg) 0;"> + <div class="machine-info"> + <div class="machine-title"><a href="/gaming/collection/">ゲームコレクション</a></div> + ビデオゲーム / 本体 / ハードウェア / 楽曲パック / ウィッシュリスト。<br> + <a href="/gaming/collection/">ビデオゲーム</a> + / <a href="/gaming/collection/consoles.php">本体</a> + / <a href="/gaming/collection/hardware.php">ハードウェア</a> + / <a href="/gaming/collection/packs.php">楽曲パック</a> + / <a href="/gaming/collection/wishlist.php">ウィッシュリスト</a> + </div> + </div> + + <ul class="tile-grid"> + <li><a href="/gaming/runescape/"><img src="/assets/img/runescape.png" alt="RuneScape" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/specialforce/"><img src="/assets/img/soldierfront.png" alt="SpecialForce / SoldierFront" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/stepmania/"><img src="/assets/img/stepmania.png" alt="StepMania" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/multibox/"><img src="/assets/img/multibox.png" alt="MMO Multibox" loading="lazy" decoding="async"></a></li> + </ul> + </section> + </main> + + <?php include '../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/index_zh.php b/gaming/index_zh.php new file mode 100644 index 0000000..214e0ae --- /dev/null +++ b/gaming/index_zh.php @@ -0,0 +1,65 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>游戏 — SillyLaird</title> + <meta name="description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta property="og:title" content="游戏 — SillyLaird" /> + <meta property="og:description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="游戏 — SillyLaird" /> + <meta name="twitter:description" content="Games I play and projects I mess with — RuneScape, StepMania, SoldierFront, and more." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> + <link rel="stylesheet" href="/assets/css/pages/computers.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="gaming-title"> + <h1 id="gaming-title">游戏</h1> + <p class="muted">Pages for games and projects.</p> + + <div class="machine" style="margin:var(--space-lg) 0;"> + <div class="machine-info"> + <div class="machine-title"><a href="/gaming/collection/">游戏收藏</a></div> + 电子游戏 / 主机 / 硬件 / 曲包 / 愿望单。<br> + <a href="/gaming/collection/">电子游戏</a> + / <a href="/gaming/collection/consoles.php">主机</a> + / <a href="/gaming/collection/hardware.php">硬件</a> + / <a href="/gaming/collection/packs.php">曲包</a> + / <a href="/gaming/collection/wishlist.php">愿望单</a> + </div> + </div> + + <ul class="tile-grid"> + <li><a href="/gaming/runescape/"><img src="/assets/img/runescape.png" alt="RuneScape" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/specialforce/"><img src="/assets/img/soldierfront.png" alt="SpecialForce / SoldierFront" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/stepmania/"><img src="/assets/img/stepmania.png" alt="StepMania" loading="lazy" decoding="async"></a></li> + <li><a href="/gaming/multibox/"><img src="/assets/img/multibox.png" alt="MMO Multibox" loading="lazy" decoding="async"></a></li> + </ul> + </section> + </main> + + <?php include '../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/global_styles.css b/gaming/multibox/global_styles.css new file mode 100644 index 0000000..fe453ea --- /dev/null +++ b/gaming/multibox/global_styles.css @@ -0,0 +1,53 @@ +/* styles.css */ + +body { + font-family: Arial, sans-serif; + line-height: 1.6; + margin: 0; + padding: 0; + background-color: #f4f4f4; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +header { + background: #333; + color: #fff; + padding: 10px 0; + text-align: center; +} + +nav ul { + list-style: none; + padding: 0; +} + +nav ul li { + display: inline; + margin: 0 15px; +} + +nav ul li a { + color: #fff; + text-decoration: none; +} + +main { + padding: 20px; + flex: 1; +} + +h2 { + color: #333; +} + +footer { + background: #333; + color: #fff; + text-align: center; + padding: 10px 0; + position: fixed; + width: 100%; + bottom: 0; +}
\ No newline at end of file diff --git a/gaming/multibox/index.php b/gaming/multibox/index.php new file mode 100644 index 0000000..11c5670 --- /dev/null +++ b/gaming/multibox/index.php @@ -0,0 +1,101 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Multiboxing — SillyLaird</title> + <meta name="description" content="Multiboxing in MMORPGs." /> + <meta property="og:title" content="Multiboxing — SillyLaird" /> + <meta property="og:description" content="Multiboxing in MMORPGs." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/" /> + <meta property="og:locale" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="Multiboxing — SillyLaird" /> + <meta name="twitter:description" content="Multiboxing in MMORPGs." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="mb-title"> + <h1 id="mb-title">Multiboxing in MMORPGs</h1> + <p class="muted">Playing multiple characters at the same time.</p> + </section> + + <section id="what-is-multiboxing" aria-labelledby="what-title"> + <h2 id="what-title">What is Multiboxing?</h2> + <p>Multiboxing is the practice of playing multiple characters at the same time in a Massively Multiplayer Online Role-Playing Game (MMORPG). This technique generally requires the use of multiple game accounts and can be achieved using different methods such as employing multiple computers, using specialized software, or even running multiple instances of the same game on a single computer.</p> + <p>Players who multibox often do so to gain advantages such as increased efficiency in resource gathering, leveling up multiple characters simultaneously, or taking on game content that would typically require a group of players.</p> + </section> + + <section id="pros-cons" aria-labelledby="pros-title"> + <h2 id="pros-title">Pros and Cons</h2> + + <h3>Pros</h3> + <ul> + <li>More control over your gameplay experience.</li> + <li>Ability to accomplish multi-character tasks solo.</li> + <li>Increased resource gathering and in-game efficiency.</li> + </ul> + + <h3>Cons</h3> + <ul> + <li>Requires significant hardware capabilities.</li> + <li>Can be costly due to multiple subscriptions.</li> + <li>Potential for breaches of game terms of service.</li> + </ul> + </section> + + <section id="getting-started" aria-labelledby="start-title"> + <h2 id="start-title">Getting Started</h2> + <p>To begin multiboxing, you will need:</p> + <ul> + <li>Multiple game accounts.</li> + <li>A computer that can handle running multiple instances of the game.</li> + <li>Knowledge of key broadcasting software.</li> + </ul> + </section> + + <section id="tools" aria-labelledby="tools-title"> + <h2 id="tools-title">Tools and Software</h2> + <ul> + <li>ISBoxer</li> + <li>HotkeyNet</li> + <li>AutoHotkey</li> + </ul> + </section> + + <section id="examples" aria-labelledby="examples-title"> + <h2 id="examples-title">Examples on YouTube</h2> + + <p><iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">OSRS/RuneScape MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/nJ428TJs6Mw" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">WOW MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/lvTl1qEvJms" allowfullscreen title="TF2 multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">TF2 Cheating "MultiBoxing"</p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/index_jp.php b/gaming/multibox/index_jp.php new file mode 100644 index 0000000..ee09b1e --- /dev/null +++ b/gaming/multibox/index_jp.php @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Multiboxing — SillyLaird</title> + <meta name="description" content="Multiboxing in MMORPGs." /> + <meta property="og:title" content="Multiboxing — SillyLaird" /> + <meta property="og:description" content="Multiboxing in MMORPGs." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="Multiboxing — SillyLaird" /> + <meta name="twitter:description" content="Multiboxing in MMORPGs." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="mb-title"> + <h1 id="mb-title">Multiboxing in MMORPGs</h1> + <p class="muted">Playing multiple characters at the same time.</p> + </section> + + <section id="what-is-multiboxing" aria-labelledby="what-title"> + <h2 id="what-title">What is Multiboxing?</h2> + <p>Multiboxing is a term used in MMORPGs that refers to playing multiple characters simultaneously. This is usually done using multiple accounts, computers, or software.</p> + </section> + + <section id="pros-cons" aria-labelledby="pros-title"> + <h2 id="pros-title">Pros and Cons</h2> + + <h3>Pros</h3> + <ul> + <li>More control over your gameplay experience.</li> + <li>Ability to accomplish multi-character tasks solo.</li> + <li>Increased resource gathering and in-game efficiency.</li> + </ul> + + <h3>Cons</h3> + <ul> + <li>Requires significant hardware capabilities.</li> + <li>Can be costly due to multiple subscriptions.</li> + <li>Potential for breaches of game terms of service.</li> + </ul> + </section> + + <section id="getting-started" aria-labelledby="start-title"> + <h2 id="start-title">Getting Started</h2> + <p>To begin multiboxing, you will need:</p> + <ul> + <li>Multiple game accounts.</li> + <li>A computer that can handle running multiple instances of the game.</li> + <li>Knowledge of key broadcasting software.</li> + </ul> + </section> + + <section id="tools" aria-labelledby="tools-title"> + <h2 id="tools-title">Tools and Software</h2> + <ul> + <li>ISBoxer</li> + <li>HotkeyNet</li> + <li>AutoHotkey</li> + </ul> + </section> + + <section id="examples" aria-labelledby="examples-title"> + <h2 id="examples-title">Examples on YouTube</h2> + + <p><iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">OSRS/RuneScape MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/nJ428TJs6Mw" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">WOW MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/lvTl1qEvJms" allowfullscreen title="TF2 multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">TF2 Cheating "MultiBoxing"</p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/index_zh.php b/gaming/multibox/index_zh.php new file mode 100644 index 0000000..b8214ad --- /dev/null +++ b/gaming/multibox/index_zh.php @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Multiboxing — SillyLaird</title> + <meta name="description" content="Multiboxing in MMORPGs." /> + <meta property="og:title" content="Multiboxing — SillyLaird" /> + <meta property="og:description" content="Multiboxing in MMORPGs." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="Multiboxing — SillyLaird" /> + <meta name="twitter:description" content="Multiboxing in MMORPGs." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="mb-title"> + <h1 id="mb-title">Multiboxing in MMORPGs</h1> + <p class="muted">Playing multiple characters at the same time.</p> + </section> + + <section id="what-is-multiboxing" aria-labelledby="what-title"> + <h2 id="what-title">What is Multiboxing?</h2> + <p>Multiboxing is a term used in MMORPGs that refers to playing multiple characters simultaneously. This is usually done using multiple accounts, computers, or software.</p> + </section> + + <section id="pros-cons" aria-labelledby="pros-title"> + <h2 id="pros-title">Pros and Cons</h2> + + <h3>Pros</h3> + <ul> + <li>More control over your gameplay experience.</li> + <li>Ability to accomplish multi-character tasks solo.</li> + <li>Increased resource gathering and in-game efficiency.</li> + </ul> + + <h3>Cons</h3> + <ul> + <li>Requires significant hardware capabilities.</li> + <li>Can be costly due to multiple subscriptions.</li> + <li>Potential for breaches of game terms of service.</li> + </ul> + </section> + + <section id="getting-started" aria-labelledby="start-title"> + <h2 id="start-title">Getting Started</h2> + <p>To begin multiboxing, you will need:</p> + <ul> + <li>Multiple game accounts.</li> + <li>A computer that can handle running multiple instances of the game.</li> + <li>Knowledge of key broadcasting software.</li> + </ul> + </section> + + <section id="tools" aria-labelledby="tools-title"> + <h2 id="tools-title">Tools and Software</h2> + <ul> + <li>ISBoxer</li> + <li>HotkeyNet</li> + <li>AutoHotkey</li> + </ul> + </section> + + <section id="examples" aria-labelledby="examples-title"> + <h2 id="examples-title">Examples on YouTube</h2> + + <p><iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">OSRS/RuneScape MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/nJ428TJs6Mw" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">WOW MultiBoxing</p> + + <p><iframe src="https://www.youtube.com/embed/lvTl1qEvJms" allowfullscreen title="TF2 multiboxing" class="saf481e1471"></iframe></p> + <p class="muted">TF2 Cheating "MultiBoxing"</p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/styles.css b/gaming/multibox/styles.css new file mode 100644 index 0000000..95dea86 --- /dev/null +++ b/gaming/multibox/styles.css @@ -0,0 +1,54 @@ +/* styles.css */
+
+body {
+ font-family: Arial, sans-serif;
+ line-height: 1.6;
+ margin: 0;
+ padding: 0;
+ background-color: #f4f4f4;
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+
+header {
+ background: #333;
+ color: #fff;
+ padding: 10px 0;
+ text-align: center;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+}
+
+nav ul li {
+ display: inline;
+ margin: 0 15px;
+}
+
+nav ul li a {
+ color: #fff;
+ text-decoration: none;
+}
+
+main {
+ padding: 20px;
+ flex: 1;
+ padding-bottom: 60px; /* Add bottom padding to ensure space for footer */
+}
+
+h2 {
+ color: #333;
+}
+
+footer {
+ background: #333;
+ color: #fff;
+ text-align: center;
+ padding: 10px 0;
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+}
\ No newline at end of file diff --git a/gaming/multibox/what-is-multiboxing/index.php b/gaming/multibox/what-is-multiboxing/index.php new file mode 100644 index 0000000..bc785b6 --- /dev/null +++ b/gaming/multibox/what-is-multiboxing/index.php @@ -0,0 +1,77 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>What Is Multiboxing? — SillyLaird</title> + <meta name="description" content="Detailed multiboxing overview." /> + <meta property="og:title" content="What Is Multiboxing? — SillyLaird" /> + <meta property="og:description" content="Detailed multiboxing overview." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <meta property="og:locale" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="What Is Multiboxing? — SillyLaird" /> + <meta name="twitter:description" content="Detailed multiboxing overview." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="title"> + <h1 id="title">What is Multiboxing?</h1> + <p class="muted">A longer explanation (methods, uses, examples).</p> + </section> + + <section> + <h2>Overview</h2> + <p>Multiboxing is the practice of playing multiple characters at the same time in a Massively Multiplayer Online Role-Playing Game (MMORPG). This technique generally requires the use of multiple game accounts and can be achieved using different methods such as employing multiple computers, using specialized software, or even running multiple instances of the same game on a single computer.</p> + <p>Players who multibox often do so to gain advantages such as increased efficiency in resource gathering, leveling up multiple characters simultaneously, or taking on game content that would typically require a group of players.</p> + </section> + + <section> + <h2>Methods</h2> + <ul> + <li><strong>Multiple Computers:</strong> Several physical PCs, each running one account.</li> + <li><strong>Virtual Machines:</strong> Multiple OS instances on one machine.</li> + <li><strong>Software Solutions:</strong> Keystroke broadcasting / window management tools (game ToS varies).</li> + </ul> + </section> + + <section> + <h2>Common Uses</h2> + <ul> + <li><strong>Solo Group Content:</strong> Do group content without other players.</li> + <li><strong>Economy Control:</strong> Resource gathering / crafting on multiple chars.</li> + <li><strong>Power Leveling:</strong> Level alts quickly with a main.</li> + </ul> + </section> + + <section> + <h2>Examples</h2> + <p><strong>Old School RuneScape (OSRS)</strong></p> + <iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe> + <p><strong>World of Warcraft (WoW)</strong></p> + <iframe src="https://www.youtube.com/embed/a5_5kbbmEiM" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe> + </section> + </main> + + <?php include '../../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/what-is-multiboxing/index_jp.php b/gaming/multibox/what-is-multiboxing/index_jp.php new file mode 100644 index 0000000..a40037f --- /dev/null +++ b/gaming/multibox/what-is-multiboxing/index_jp.php @@ -0,0 +1,77 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>What Is Multiboxing? — SillyLaird</title> + <meta name="description" content="Detailed multiboxing overview." /> + <meta property="og:title" content="What Is Multiboxing? — SillyLaird" /> + <meta property="og:description" content="Detailed multiboxing overview." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="What Is Multiboxing? — SillyLaird" /> + <meta name="twitter:description" content="Detailed multiboxing overview." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="title"> + <h1 id="title">What is Multiboxing?</h1> + <p class="muted">A longer explanation (methods, uses, examples).</p> + </section> + + <section> + <h2>Overview</h2> + <p>Multiboxing is the practice of playing multiple characters at the same time in a Massively Multiplayer Online Role-Playing Game (MMORPG). This technique generally requires the use of multiple game accounts and can be achieved using different methods such as employing multiple computers, using specialized software, or even running multiple instances of the same game on a single computer.</p> + <p>Players who multibox often do so to gain advantages such as increased efficiency in resource gathering, leveling up multiple characters simultaneously, or taking on game content that would typically require a group of players.</p> + </section> + + <section> + <h2>Methods</h2> + <ul> + <li><strong>Multiple コンピューター:</strong> Several physical PCs, each running one account.</li> + <li><strong>Virtual Machines:</strong> Multiple OS instances on one machine.</li> + <li><strong>Software Solutions:</strong> Keystroke broadcasting / window management tools (game ToS varies).</li> + </ul> + </section> + + <section> + <h2>Common Uses</h2> + <ul> + <li><strong>Solo Group Content:</strong> Do group content without other players.</li> + <li><strong>Economy Control:</strong> Resource gathering / crafting on multiple chars.</li> + <li><strong>Power Leveling:</strong> Level alts quickly with a main.</li> + </ul> + </section> + + <section> + <h2>Examples</h2> + <p><strong>Old School RuneScape (OSRS)</strong></p> + <iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe> + <p><strong>World of Warcraft (WoW)</strong></p> + <iframe src="https://www.youtube.com/embed/a5_5kbbmEiM" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe> + </section> + </main> + + <?php include '../../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/what-is-multiboxing/index_zh.php b/gaming/multibox/what-is-multiboxing/index_zh.php new file mode 100644 index 0000000..4d9d18a --- /dev/null +++ b/gaming/multibox/what-is-multiboxing/index_zh.php @@ -0,0 +1,77 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>What Is Multiboxing? — SillyLaird</title> + <meta name="description" content="Detailed multiboxing overview." /> + <meta property="og:title" content="What Is Multiboxing? — SillyLaird" /> + <meta property="og:description" content="Detailed multiboxing overview." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="What Is Multiboxing? — SillyLaird" /> + <meta name="twitter:description" content="Detailed multiboxing overview." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/multibox/what-is-multiboxing/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="title"> + <h1 id="title">What is Multiboxing?</h1> + <p class="muted">A longer explanation (methods, uses, examples).</p> + </section> + + <section> + <h2>Overview</h2> + <p>Multiboxing is the practice of playing multiple characters at the same time in a Massively Multiplayer Online Role-Playing Game (MMORPG). This technique generally requires the use of multiple game accounts and can be achieved using different methods such as employing multiple computers, using specialized software, or even running multiple instances of the same game on a single computer.</p> + <p>Players who multibox often do so to gain advantages such as increased efficiency in resource gathering, leveling up multiple characters simultaneously, or taking on game content that would typically require a group of players.</p> + </section> + + <section> + <h2>Methods</h2> + <ul> + <li><strong>Multiple 电脑设备:</strong> Several physical PCs, each running one account.</li> + <li><strong>Virtual Machines:</strong> Multiple OS instances on one machine.</li> + <li><strong>Software Solutions:</strong> Keystroke broadcasting / window management tools (game ToS varies).</li> + </ul> + </section> + + <section> + <h2>Common Uses</h2> + <ul> + <li><strong>Solo Group Content:</strong> Do group content without other players.</li> + <li><strong>Economy Control:</strong> Resource gathering / crafting on multiple chars.</li> + <li><strong>Power Leveling:</strong> Level alts quickly with a main.</li> + </ul> + </section> + + <section> + <h2>Examples</h2> + <p><strong>Old School RuneScape (OSRS)</strong></p> + <iframe src="https://www.youtube.com/embed/6qGL-7NkpGM" allowfullscreen title="OSRS multiboxing" class="saf481e1471"></iframe> + <p><strong>World of Warcraft (WoW)</strong></p> + <iframe src="https://www.youtube.com/embed/a5_5kbbmEiM" allowfullscreen title="WoW multiboxing" class="saf481e1471"></iframe> + </section> + </main> + + <?php include '../../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/multibox/what-is-multiboxing/styles.css b/gaming/multibox/what-is-multiboxing/styles.css new file mode 100644 index 0000000..95dea86 --- /dev/null +++ b/gaming/multibox/what-is-multiboxing/styles.css @@ -0,0 +1,54 @@ +/* styles.css */
+
+body {
+ font-family: Arial, sans-serif;
+ line-height: 1.6;
+ margin: 0;
+ padding: 0;
+ background-color: #f4f4f4;
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+}
+
+header {
+ background: #333;
+ color: #fff;
+ padding: 10px 0;
+ text-align: center;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+}
+
+nav ul li {
+ display: inline;
+ margin: 0 15px;
+}
+
+nav ul li a {
+ color: #fff;
+ text-decoration: none;
+}
+
+main {
+ padding: 20px;
+ flex: 1;
+ padding-bottom: 60px; /* Add bottom padding to ensure space for footer */
+}
+
+h2 {
+ color: #333;
+}
+
+footer {
+ background: #333;
+ color: #fff;
+ text-align: center;
+ padding: 10px 0;
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+}
\ No newline at end of file diff --git a/gaming/runescape/_lib.php b/gaming/runescape/_lib.php new file mode 100644 index 0000000..c8fbbab --- /dev/null +++ b/gaming/runescape/_lib.php @@ -0,0 +1,182 @@ +<?php +// Shared read-only helpers for the /gaming/runescape/ page. +// Data is edited via /admin.php?section=runescape; this file just renders it. + +function runescape_valid_url_or_path(string $url): bool { + if ($url === '') return false; + if ($url[0] === '/') return !str_starts_with($url, '//') && !str_contains($url, "\0"); + $scheme = strtolower(parse_url($url, PHP_URL_SCHEME) ?? ''); + if (in_array($scheme, ['http', 'https', 'gemini', 'gopher'], true)) return filter_var($url, FILTER_VALIDATE_URL) !== false; + return false; +} + +function runescape_data(?string $path = null): array { + $path = $path ?? (__DIR__ . '/data.json'); + $empty = [ + 'welcome' => [], + 'screenshots' => [], + 'eras' => [], + 'links_section' => ['title' => 'Server Lists', 'disclaimer' => '', 'items' => []], + ]; + if (!is_file($path)) { + return $empty; + } + $raw = file_get_contents($path); + if ($raw === false || trim($raw) === '') { + return $empty; + } + $data = json_decode($raw, true); + if (!is_array($data)) { + return $empty; + } + $welcome = []; + foreach (($data['welcome'] ?? []) as $line) { + $line = trim((string)$line); + if ($line !== '') $welcome[] = $line; + } + $screenshots = []; + foreach (($data['screenshots'] ?? []) as $shot) { + if (!is_array($shot)) continue; + $filename = trim((string)($shot['filename'] ?? '')); + if ($filename === '' || str_contains($filename, '..') || str_contains($filename, '/')) continue; + $screenshots[] = [ + 'filename' => $filename, + 'caption' => (string)($shot['caption'] ?? ''), + ]; + } + $eras = []; + foreach (($data['eras'] ?? []) as $era) { + if (!is_array($era)) continue; + $title = trim((string)($era['title'] ?? '')); + if ($title === '') continue; + $servers = []; + foreach (($era['servers'] ?? []) as $srv) { + if (!is_array($srv)) continue; + $name = trim((string)($srv['name'] ?? '')); + if ($name === '') continue; + $url = trim((string)($srv['url'] ?? '')); + if ($url !== '' && !runescape_valid_url_or_path($url)) $url = ''; + $highlights = []; + foreach (($srv['highlights'] ?? []) as $hl) { + $hl = trim((string)$hl); + if ($hl !== '') $highlights[] = $hl; + } + $links = []; + foreach (($srv['links'] ?? []) as $lk) { + if (!is_array($lk)) continue; + $label = trim((string)($lk['label'] ?? '')); + $lurl = trim((string)($lk['url'] ?? '')); + if ($label === '' || $lurl === '' || !runescape_valid_url_or_path($lurl)) continue; + $links[] = ['label' => $label, 'url' => $lurl]; + } + $srvImage = trim((string)($srv['image'] ?? '')); + if ($srvImage !== '' && str_contains($srvImage, '..')) $srvImage = ''; + $servers[] = [ + 'id' => (string)($srv['id'] ?? ''), + 'name' => $name, + 'url' => $url, + 'featured' => !empty($srv['featured']), + 'desc' => (string)($srv['desc'] ?? ''), + 'highlights' => $highlights, + 'links' => $links, + 'image' => $srvImage, + ]; + } + $eraImage = trim((string)($era['image'] ?? '')); + if ($eraImage !== '' && str_contains($eraImage, '..')) $eraImage = ''; + $eras[] = [ + 'id' => (string)($era['id'] ?? ''), + 'title' => $title, + 'subtitle' => (string)($era['subtitle'] ?? ''), + 'image' => $eraImage, + 'servers' => $servers, + ]; + } + $linksSection = ['title' => 'Server Lists', 'disclaimer' => '', 'items' => []]; + if (is_array($data['links_section'] ?? null)) { + $ls = $data['links_section']; + $linksSection['title'] = trim((string)($ls['title'] ?? '')) ?: 'Server Lists'; + $linksSection['disclaimer'] = (string)($ls['disclaimer'] ?? ''); + foreach (($ls['items'] ?? []) as $item) { + if (!is_array($item)) continue; + $label = trim((string)($item['label'] ?? '')); + $lurl = trim((string)($item['url'] ?? '')); + if ($label === '' || $lurl === '' || !runescape_valid_url_or_path($lurl)) continue; + $linksSection['items'][] = ['label' => $label, 'url' => $lurl, 'desc' => (string)($item['desc'] ?? '')]; + } + } + return ['welcome' => $welcome, 'screenshots' => $screenshots, 'eras' => $eras, 'links_section' => $linksSection]; +} + +function runescape_screenshot_src(string $filename): string { + $filename = trim($filename); + if ($filename === '' || str_contains($filename, '..') || str_contains($filename, '/')) return ''; + return '/gaming/runescape/images/' . rawurlencode($filename); +} + +/** Public URL for an era/server image (uploaded filename, site path, or absolute URL). */ +function runescape_image_src(string $image): string { + $image = trim($image); + if ($image === '') return ''; + if (str_starts_with($image, 'http://') || str_starts_with($image, 'https://') || str_starts_with($image, '/')) { + return $image; + } + if (str_contains($image, '..') || str_contains($image, "\0")) return ''; + return '/gaming/runescape/images/' . rawurlencode(basename($image)); +} + +/** Render the Welcome list — lines like "::Label::" become bold headings, everything else is a bullet. */ +function runescape_render_welcome(array $lines): void { + $he = fn($s) => htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); + $inList = false; + foreach ($lines as $line) { + if (preg_match('/^::(.+)::$/', trim($line), $m)) { + if ($inList) { echo '</ul>'; $inList = false; } + echo '<p class="machine-title machine-title--sub">' . $he(trim($m[1])) . '</p>'; + continue; + } + if (!$inList) { echo '<ul class="contact-list">'; $inList = true; } + echo '<li>' . $he($line) . '</li>'; + } + if ($inList) echo '</ul>'; +} + +/** Render one server card (used inside an era section). */ +function runescape_render_server(array $srv): void { + $he = fn($s) => htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); + $cardClass = $srv['featured'] ? 'machine machine--notes' : 'machine'; + $img = runescape_image_src((string)($srv['image'] ?? '')); + ?> + <div class="<?= $cardClass ?>"> + <div class="<?= $img !== '' ? 'machine-row' : '' ?>"> + <?php if ($img !== ''): ?> + <img class="machine-thumb" src="<?= $he($img) ?>" alt="<?= $he($srv['name']) ?>" loading="lazy" decoding="async"> + <?php endif; ?> + <div class="machine-info<?= $img !== '' ? ' machine-facts' : '' ?>"> + <div class="machine-title"> + <?php if ($srv['url'] !== ''): ?> + <a href="<?= $he($srv['url']) ?>" target="_blank" rel="noopener noreferrer"><?= $he($srv['name']) ?></a> + <?php else: ?> + <?= $he($srv['name']) ?> + <?php endif; ?> + </div> + <?php if ($srv['desc'] !== ''): ?> + <?= nl2br($he($srv['desc'])) ?> + <?php endif; ?> + <?php if ($srv['highlights']): ?> + <ul class="contact-list"> + <?php foreach ($srv['highlights'] as $hl): ?><li><?= $he($hl) ?></li><?php endforeach; ?> + </ul> + <?php endif; ?> + <?php if ($srv['links']): ?> + <p> + <?php foreach ($srv['links'] as $i => $lk): ?> + <?= $i > 0 ? ' · ' : '' ?><a href="<?= $he($lk['url']) ?>" target="_blank" rel="noopener noreferrer"><?= $he($lk['label']) ?></a> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> + </div> + </div> + <?php +} diff --git a/gaming/runescape/data.json b/gaming/runescape/data.json new file mode 100644 index 0000000..3b81b94 --- /dev/null +++ b/gaming/runescape/data.json @@ -0,0 +1,95 @@ +{ + "welcome": [], + "screenshots": [], + "eras": [ + { + "id": "2004-lost-city", + "title": "2004 · Lost City Era", + "subtitle": "Preservation servers recreating RuneScape as it was in 2004.", + "servers": [ + { + "id": "lost-city", + "name": "Lost City", + "url": "https://2004.lostcity.rs/", + "featured": true, + "desc": "Open-source recreation of RuneScape 2 as it launched in May 2004, rebuilt from decompiled client/server code and old cache dumps rather than guesswork. Runs live, incrementally-patched revisions instead of one static snapshot.", + "highlights": [ + "Play straight in the browser, no client install required", + "Progresses through real 2004–2005 content updates over time, at the original pace", + "Active dev team, open GitHub repo, public roadmap" + ], + "links": [ + {"label": "Play", "url": "https://2004.lostcity.rs/"}, + {"label": "Website", "url": "https://lostcity.rs/"} + ] + } + ] + }, + { + "id": "other-era-servers", + "title": "Other Era Servers", + "subtitle": "", + "servers": [ + { + "id": "openrsc", + "name": "OpenRSC", + "url": "https://rsc.vet/", + "featured": false, + "desc": "Preservation of RuneScape Classic, the isometric pre-RS2 client from 2001–2003, before the switch to the 3D engine.", + "highlights": [ + "Original 2D isometric client and UI, not a reskin of a later revision", + "Slower, grindier economy typical of the Classic era", + "Small dedicated community focused on historical accuracy" + ], + "links": [] + }, + { + "id": "2006scape", + "name": "2006Scape", + "url": "https://2006scape.org/", + "featured": false, + "desc": "Targets the RS2 client roughly a year after Lost City's starting point — post-Lost City the quest, pre-Evolution of Combat.", + "highlights": [ + "Wilderness and old-style PvP still intact", + "Content built out toward the mid-2000s quest/skill lineup", + "Fan-maintained, community-driven development" + ], + "links": [] + }, + { + "id": "2009scape", + "name": "2009scape", + "url": "https://2009scape.org/", + "featured": false, + "desc": "Open-source continuation of the old RS2 client around the HD graphics upgrade era, before Evolution of Combat and the Grand Exchange changes that followed.", + "highlights": [ + "HD-era graphics with the old tick-based combat system", + "Fully open source, community forks welcome", + "Long-running project with regular content patches" + ], + "links": [] + }, + { + "id": "darkan", + "name": "Darkan", + "url": "https://darkan.org/", + "featured": false, + "desc": "Solo-developed remake targeting the 2011–2012 client, later than the other entries here and closer to modern OSRS's starting point.", + "highlights": [ + "One-person passion project, built from scratch rather than a leaked source", + "Development notes and progress posted publicly", + "Smaller playerbase, actively maintained" + ], + "links": [] + } + ] + } + ], + "links_section": { + "title": "Server Lists", + "disclaimer": "Unofficial private servers, not affiliated with Jagex Ltd.", + "items": [ + {"label": "Rune-Server", "url": "https://rune-server.org/", "desc": "private server development community"} + ] + } +} diff --git a/gaming/runescape/index.php b/gaming/runescape/index.php new file mode 100644 index 0000000..e8aacfa --- /dev/null +++ b/gaming/runescape/index.php @@ -0,0 +1,139 @@ +<?php +require_once __DIR__ . '/_lib.php'; +$rsData = runescape_data(); +?> +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:title" content="RuneScape — SillyLaird" /> + <meta property="og:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/runescape/" /> + <meta property="og:locale" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="RuneScape — SillyLaird" /> + <meta property="og:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/runescape/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/runescape/index_jp.php" /> + <title>RuneScape — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> + <link rel="stylesheet" href="/assets/css/pages/computers.css" /> +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="rs-title"> + <h1 id="rs-title">RuneScape (OSRS)</h1> + + <nav class="colon-nav" aria-label="RuneScape page sections"> + <strong>::Servers::</strong> + <?php foreach ($rsData['eras'] as $era): ?> + <a href="#era-<?= htmlspecialchars($era['id'], ENT_QUOTES, 'UTF-8') ?>-title"><?= htmlspecialchars($era['title'], ENT_QUOTES, 'UTF-8') ?></a> | + <?php endforeach; ?> + <a href="#servers-links-title">Links</a> + <strong>::Scrapbook::</strong> + <a href="#servers-bank-title">Bank Pics</a> + <strong>::Official::</strong> + <a href="https://oldschool.runescape.wiki/" target="_blank" rel="noopener noreferrer">OSRS Wiki</a> + </nav> + + <div class="machine"> + <div class="machine-row"> + <img class="machine-thumb" src="/assets/img/runescape.png" alt="RuneScape" loading="lazy" decoding="async"> + <div class="machine-facts"> + <div class="machine-info"> + <strong>Page added:</strong> 2026-07-25<br> + <strong>Last revised:</strong> 2026-07-25 + </div> + <?php if ($rsData['welcome']): ?> + <?php runescape_render_welcome($rsData['welcome']); ?> + <?php else: ?> + <div class="machine-title machine-title--sub">Welcome</div> + <ul class="contact-list"> + <li>A small fan page / launch pad — official OSRS plus private servers, grouped by era.</li> + <li>Servers listed below are unofficial preservation projects, not affiliated with Jagex Ltd.</li> + <li>Bookmark <a href="/gaming/runescape/">/gaming/runescape/</a> directly — server hosts change over time.</li> + </ul> + <?php endif; ?> + </div> + </div> + </div> + </section> + + <?php foreach ($rsData['eras'] as $era): ?> + <section aria-labelledby="era-<?= htmlspecialchars($era['id'], ENT_QUOTES, 'UTF-8') ?>-title"> + <h2 id="era-<?= htmlspecialchars($era['id'], ENT_QUOTES, 'UTF-8') ?>-title" class="section-accent-title"><?= htmlspecialchars($era['title'], ENT_QUOTES, 'UTF-8') ?></h2> + <?php if ($era['subtitle'] !== ''): ?><p class="muted"><?= htmlspecialchars($era['subtitle'], ENT_QUOTES, 'UTF-8') ?></p><?php endif; ?> + <?php $eraImgSrc = runescape_image_src($era['image']); ?> + <?php if ($eraImgSrc !== ''): ?> + <img class="rs-era-banner" src="<?= htmlspecialchars($eraImgSrc, ENT_QUOTES, 'UTF-8') ?>" alt="<?= htmlspecialchars($era['title'], ENT_QUOTES, 'UTF-8') ?>" loading="lazy" decoding="async"> + <?php endif; ?> + + <?php foreach ($era['servers'] as $srv): ?> + <?php runescape_render_server($srv); ?> + <?php endforeach; ?> + </section> + <?php endforeach; ?> + + <!-- Screenshots are managed at /admin.php?section=runescape — placeholder-box slots + show until real ones are uploaded there; no manual editing needed. --> + <section aria-labelledby="servers-bank-title"> + <h2 id="servers-bank-title" class="section-accent-title">My Bank / Screenshots</h2> + <?php if ($rsData['screenshots']): ?> + <div class="placeholder-grid"> + <?php foreach ($rsData['screenshots'] as $shot): ?> + <figure class="rs-shot"> + <img src="<?= htmlspecialchars(runescape_screenshot_src($shot['filename']), ENT_QUOTES, 'UTF-8') ?>" + alt="<?= htmlspecialchars($shot['caption'] !== '' ? $shot['caption'] : 'RuneScape screenshot', ENT_QUOTES, 'UTF-8') ?>" + loading="lazy" decoding="async"> + <?php if ($shot['caption'] !== ''): ?> + <figcaption class="muted"><?= htmlspecialchars($shot['caption'], ENT_QUOTES, 'UTF-8') ?></figcaption> + <?php endif; ?> + </figure> + <?php endforeach; ?> + </div> + <?php else: ?> + <p class="muted">Placeholder — swap these for real bank/inventory screenshots later.</p> + <div class="placeholder-grid"> + <div class="placeholder-box">Add screenshot 1</div> + <div class="placeholder-box">Add screenshot 2</div> + <div class="placeholder-box">Add screenshot 3</div> + </div> + <?php endif; ?> + </section> + + <section aria-labelledby="servers-links-title"> + <h2 id="servers-links-title" class="section-accent-title"><?= htmlspecialchars($rsData['links_section']['title'], ENT_QUOTES, 'UTF-8') ?></h2> + <?php if ($rsData['links_section']['items']): ?> + <ul class="contact-list"> + <?php foreach ($rsData['links_section']['items'] as $item): ?> + <li><a href="<?= htmlspecialchars($item['url'], ENT_QUOTES, 'UTF-8') ?>" target="_blank" rel="noopener noreferrer"><?= htmlspecialchars($item['label'], ENT_QUOTES, 'UTF-8') ?></a><?= $item['desc'] !== '' ? ' — ' . htmlspecialchars($item['desc'], ENT_QUOTES, 'UTF-8') : '' ?></li> + <?php endforeach; ?> + </ul> + <?php endif; ?> + <?php if ($rsData['links_section']['disclaimer'] !== ''): ?> + <p class="muted"><?= htmlspecialchars($rsData['links_section']['disclaimer'], ENT_QUOTES, 'UTF-8') ?></p> + <?php endif; ?> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/runescape/index_jp.php b/gaming/runescape/index_jp.php new file mode 100644 index 0000000..629dca9 --- /dev/null +++ b/gaming/runescape/index_jp.php @@ -0,0 +1,66 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:title" content="RuneScape — SillyLaird" /> + <meta property="og:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/runescape/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="RuneScape — SillyLaird" /> + <meta name="twitter:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/runescape/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/runescape/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/runescape/index_jp.php" /> + <meta name="keywords" content="sillylaird, runescape, osrs, gielinor" /> + <title>RuneScape — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="rs-title"> + <h1 id="rs-title">RuneScape (OSRS)</h1> + <p class="muted">A small fan page / launch pad.</p> + + <img + src="https://oldschool.runescape.wiki/images/thumb/Old_School_RuneScape_logo.png/1200px-Old_School_RuneScape_logo.png?d047b" + alt="Old School RuneScape Logo" + loading="lazy" + decoding="async" class="sb83d4c5326" + /> + + <p class="sd1a2ffa0b4"> + <a class="header-button" href="https://oldschool.runescape.wiki/" target="_blank" rel="noopener noreferrer">Visit OSRS Wiki</a> + </p> + </section> + + <section aria-labelledby="guides-title"> + <h2 id="guides-title">Essential Guides</h2> + <ul class="contact-list"> + <li><a href="#">Combat XP Calculator</a></li> + <li><a href="#">Quest Item Database</a></li> + <li><a href="#">Grand Exchange Tracker</a></li> + </ul> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/runescape/index_zh.php b/gaming/runescape/index_zh.php new file mode 100644 index 0000000..a2cf16f --- /dev/null +++ b/gaming/runescape/index_zh.php @@ -0,0 +1,66 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:title" content="RuneScape — SillyLaird" /> + <meta property="og:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/runescape/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="RuneScape — SillyLaird" /> + <meta name="twitter:description" content="RuneScape / OSRS fan page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/runescape/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/runescape/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/runescape/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/runescape/index_jp.php" /> + <meta name="keywords" content="sillylaird, runescape, osrs, gielinor" /> + <title>RuneScape — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="rs-title"> + <h1 id="rs-title">RuneScape (OSRS)</h1> + <p class="muted">A small fan page / launch pad.</p> + + <img + src="https://oldschool.runescape.wiki/images/thumb/Old_School_RuneScape_logo.png/1200px-Old_School_RuneScape_logo.png?d047b" + alt="Old School RuneScape Logo" + loading="lazy" + decoding="async" class="sb83d4c5326" + /> + + <p class="sd1a2ffa0b4"> + <a class="header-button" href="https://oldschool.runescape.wiki/" target="_blank" rel="noopener noreferrer">Visit OSRS Wiki</a> + </p> + </section> + + <section aria-labelledby="guides-title"> + <h2 id="guides-title">Essential Guides</h2> + <ul class="contact-list"> + <li><a href="#">Combat XP Calculator</a></li> + <li><a href="#">Quest Item Database</a></li> + <li><a href="#">Grand Exchange Tracker</a></li> + </ul> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/runescape/runescape.png b/gaming/runescape/runescape.png Binary files differnew file mode 100644 index 0000000..2eb0c44 --- /dev/null +++ b/gaming/runescape/runescape.png diff --git a/gaming/specialforce/SpecialForce_Launcher.exe b/gaming/specialforce/SpecialForce_Launcher.exe Binary files differnew file mode 100644 index 0000000..befd61f --- /dev/null +++ b/gaming/specialforce/SpecialForce_Launcher.exe diff --git a/gaming/specialforce/index.php b/gaming/specialforce/index.php new file mode 100644 index 0000000..804b54d --- /dev/null +++ b/gaming/specialforce/index.php @@ -0,0 +1,57 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:title" content="SpecialForce — SillyLaird" /> + <meta property="og:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/specialforce/" /> + <meta property="og:locale" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="SpecialForce — SillyLaird" /> + <meta property="og:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/specialforce/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/specialforce/index_jp.php" /> + <meta name="keywords" content="sillylaird, special force, soldierfront" /> + <title>SpecialForce — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sf-title"> + <h1 id="sf-title">SoldierFront / SpecialForce</h1> + <p class="muted">Small page/wiki and file drop.</p> + + <p class="sdac4fe6c9b"> + <a class="header-button" href="https://en.wikipedia.org/wiki/Special_Force_(2004_video_game)" target="_blank" rel="noopener noreferrer">Wikipedia</a> + </p> + </section> + + <section aria-labelledby="launchers-title"> + <h2 id="launchers-title">SpecialForce Launcher Files</h2> + <ul class="contact-list"> + <li><a href="SpecialForce_Launcher.exe">SpecialForce Launcher</a></li> + </ul> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/specialforce/index_jp.php b/gaming/specialforce/index_jp.php new file mode 100644 index 0000000..4a021fc --- /dev/null +++ b/gaming/specialforce/index_jp.php @@ -0,0 +1,57 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:title" content="SpecialForce — SillyLaird" /> + <meta property="og:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/specialforce/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="SpecialForce — SillyLaird" /> + <meta name="twitter:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/specialforce/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/specialforce/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/specialforce/index_jp.php" /> + <meta name="keywords" content="sillylaird, special force, soldierfront" /> + <title>SpecialForce — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sf-title"> + <h1 id="sf-title">SoldierFront / SpecialForce</h1> + <p class="muted">Small page/wiki and file drop.</p> + + <p class="sd1a2ffa0b4"> + <a class="header-button" href="https://en.wikipedia.org/wiki/Special_Force_(2004_video_game)" target="_blank" rel="noopener noreferrer">Wikipedia</a> + </p> + </section> + + <section aria-labelledby="launchers-title"> + <h2 id="launchers-title">SpecialForce Launcher Files</h2> + <ul class="contact-list"> + <li><a href="SpecialForce_Launcher.exe">SpecialForce Launcher</a></li> + </ul> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/specialforce/index_zh.php b/gaming/specialforce/index_zh.php new file mode 100644 index 0000000..bf28068 --- /dev/null +++ b/gaming/specialforce/index_zh.php @@ -0,0 +1,57 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <meta name="description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:title" content="SpecialForce — SillyLaird" /> + <meta property="og:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/specialforce/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="SpecialForce — SillyLaird" /> + <meta name="twitter:description" content="SoldierFront / SpecialForce page by SillyLaird." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/specialforce/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/specialforce/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/specialforce/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/specialforce/index_jp.php" /> + <meta name="keywords" content="sillylaird, special force, soldierfront" /> + <title>SpecialForce — SillyLaird</title> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sf-title"> + <h1 id="sf-title">SoldierFront / SpecialForce</h1> + <p class="muted">Small page/wiki and file drop.</p> + + <p class="sd1a2ffa0b4"> + <a class="header-button" href="https://en.wikipedia.org/wiki/Special_Force_(2004_video_game)" target="_blank" rel="noopener noreferrer">Wikipedia</a> + </p> + </section> + + <section aria-labelledby="launchers-title"> + <h2 id="launchers-title">SpecialForce Launcher Files</h2> + <ul class="contact-list"> + <li><a href="SpecialForce_Launcher.exe">SpecialForce Launcher</a></li> + </ul> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/specialforce/style.css b/gaming/specialforce/style.css new file mode 100644 index 0000000..27758e1 --- /dev/null +++ b/gaming/specialforce/style.css @@ -0,0 +1,174 @@ +/* --- RESET & BASICS --------------------------------------------------- */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ font-family: system-ui, Helvetica, Arial, sans-serif;
+ line-height: 1.4;
+ background: #000;
+ color: var(--ink, #8b0000);
+}
+
+body {
+ text-align: left;
+}
+
+/* --- LAYOUT ----------------------------------------------------------- */
+header {
+ padding: 1rem 1.5rem;
+ background: #000;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ border-bottom: 1px solid #2a1010;
+}
+
+main {
+ padding: 1.5rem;
+ margin: 0 1.5rem;
+ max-width: none;
+}
+
+/* --- LINKS ------------------------------------------------------------ */
+a {
+ text-decoration: none;
+ border-radius: 4px;
+ padding: 2px 4px;
+ transition: background .2s, color .2s;
+ color: var(--ink, #8b0000);
+}
+
+a:hover {
+ background: red;
+ color: #000;
+}
+
+a.no-hover-box:hover {
+ background: transparent;
+ color: red;
+}
+
+/* --- SIDEBAR ---------------------------------------------------------- */
+#mobile-sidebar {
+ position: fixed;
+ top: 0;
+ right: 0;
+ width: 250px;
+ max-height: 100vh;
+ overflow-y: auto;
+ background: #000;
+ transform: translateX(100%);
+ transition: transform .3s ease-in-out;
+ padding: 1rem;
+ box-shadow: -4px 0 8px rgba(0, 0, 0, .5);
+ z-index: 9000;
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ border-left: 1px solid #2a1010;
+}
+
+#mobile-sidebar.visible {
+ transform: translateX(0);
+}
+
+#mobile-sidebar::-webkit-scrollbar {
+ display: none;
+}
+
+#menu-toggle {
+ position: fixed;
+ top: 1rem;
+ right: 1rem;
+ z-index: 9100;
+ padding: .5rem 1rem;
+ border: 1px solid #2a1010;
+ background: #000;
+ color: var(--ink, #8b0000);
+ border-radius: 4px;
+ cursor: pointer;
+}
+
+#menu-toggle:hover {
+ background: #2a1010;
+ color: red;
+}
+
+/* --- LOGO ------------------------------------------------------------- */
+.logo {
+ width: 100px;
+ display: block;
+ margin-bottom: 1rem;
+}
+
+/* --- BUTTON ----------------------------------------------------------- */
+.button {
+ background-color: black;
+ color: white;
+ padding: 10px 20px;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 1em;
+ margin: 20px 0;
+ cursor: pointer;
+ border-radius: 8px;
+ transition: background 0.3s, transform 0.3s;
+ border: 1px solid #2a1010;
+}
+
+.button:hover {
+ background-color: red;
+ transform: translateY(-2px);
+}
+
+/* --- FOOTER ----------------------------------------------------------- */
+.footer {
+ background-color: #111;
+ color: #8b0000;
+ padding: 30px 20px;
+ text-align: center;
+ font-size: 0.9em;
+ border-top: 1px solid #2a1010;
+ margin-top: 20px;
+}
+
+.footer a {
+ color: var(--ink, #8b0000);
+ text-decoration: none;
+}
+
+.footer a:hover {
+ text-decoration: underline;
+}
+
+/* --- MEDIA QUERIES --------------------------------------------------- */
+@media (max-width: 768px) {
+ body {
+ flex-direction: column;
+ font-size: 14px;
+ }
+
+ .sidebar {
+ width: 100%;
+ min-height: auto;
+ box-shadow: none;
+ }
+
+ main {
+ width: 100%;
+ }
+
+ h1 {
+ font-size: 2em;
+ }
+
+ .button {
+ font-size: 0.9em;
+ }
+}
\ No newline at end of file diff --git a/gaming/stepmania/index.php b/gaming/stepmania/index.php new file mode 100644 index 0000000..1910b45 --- /dev/null +++ b/gaming/stepmania/index.php @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="en"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>StepMania — SillyLaird</title> + <meta name="description" content="StepMania page and downloads." /> + <meta property="og:title" content="StepMania — SillyLaird" /> + <meta property="og:description" content="StepMania page and downloads." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/stepmania/" /> + <meta property="og:locale" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="StepMania — SillyLaird" /> + <meta name="twitter:description" content="StepMania page and downloads." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/stepmania/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/stepmania/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">Skip to content</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sm-title"> + <h1 id="sm-title">StepMania</h1> + <p class="muted">Clean, fast, and to the point.</p> + </section> + + <section aria-labelledby="packs-title"> + <h2 id="packs-title">Song Packs</h2> + <ul class="contact-list"> + <li>Dance Revolution Mix 2024</li> + <li>Retro Arcade Hits</li> + <li>Anime Beats Edition</li> + </ul> + </section> + + <section aria-labelledby="scores-title"> + <h2 id="scores-title">High Scores</h2> + <div class="s16a8a8b00c"> + <table class="s473e6bbfeb"> + <thead> + <tr> + <th class="sf2e940dbbf">Rank</th> + <th class="sf2e940dbbf">Player</th> + <th class="sf2e940dbbf">Song</th> + <th class="sf2e940dbbf">Score</th> + </tr> + </thead> + <tbody> + <tr> + <td class="s6f279abaab">1</td> + <td class="s6f279abaab">NeoStep</td> + <td class="s6f279abaab">PARANOiA Rebirth</td> + <td class="s6f279abaab">997,450</td> + </tr> + <tr> + <td class="s6f279abaab">2</td> + <td class="s6f279abaab">LainDance</td> + <td class="s6f279abaab">MAX 300</td> + <td class="s6f279abaab">995,210</td> + </tr> + <tr> + <td class="s44cd1236df">3</td> + <td class="s44cd1236df">PadWizard</td> + <td class="s44cd1236df">vanity angel</td> + <td class="s44cd1236df">992,880</td> + </tr> + </tbody> + </table> + </div> + </section> + + <section aria-labelledby="downloads-title"> + <h2 id="downloads-title">Downloads</h2> + <p><a href="https://www.mediafire.com/folder/ncph2tqkddpli/downloads" target="_blank" rel="noopener noreferrer">StepMania 3.9 / 3.95 / misc files</a></p> + </section> + + <section aria-labelledby="contact-title"> + <h2 id="contact-title">Contact</h2> + <p><a href="mailto:m@sillylaird.ca">m@sillylaird.ca</a></p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/stepmania/index_jp.php b/gaming/stepmania/index_jp.php new file mode 100644 index 0000000..1090c0e --- /dev/null +++ b/gaming/stepmania/index_jp.php @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="ja"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>StepMania — SillyLaird</title> + <meta name="description" content="StepMania page and downloads." /> + <meta property="og:title" content="StepMania — SillyLaird" /> + <meta property="og:description" content="StepMania page and downloads." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/stepmania/index_jp.php" /> + <meta property="og:locale" content="ja_JP" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="zh_CN" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="StepMania — SillyLaird" /> + <meta name="twitter:description" content="StepMania page and downloads." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/stepmania/index_jp.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/stepmania/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/stepmania/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">本文へ移動</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sm-title"> + <h1 id="sm-title">StepMania</h1> + <p class="muted">Clean, fast, and to the point.</p> + </section> + + <section aria-labelledby="packs-title"> + <h2 id="packs-title">Song Packs</h2> + <ul class="contact-list"> + <li>Dance Revolution Mix 2024</li> + <li>Retro Arcade Hits</li> + <li>Anime Beats Edition</li> + </ul> + </section> + + <section aria-labelledby="scores-title"> + <h2 id="scores-title">High Scores</h2> + <div class="s16a8a8b00c"> + <table class="s473e6bbfeb"> + <thead> + <tr> + <th class="sf2e940dbbf">Rank</th> + <th class="sf2e940dbbf">Player</th> + <th class="sf2e940dbbf">Song</th> + <th class="sf2e940dbbf">Score</th> + </tr> + </thead> + <tbody> + <tr> + <td class="s6f279abaab">1</td> + <td class="s6f279abaab">NeoStep</td> + <td class="s6f279abaab">PARANOiA Rebirth</td> + <td class="s6f279abaab">997,450</td> + </tr> + <tr> + <td class="s6f279abaab">2</td> + <td class="s6f279abaab">LainDance</td> + <td class="s6f279abaab">MAX 300</td> + <td class="s6f279abaab">995,210</td> + </tr> + <tr> + <td class="s44cd1236df">3</td> + <td class="s44cd1236df">PadWizard</td> + <td class="s44cd1236df">vanity angel</td> + <td class="s44cd1236df">992,880</td> + </tr> + </tbody> + </table> + </div> + </section> + + <section aria-labelledby="downloads-title"> + <h2 id="downloads-title">Downloads</h2> + <p><a href="https://www.mediafire.com/folder/ncph2tqkddpli/downloads" target="_blank" rel="noopener noreferrer">StepMania 3.9 / 3.95 / misc files</a></p> + </section> + + <section aria-labelledby="contact-title"> + <h2 id="contact-title">連絡先</h2> + <p><a href="mailto:m@sillylaird.ca">m@sillylaird.ca</a></p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/stepmania/index_zh.php b/gaming/stepmania/index_zh.php new file mode 100644 index 0000000..916396d --- /dev/null +++ b/gaming/stepmania/index_zh.php @@ -0,0 +1,100 @@ +<!doctype html> +<html lang="zh"> +<head> + <meta charset="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>StepMania — SillyLaird</title> + <meta name="description" content="StepMania page and downloads." /> + <meta property="og:title" content="StepMania — SillyLaird" /> + <meta property="og:description" content="StepMania page and downloads." /> + <meta property="og:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <meta property="og:type" content="website" /> + <meta property="og:url" content="https://www.sillylaird.ca/gaming/stepmania/index_zh.php" /> + <meta property="og:locale" content="zh_CN" /> + <meta property="og:locale:alternate" content="en_US" /> + <meta property="og:locale:alternate" content="ja_JP" /> + <meta name="twitter:card" content="summary_large_image" /> + <meta name="twitter:title" content="StepMania — SillyLaird" /> + <meta name="twitter:description" content="StepMania page and downloads." /> + <meta name="twitter:image" content="https://www.sillylaird.ca/assets/img/lain.png" /> + <link rel="canonical" href="https://www.sillylaird.ca/gaming/stepmania/index_zh.php" /> + <link rel="alternate" hreflang="x-default" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="en" href="https://www.sillylaird.ca/gaming/stepmania/" /> + <link rel="alternate" hreflang="zh" href="https://www.sillylaird.ca/gaming/stepmania/index_zh.php" /> + <link rel="alternate" hreflang="ja" href="https://www.sillylaird.ca/gaming/stepmania/index_jp.php" /> + <link rel="icon" href="https://www.sillylaird.ca/assets/img/lain.png" /> + + <link rel="stylesheet" href="/assets/css/fonts.css" /> + <link rel="stylesheet" href="/assets/css/site.css" /> + <link rel="stylesheet" href="/assets/css/skeleton.css" /> +</head> + +<body> + <a class="skip-link" href="#main">跳至内容</a> + <?php include '../../partials/header.php'; ?> + + <main id="main" class="wrap"> + <section aria-labelledby="sm-title"> + <h1 id="sm-title">StepMania</h1> + <p class="muted">Clean, fast, and to the point.</p> + </section> + + <section aria-labelledby="packs-title"> + <h2 id="packs-title">Song Packs</h2> + <ul class="contact-list"> + <li>Dance Revolution Mix 2024</li> + <li>Retro Arcade Hits</li> + <li>Anime Beats Edition</li> + </ul> + </section> + + <section aria-labelledby="scores-title"> + <h2 id="scores-title">High Scores</h2> + <div class="s16a8a8b00c"> + <table class="s473e6bbfeb"> + <thead> + <tr> + <th class="sf2e940dbbf">Rank</th> + <th class="sf2e940dbbf">Player</th> + <th class="sf2e940dbbf">Song</th> + <th class="sf2e940dbbf">Score</th> + </tr> + </thead> + <tbody> + <tr> + <td class="s6f279abaab">1</td> + <td class="s6f279abaab">NeoStep</td> + <td class="s6f279abaab">PARANOiA Rebirth</td> + <td class="s6f279abaab">997,450</td> + </tr> + <tr> + <td class="s6f279abaab">2</td> + <td class="s6f279abaab">LainDance</td> + <td class="s6f279abaab">MAX 300</td> + <td class="s6f279abaab">995,210</td> + </tr> + <tr> + <td class="s44cd1236df">3</td> + <td class="s44cd1236df">PadWizard</td> + <td class="s44cd1236df">vanity angel</td> + <td class="s44cd1236df">992,880</td> + </tr> + </tbody> + </table> + </div> + </section> + + <section aria-labelledby="downloads-title"> + <h2 id="downloads-title">Downloads</h2> + <p><a href="https://www.mediafire.com/folder/ncph2tqkddpli/downloads" target="_blank" rel="noopener noreferrer">StepMania 3.9 / 3.95 / misc files</a></p> + </section> + + <section aria-labelledby="contact-title"> + <h2 id="contact-title">联系</h2> + <p><a href="mailto:m@sillylaird.ca">m@sillylaird.ca</a></p> + </section> + </main> + + <?php include '../../partials/footer.php'; ?> +</body> +</html> diff --git a/gaming/stepmania/script.js b/gaming/stepmania/script.js new file mode 100644 index 0000000..1deb43c --- /dev/null +++ b/gaming/stepmania/script.js @@ -0,0 +1,46 @@ +document.addEventListener('DOMContentLoaded', () => {
+ // Simple active link when clicking nav
+ const links = Array.from(document.querySelectorAll('nav a[href^="#"]'));
+ links.forEach(a => {
+ a.addEventListener('click', e => {
+ const id = a.getAttribute('href');
+ const target = document.querySelector(id);
+ if (!target) return;
+ e.preventDefault();
+ links.forEach(x => x.classList.remove('is-active'));
+ a.classList.add('is-active');
+ target.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ history.replaceState(null, '', id);
+ });
+ });
+
+ // Minimal demo scoreboard
+ const data = [
+ { rank: 1, player: 'NeoStep', song: 'PARANOiA Rebirth', score: '997,450' },
+ { rank: 2, player: 'LainDance', song: 'MAX 300', score: '995,210' },
+ { rank: 3, player: 'PadWizard', song: 'vanity angel', score: '992,880' },
+ ];
+ const board = document.getElementById('score-board');
+ if (board) {
+ const table = document.createElement('table');
+ table.innerHTML = `
+ <thead><tr>
+ <th>Rank</th><th>Player</th><th>Song</th><th>Score</th>
+ </tr></thead>
+ <tbody>
+ ${data.map(r => `<tr>
+ <td>${r.rank}</td><td>${r.player}</td><td>${r.song}</td><td>${r.score}</td>
+ </tr>`).join('')}
+ </tbody>`;
+ board.replaceChildren(table);
+ }
+
+ // Join button feedback
+ const btn = document.getElementById('join-event');
+ if (btn) {
+ btn.addEventListener('click', () => {
+ btn.disabled = true;
+ btn.textContent = 'You’re in! Check your inbox.';
+ });
+ }
+});
diff --git a/gaming/stepmania/style.css b/gaming/stepmania/style.css new file mode 100644 index 0000000..20bca04 --- /dev/null +++ b/gaming/stepmania/style.css @@ -0,0 +1,139 @@ +/* Base */
+*, *::before, *::after { box-sizing: border-box; }
+
+html, body {
+ margin: 0;
+ padding: 0;
+ background: #ffd; /* light yellow */
+ color: #111;
+ font-family: system-ui, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+}
+
+/* Header */
+header {
+ padding: 16px;
+ background: #fff6c7;
+ border-bottom: 2px solid #e6d27a;
+ text-align: center;
+}
+h1 {
+ margin: 0 0 8px;
+ font-family: "Comic Sans MS","Chalkboard SE","Comic Neue",sans-serif;
+ font-size: 1.6rem;
+}
+
+/* Nav */
+nav ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ display: grid;
+ grid-auto-flow: column;
+ gap: 8px;
+ justify-content: center;
+}
+nav a {
+ display: inline-block;
+ padding: 6px 8px;
+ text-decoration: none;
+ color: #002;
+ border-radius: 4px;
+ transition: background .15s, color .15s;
+}
+nav a:hover, nav a.is-active { + background: red; + color: #000; +} +
+/* Layout */
+main {
+ max-width: 900px;
+ margin: 20px auto;
+ padding: 0 16px;
+}
+section { margin: 24px 0; }
+h2 { margin: 0 0 8px; }
+
+/* Hero image */
+.hero-image {
+ display: block;
+ max-width: 100%;
+ height: auto;
+ border-radius: 8px;
+ border: 2px solid #e6d27a;
+ background: #fffbe3;
+}
+
+/* Lists */
+#song-list { padding-left: 18px; }
+
+/* Scoreboard (minimal) */
+#score-board {
+ margin-top: 8px;
+ border: 2px solid #e6d27a;
+ border-radius: 8px;
+ background: #fffbe3;
+ overflow: hidden;
+}
+#score-board table { width: 100%; border-collapse: collapse; }
+#score-board th, #score-board td { padding: 8px; text-align: left; }
+#score-board thead th { background: #ffe06d; }
+#score-board tbody tr:nth-child(odd) { background: #fff6c7; }
+
+/* Button */
+button {
+ padding: 10px 14px;
+ border: 2px solid #e6d27a;
+ border-radius: 8px;
+ background: #ffd;
+ color: #111;
+ cursor: pointer;
+ transition: background .15s, color .15s;
+}
+button:hover { background: red; color: #fff; }
+
+/* Gallery (simple responsive) */
+.gallery {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.gallery img {
+ width: calc(33.333% - 7px);
+ min-width: 160px;
+ flex: 1 1 auto;
+ border: 2px solid #e6d27a;
+ border-radius: 8px;
+ background: #fffbe3;
+}
+
+/* Form */
+form {
+ display: grid;
+ gap: 8px;
+ max-width: 600px;
+}
+input[type="text"], input[type="email"], textarea {
+ width: 100%;
+ padding: 10px;
+ border: 2px solid #e6d27a;
+ border-radius: 8px;
+ background: #fffef0;
+ font: inherit;
+ color: #111;
+}
+textarea { min-height: 120px; resize: vertical; }
+
+/* Footer */
+footer {
+ text-align: center;
+ color: #444;
+ margin: 32px 0 24px;
+}
+
+/* Small screens */
+@media (max-width: 640px) {
+ nav ul { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .gallery img { width: calc(50% - 5px); }
+}
|
