Styling fixes and Olden Era mmodule
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Services\TwitchHelix;
|
||||
use App\Support\OldenEra;
|
||||
use App\Support\RigData;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -18,13 +19,19 @@ use Throwable;
|
||||
*/
|
||||
class OnboardController extends Controller
|
||||
{
|
||||
public function show(RigData $rig, TwitchHelix $twitch)
|
||||
public function show(RigData $rig, TwitchHelix $twitch, OldenEra $olden)
|
||||
{
|
||||
return view('onboard', [
|
||||
'manifest' => $rig->loading(),
|
||||
'telemetry' => $rig->telemetry(),
|
||||
'trackCount' => $rig->playlistCount(),
|
||||
'twitchEnabled' => $twitch->enabled(),
|
||||
'oldenEra' => [
|
||||
'gameId' => OldenEra::GAME_ID,
|
||||
'assetBase' => OldenEra::URL,
|
||||
'catalog' => $olden->catalog(),
|
||||
'manifest' => $olden->manifest(),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -47,7 +54,7 @@ class OnboardController extends Controller
|
||||
return response()->json(['matches' => $hits]);
|
||||
}
|
||||
|
||||
public function submit(Request $request, RigData $rig, TwitchHelix $twitch): JsonResponse
|
||||
public function submit(Request $request, RigData $rig, TwitchHelix $twitch, OldenEra $olden): JsonResponse
|
||||
{
|
||||
$data = $request->validate([
|
||||
'game' => 'required|string|max:200',
|
||||
@@ -76,6 +83,28 @@ class OnboardController extends Controller
|
||||
json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n"
|
||||
);
|
||||
|
||||
$oldenPath = null;
|
||||
if (($manifest['gameId'] ?? null) === OldenEra::GAME_ID) {
|
||||
$factions = array_keys($olden->catalog());
|
||||
$extra = $request->validate([
|
||||
'olden.color' => 'required|in:red,blue',
|
||||
'olden.my.faction' => 'required|string|in:' . implode(',', $factions),
|
||||
'olden.my.hero' => 'required|string|max:120',
|
||||
'olden.enemy.faction' => 'required|string|in:' . implode(',', $factions),
|
||||
'olden.enemy.hero' => 'required|string|max:120',
|
||||
'olden.map' => 'nullable|string|max:200',
|
||||
])['olden'];
|
||||
|
||||
$oldenPath = $olden->writeManifest([
|
||||
'compiledAt' => gmdate('Y-m-d\TH:i:s\Z'),
|
||||
'gameId' => OldenEra::GAME_ID,
|
||||
'color' => $extra['color'],
|
||||
'my' => $extra['my'],
|
||||
'enemy' => $extra['enemy'],
|
||||
'map' => isset($extra['map']) && $extra['map'] !== '' ? $extra['map'] : null,
|
||||
]);
|
||||
}
|
||||
|
||||
$twitchStatus = null;
|
||||
if (!empty($data['pushTwitch']) && $twitch->enabled() && !empty($manifest['gameId'])) {
|
||||
try {
|
||||
@@ -88,10 +117,11 @@ class OnboardController extends Controller
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'ok' => true,
|
||||
'manifest' => $manifest,
|
||||
'twitch' => $twitchStatus,
|
||||
'path' => str_replace(base_path() . '/', '', $path),
|
||||
'ok' => true,
|
||||
'manifest' => $manifest,
|
||||
'twitch' => $twitchStatus,
|
||||
'path' => str_replace(base_path() . '/', '', $path),
|
||||
'oldenPath' => $oldenPath ? str_replace(base_path() . '/', '', $oldenPath) : null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,22 @@
|
||||
namespace App\Http\Controllers\Overlays;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Support\OldenEra;
|
||||
use App\Support\RigData;
|
||||
|
||||
class GameController extends Controller
|
||||
{
|
||||
public function show(RigData $rig)
|
||||
public function show(RigData $rig, OldenEra $olden)
|
||||
{
|
||||
$manifest = $rig->loading();
|
||||
$isOlden = ($manifest['gameId'] ?? null) === OldenEra::GAME_ID;
|
||||
$oldenManifest = $isOlden ? $olden->manifest() : [];
|
||||
|
||||
return view('overlays.game', [
|
||||
'manifest' => $rig->loading(),
|
||||
'manifest' => $manifest,
|
||||
'olden' => !empty($oldenManifest) ? $oldenManifest : null,
|
||||
'oldenAssetBase' => OldenEra::URL,
|
||||
'rigName' => (string) (config('rig.streamer_nick') ?: 'OPHI118'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,9 @@ use RuntimeException;
|
||||
* Thin Twitch Helix client. Replaces twitch-bot/search-game.py + set-channel.py
|
||||
* for use from `php artisan rig:loading`.
|
||||
*
|
||||
* Requires TWITCH_CLIENT_ID + TWITCH_TOKEN (user OAuth token with the
|
||||
* Requires TWITCH_CLIENT_ID + TWITCH_ACCESS_TOKEN (user OAuth token with the
|
||||
* channel:manage:broadcast scope) and TWITCH_BROADCASTER_ID in .env.
|
||||
* Legacy TWITCH_TOKEN is still accepted as a fallback (see config/rig.php).
|
||||
*/
|
||||
class TwitchHelix
|
||||
{
|
||||
|
||||
78
webapp/app/Support/OldenEra.php
Normal file
78
webapp/app/Support/OldenEra.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
/**
|
||||
* Per-game extra manifest for Heroes of Might & Magic: Olden Era.
|
||||
*
|
||||
* `loading.json` keeps the generic stream metadata (game, subtitle, mic…).
|
||||
* Olden Era specifics — matchup factions, heroes, the player's team color,
|
||||
* map name — live in their own `olden-era-manifest.json` so the loading
|
||||
* schema doesn't grow a new key every time a game gets bespoke chrome.
|
||||
*/
|
||||
class OldenEra
|
||||
{
|
||||
/** Twitch Helix category id for "Heroes of Might & Magic: Olden Era". */
|
||||
public const GAME_ID = '1426873999';
|
||||
|
||||
/** Public URL prefix; resolved via the webapp/public/games symlink. */
|
||||
public const URL = '/games/olden-era';
|
||||
|
||||
private ?array $catalogCache = null;
|
||||
|
||||
/**
|
||||
* Faction → {logo URL, heroes list}. Built by globbing
|
||||
* resources/games/olden-era/{factions,heroes/<Faction>}/*.png.
|
||||
*/
|
||||
public function catalog(): array
|
||||
{
|
||||
if ($this->catalogCache !== null) return $this->catalogCache;
|
||||
|
||||
$root = resource_path('games/olden-era');
|
||||
$out = [];
|
||||
|
||||
foreach (glob($root . '/factions/*.png') ?: [] as $factionPng) {
|
||||
$faction = pathinfo($factionPng, PATHINFO_FILENAME);
|
||||
$heroes = [];
|
||||
foreach (glob($root . '/heroes/' . $faction . '/*.png') ?: [] as $heroPng) {
|
||||
$name = pathinfo($heroPng, PATHINFO_FILENAME);
|
||||
$heroes[] = [
|
||||
'name' => $name,
|
||||
'portrait' => self::URL . '/heroes/' . rawurlencode($faction) . '/' . rawurlencode($name) . '.png',
|
||||
];
|
||||
}
|
||||
usort($heroes, fn($a, $b) => strcasecmp($a['name'], $b['name']));
|
||||
$out[$faction] = [
|
||||
'logo' => self::URL . '/factions/' . rawurlencode($faction) . '.png',
|
||||
'heroes' => $heroes,
|
||||
];
|
||||
}
|
||||
|
||||
ksort($out);
|
||||
return $this->catalogCache = $out;
|
||||
}
|
||||
|
||||
public function manifest(): array
|
||||
{
|
||||
$path = $this->manifestPath();
|
||||
if (!is_file($path)) return [];
|
||||
$parsed = json_decode((string) @file_get_contents($path), true);
|
||||
return is_array($parsed) ? $parsed : [];
|
||||
}
|
||||
|
||||
public function writeManifest(array $data): string
|
||||
{
|
||||
$path = $this->manifestPath();
|
||||
@mkdir(dirname($path), 0775, true);
|
||||
file_put_contents(
|
||||
$path,
|
||||
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "\n"
|
||||
);
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function manifestPath(): string
|
||||
{
|
||||
return rtrim(config('rig.storage_data'), '/') . '/olden-era-manifest.json';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user