--- /dev/null
+<?php
+
+namespace App\Console\Commands;
+
+use App\Beat\Encoder;
+use App\Models\AosSeed;
+use HeadlessChromium\BrowserFactory;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
+
+class GenerateAosSeed extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'aos:generate {id}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Generate AoS seed';
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $seed = AosSeed::findOrFail($this->argument('id'));
+ $seed->status = 'generating';
+ $seed->error_detail = null;
+ $seed->save();
+
+ $stage = 'initial';
+ try {
+ $temp_dir = sys_get_temp_dir();
+
+ $params = array_merge(['seed' => $seed->seed], $seed->settings);
+ $url = config('aos.surge_url').'/?'.http_build_query($params, '', '&');
+
+ $fac = new BrowserFactory('chromium');
+ $browser = $fac->createBrowser();
+
+ $stage = 'loading page';
+ $page = $browser->createPage();
+ $page->setDownloadPath($temp_dir);
+ $page->navigate($url)->waitForNavigation();
+
+ $stage = 'selecting rom';
+ $fileInput = $page->dom()->querySelector('input[type=file]');
+ $fileInput->sendFile(config('aos.base_rom'));
+ $page->waitUntilContainsElement('select');
+
+ $stage = 'clicking randomize';
+ $page->mouse()->find('button', 2)->click();
+ $page->waitUntilContainsElement('a[download]');
+
+ $stage = 'clicking download';
+ $page->dom()->querySelector('a[download]')->setAttributeValue('download', $seed->hash.'.gba');
+ $page->mouse()->find('a[download]')->click();
+
+ $stage = 'waiting for rom';
+ $romFile = $temp_dir.'/'.$seed->hash.'.gba';
+ for ($i = 0; $i < 100; ++$i) {
+ clearstatcache();
+ if (is_file($romFile) && filesize($romFile) >= 8388608) {
+ break;
+ }
+ usleep(100_000);
+ }
+
+ $stage = 'calculating patch';
+ $encoder = new Encoder(file_get_contents(config('aos.base_rom')));
+ $patch = $encoder->createPatch(file_get_contents($romFile));
+ Storage::disk('aos-seeds')->put($seed->hash.'.bps', $patch);
+ unlink($romFile);
+
+ $stage = 'done';
+ $seed->status = 'generated';
+ $seed->save();
+
+ $browser->close();
+ } catch (\Throwable $e) {
+ $seed->status = 'error';
+ $seed->error_detail = [
+ 'stage' => $stage,
+ 'type' => get_class($e),
+ 'message' => $e->getMessage(),
+ ];
+ $seed->save();
+ return 1;
+ }
+
+ return 0;
+ }
+}
use App\Models\AosSeed;
use Discord\Builders\MessageBuilder;
use Discord\Discord;
-use Discord\Parts\Embed\Embed;
-use Discord\Parts\Embed\Field;
-use Discord\Parts\Embed\Footer;
use Discord\Parts\Interactions\Interaction;
class AosrPresetCommand {
$presetName = $interaction->data->options['preset']->options['preset']->value;
$race = isset($interaction->data->options['preset']->options['race'])
? $interaction->data->options['preset']->options['race']->value : false;
- $message = MessageBuilder::new();
if (isset(static::$presets[$presetName])) {
$preset = static::$presets[$presetName];
$seed = AosSeed::generateSurge($presetName, $preset['settings'], $race);
- $embed = new Embed($discord, [
- 'fields' => [
- new Field($discord, [ 'name' => 'Generator', 'value' => 'This seed has been generated with fusecv\'s randomizer on aosrando.surge.sh.' ]),
- new Field($discord, [ 'name' => 'Preset', 'value' => $preset['name'], 'inline' => true ]),
- new Field($discord, [ 'name' => 'Seed', 'value' => $race ? 'secret' : $seed->seed, 'inline' => true ]),
- new Field($discord, [ 'name' => 'Logic', 'value' => $preset['settings']['logic'], 'inline' => true ]),
- new Field($discord, [ 'name' => 'Area', 'value' => $preset['settings']['area'], 'inline' => true ]),
- new Field($discord, [ 'name' => 'Boss', 'value' => $preset['settings']['boss'], 'inline' => true ]),
- new Field($discord, [ 'name' => 'Enemy', 'value' => $preset['settings']['enemy'], 'inline' => true ]),
- new Field($discord, [ 'name' => 'Permalink', 'value' => $seed->permalink ]),
- ],
- 'footer' => new Footer($discord, [
- 'text' => 'Grün',
- ]),
- 'timestamp' => now(),
- 'title' => 'AoSRando Seed',
- 'type' => 'rich',
- 'url' => $seed->permalink,
- ]);
- $message->addEmbed($embed);
+ $process = $seed->createProcess();
+ $process->on('exit', function() use ($discord, $interaction, $seed) {
+ $seed = $seed->fresh();
+
+ $embed = $seed->createEmbed($discord);
+ $message = MessageBuilder::new();
+ $message->addEmbed($embed);
+
+ $interaction->updateOriginalResponse($message);
+ });
+
+ $process->start($discord->getLoop());
} else {
+ $message = MessageBuilder::new();
$message->setContent('unknown preset '.$presetName);
+ $interaction->updateOriginalResponse($message);
}
- $interaction->updateOriginalResponse($message);
});
return true;
});
}
- private static $presets = [
+ public static $presets = [
'Normal' => [
'name' => 'Normal',
'value' => 'Normal',
namespace App\Http\Controllers;
-use App\Jobs\GenerateAosSeed;
use App\Models\AosSeed;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Artisan;
class AosSeedController extends Controller
{
if ($seed->status == 'error') {
$seed->status = 'pending';
$seed->save();
- GenerateAosSeed::dispatch($seed)->onConnection('database');
+ Artisan::call('aos:generate '.intval($seed->id));
}
return $seed->toJson();
+++ /dev/null
-<?php
-
-namespace App\Jobs;
-
-use App\Beat\Encoder;
-use App\Models\AosSeed;
-use HeadlessChromium\BrowserFactory;
-use Illuminate\Bus\Queueable;
-use Illuminate\Contracts\Queue\ShouldBeUnique;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Foundation\Bus\Dispatchable;
-use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Support\Facades\Storage;
-
-class GenerateAosSeed implements ShouldQueue
-{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
-
- /**
- * Create a new job instance.
- *
- * @return void
- */
- public function __construct(AosSeed $seed)
- {
- $this->seed = $seed;
- }
-
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- $stage = 'initial';
- try {
- $temp_dir = sys_get_temp_dir();
-
- $seed = $this->seed;
- $params = array_merge(['seed' => $seed->seed], $seed->settings);
- $url = config('aos.surge_url').'/?'.http_build_query($params, '', '&');
-
- $fac = new BrowserFactory('chromium');
- $browser = $fac->createBrowser();
-
- $stage = 'loading page';
- $page = $browser->createPage();
- $page->setDownloadPath($temp_dir);
- $page->navigate($url)->waitForNavigation();
-
- $stage = 'selecting rom';
- $fileInput = $page->dom()->querySelector('input[type=file]');
- $fileInput->sendFile(config('aos.base_rom'));
- $page->waitUntilContainsElement('select');
-
- $stage = 'clicking randomize';
- $page->mouse()->find('button', 2)->click();
- $page->waitUntilContainsElement('a[download]');
-
- $stage = 'clicking download';
- $page->dom()->querySelector('a[download]')->setAttributeValue('download', $seed->hash.'.gba');
- $page->mouse()->find('a[download]')->click();
-
- $stage = 'waiting for rom';
- $romFile = $temp_dir.'/'.$seed->hash.'.gba';
- for ($i = 0; $i < 100; ++$i) {
- clearstatcache();
- if (is_file($romFile) && filesize($romFile) >= 8388608) {
- break;
- }
- usleep(100_000);
- }
-
- $stage = 'calculating patch';
- $encoder = new Encoder(file_get_contents(config('aos.base_rom')));
- $patch = $encoder->createPatch(file_get_contents($romFile));
- Storage::disk('aos-seeds')->put($seed->hash.'.bps', $patch);
- unlink($romFile);
-
- $stage = 'done';
- $seed->status = 'generated';
- $seed->save();
-
- $browser->close();
- } catch (\Throwable $e) {
- $seed->status = 'error';
- $seed->error_detail = [
- 'stage' => $stage,
- 'type' => get_class($e),
- 'message' => $e->getMessage(),
- ];
- $seed->save();
- }
- }
-
- protected $seed;
-
-}
namespace App\Models;
-use App\Jobs\GenerateAosSeed;
+use App\DiscordAppCommands\AosrPresetCommand;
+use Discord\Discord;
+use Discord\Parts\Embed\Embed;
+use Discord\Parts\Embed\Field;
+use Discord\Parts\Embed\Footer;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
+use React\ChildProcess\Process;
class AosSeed extends Model
{
$seed->settings = $settings;
$seed->status = 'pending';
$seed->save();
- GenerateAosSeed::dispatch($seed)->onConnection('database');
return $seed;
}
+ public function createProcess() {
+ return new Process('php artisan aos:generate '.intval($this->id), base_path());
+ }
+
+ public function createEmbed(Discord $discord) {
+ $preset = AosrPresetCommand::$presets[$this->preset];
+
+ $fields = [
+ new Field($discord, [ 'name' => 'Generator', 'value' => 'This seed has been generated with fusecv\'s randomizer on aosrando.surge.sh.' ]),
+ new Field($discord, [ 'name' => 'Preset', 'value' => $preset['name'], 'inline' => true ]),
+ ];
+
+ if (!$this->race) {
+ $fields[] = new Field($discord, [ 'name' => 'Seed', 'value' => $this->seed, 'inline' => true ]);
+ }
+
+ if (!$this->mystery) {
+ $fields[] = new Field($discord, [ 'name' => 'Logic', 'value' => $this->settings['logic'], 'inline' => true ]);
+ $fields[] = new Field($discord, [ 'name' => 'Area', 'value' => $this->settings['area'], 'inline' => true ]);
+ $fields[] = new Field($discord, [ 'name' => 'Boss', 'value' => $this->settings['boss'], 'inline' => true ]);
+ $fields[] = new Field($discord, [ 'name' => 'Enemy', 'value' => $this->settings['enemy'], 'inline' => true ]);
+ }
+
+ $fields[] = new Field($discord, [ 'name' => 'Permalink', 'value' => $this->permalink ]);
+
+ return new Embed($discord, [
+ 'fields' => $fields,
+ 'footer' => new Footer($discord, [
+ 'text' => 'Grün',
+ ]),
+ 'timestamp' => now(),
+ 'title' => 'AoSRando Seed',
+ 'type' => 'rich',
+ 'url' => $this->permalink,
+ ]);
+ }
+
public function getPermalinkAttribute() {
return config('aos.url').'/h/'.rawurlencode($this->hash);
}