124 lines
4.0 KiB
PHP
124 lines
4.0 KiB
PHP
<?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 投放者用户ID(null=系统自动)
|
||
*/
|
||
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));
|
||
}
|
||
}
|