Files
chatroom/app/Jobs/DropMysteryBoxJob.php

124 lines
4.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:投放神秘箱子队列任务
*
* 由调度器或管理员手动触发,执行以下操作:
* 1. 创建神秘箱记录(含暗号、类型、奖励范围)
* 2. 公屏广播暗号提示(全服可见)
* 3. 设定定时关闭任务windows_seconds 秒后过期)
*
* @author ChatRoom Laravel
*
* @version 1.0.0
*/
namespace App\Jobs;
use App\Events\MessageSent;
use App\Models\GameConfig;
use App\Models\MysteryBox;
use App\Services\ChatStateService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Str;
class DropMysteryBoxJob implements ShouldQueue
{
use Queueable;
/**
* 最大重试次数。
*/
public int $tries = 1;
/**
* @param string $boxType 箱子类型normal | rare | trap
* @param int|null $roomId 投放目标房间null 时默认 1
* @param string|null $passcode 手动指定暗号null=自动生成)
* @param int|null $droppedBy 投放者用户IDnull=系统自动)
*/
public function __construct(
public readonly string $boxType = 'normal',
public readonly ?int $roomId = 1,
public readonly ?string $passcode = null,
public readonly ?int $droppedBy = null,
) {}
/**
* 执行投放逻辑。
*/
public function handle(ChatStateService $chatState): void
{
// 检查游戏是否开启
if (! GameConfig::isEnabled('mystery_box')) {
return;
}
$config = GameConfig::forGame('mystery_box')?->params ?? [];
$claimWindow = (int) ($config['claim_window_seconds'] ?? 120);
$targetRoom = $this->roomId ?? 1;
// 自动生成随机暗号(若未指定)
$passcode = $this->passcode ?? strtoupper(Str::random(6));
// 根据类型确定奖励范围
[$rewardMin, $rewardMax] = match ($this->boxType) {
'rare' => [
(int) ($config['rare_reward_min'] ?? 5000),
(int) ($config['rare_reward_max'] ?? 20000),
],
'trap' => [
(int) ($config['trap_penalty_min'] ?? 200),
(int) ($config['trap_penalty_max'] ?? 1000),
],
default => [
(int) ($config['normal_reward_min'] ?? 500),
(int) ($config['normal_reward_max'] ?? 2000),
],
};
// 创建箱子记录
$box = MysteryBox::create([
'box_type' => $this->boxType,
'passcode' => $passcode,
'reward_min' => $rewardMin,
'reward_max' => $rewardMax,
'status' => 'open',
'expires_at' => now()->addSeconds($claimWindow),
'dropped_by' => $this->droppedBy,
]);
// 公屏广播暗号提示
$emoji = $box->typeEmoji();
$typeName = $box->typeName();
$source = $this->droppedBy ? '管理员' : '系统';
$content = "{$emoji}{$typeName}{$source}投放了一个神秘箱子!"
."发送暗号「{$passcode}」即可开箱!限时 {$claimWindow} 秒,先到先得!";
$msg = [
'id' => $chatState->nextMessageId($targetRoom),
'room_id' => $targetRoom,
'from_user' => '系统传音',
'to_user' => '大家',
'content' => $content,
'is_secret' => false,
'font_color' => match ($this->boxType) {
'rare' => '#c4b5fd',
'trap' => '#f87171',
default => '#34d399',
},
'action' => '大声宣告',
'sent_at' => now()->toDateTimeString(),
];
$chatState->pushMessage($targetRoom, $msg);
broadcast(new MessageSent($targetRoom, $msg));
SaveMessageJob::dispatch($msg);
// 定时关闭任务:到期后将箱子标记为 expired
ExpireMysteryBoxJob::dispatch($box->id)->delay(now()->addSeconds($claimWindow + 5));
}
}