|
|
6 mesiacov pred | |
|---|---|---|
| .. | ||
| AdminControllers | 6 mesiacov pred | |
| AdminForms | 7 mesiacov pred | |
| Casts | 7 mesiacov pred | |
| Commands | 7 mesiacov pred | |
| Config | 7 mesiacov pred | |
| Console | 7 mesiacov pred | |
| Databases | 6 mesiacov pred | |
| Docs | 6 mesiacov pred | |
| Dtos | 7 mesiacov pred | |
| Enums | 7 mesiacov pred | |
| Events | 6 mesiacov pred | |
| Examples | 7 mesiacov pred | |
| Exceptions | 7 mesiacov pred | |
| Jobs | 6 mesiacov pred | |
| Listeners | 7 mesiacov pred | |
| Logics | 6 mesiacov pred | |
| Models | 6 mesiacov pred | |
| Providers | 7 mesiacov pred | |
| Queues | 7 mesiacov pred | |
| Repositories | 7 mesiacov pred | |
| Repositorys | 6 mesiacov pred | |
| Services | 6 mesiacov pred | |
| Tests | 6 mesiacov pred | |
| Validation | 7 mesiacov pred | |
| Validations | 7 mesiacov pred | |
| Validators | 7 mesiacov pred | |
| DEV.md | 7 mesiacov pred | |
| README.md | 6 mesiacov pred | |
游戏物品系统 - 综合管理游戏内所有物品的生命周期
GameItems模块是游戏核心系统之一,负责管理游戏内所有物品的完整生命周期,包括创建、获取、使用、交易、过期和销毁。该模块为游戏内经济系统和玩家进度提供基础支持,是连接多个游戏子系统的核心组件。
app/Module/GameItems/
├── AdminControllers/ # 后台管理控制器
│ ├── Helper/ # 控制器辅助类
│ ├── Actions/ # 控制器动作类
│ └── LazyRenderable/ # 懒加载渲染类
├── Commands/ # 命令行工具
├── Casts/ # 自定义类型转换器
├── Databases/ # 数据库相关文件
│ └── create.sql # 数据库创建脚本
├── Enums/ # 枚举类型定义
├── Events/ # 事件类
├── Exceptions/ # 异常类
├── Logics/ # 业务逻辑类
├── Models/ # 数据模型
├── Providers/ # 服务提供者
├── Repositorys/ # 数据仓库
├── Services/ # 服务类
└── README.md # 模块文档
GameItems模块采用分层架构设计,遵循"服务是对外的,Logic是内部的"原则:
Services
├── ItemService - 物品基础服务
├── ChestService - 宝箱服务
├── CraftService - 合成服务
└── DismantleService - 分解服务
Logics
├── Item - 物品逻辑
├── PityTime - 保底计数逻辑
├── ItemInstance - 物品实例逻辑
├── UserRecipe - 用户配方逻辑
├── Recipe - 配方逻辑
├── UserOutputCounter - 用户产出计数逻辑
└── Group - 物品组逻辑
Models
├── Item - 物品基础信息
├── ItemCategory - 物品分类
├── ItemInstance - 物品实例(单独属性物品)
├── ItemUser - 用户物品关联
├── ItemGroup - 物品组
├── ItemGroupItem - 物品组内容
├── ItemChestConfig - 宝箱配置(新系统)
├── ItemPityTime - 宝箱保底计数
├── ItemChestOpenLog - 宝箱开启记录
├── ItemRecipe - 物品合成配方
├── ItemRecipeMaterial - 合成配方材料
├── ItemUserRecipe - 用户配方解锁状态
├── ItemCraftLog - 物品合成记录
├── ItemDismantleRule - 物品分解规则
├── ItemDismantleLog - 物品分解记录
├── ItemOutputLimit - 物品产出限制
├── ItemUserOutputCounter - 用户产出计数
└── ItemTransactionLog - 物品交易记录
| 表名 | 主要功能 | 关键字段 |
|---|---|---|
| item_items | 统一属性物品定义 | id, name, type, is_unique, attributes |
| item_categories | 物品分类管理 | id, name, code, parent_id |
| item_instances | 单独属性物品实例 | id, item_id, attributes, is_bound |
| item_users | 用户物品关联 | user_id, item_id, instance_id, quantity |
| item_groups | 物品组定义 | id, name, code |
| item_group_items | 物品组内容 | group_id, item_id, weight |
| item_chest_configs | 宝箱配置(新系统) | item_id, consume_group_id, reward_group_id, condition_group_id |
| item_pity_times | 用户宝箱保底计数 | user_id, chest_id, chest_content_id, current_count |
| item_chest_open_logs | 宝箱开启记录 | user_id, chest_id, result_items, pity_triggered |
| item_recipes | 合成配方定义 | id, result_item_id, success_rate |
| item_recipe_materials | 配方材料需求 | recipe_id, item_id, quantity |
| item_user_recipes | 用户配方解锁状态 | user_id, recipe_id, is_unlocked |
| item_craft_logs | 物品合成记录 | user_id, recipe_id, is_success |
| item_dismantle_rules | 物品分解规则 | item_id/category_id, priority |
| item_dismantle_logs | 物品分解记录 | user_id, item_id, results |
| item_output_limits | 物品产出限制 | item_id, limit_type, max_quantity |
| item_user_output_counters | 用户产出计数 | user_id, limit_id, current_count |
| item_transaction_logs | 物品交易记录 | user_id, item_id, quantity, transaction_type |
物品类型决定了物品的基本行为和使用方式:
物品属性以JSON格式存储,分为两类:
记录物品流转的类型:
// 添加统一属性物品
$result = $itemService->addItem($userId, $itemId, $quantity, [
'source_type' => 'quest_reward',
'source_id' => $questId,
]);
// 添加单独属性物品
$result = $itemService->addItem($userId, $itemId, 1, [
'source_type' => 'chest_open',
'source_id' => $chestId,
'display_attributes' => ['color' => 'red', 'size' => 'large'],
'numeric_attributes' => ['attack' => 100, 'defense' => 50],
]);
// 消耗统一属性物品
$result = $itemService->consumeItem($userId, $itemId, null, $quantity, [
'source_type' => 'item_use',
'details' => ['effect_id' => 123],
]);
// 消耗单独属性物品
$result = $itemService->consumeItem($userId, $itemId, $instanceId, 1, [
'source_type' => 'equipment_upgrade',
'details' => ['upgrade_id' => 456],
]);
// 获取所有物品
$items = $itemService->getUserItems($userId);
// 获取特定类型的物品
$items = $itemService->getUserItems($userId, [
'type' => 2, // 装备类物品
'category_id' => 5, // 特定分类
]);
// 开启宝箱
$result = $chestService->openChest($userId, $chestId, $quantity, [
'ip_address' => $request->ip(),
'device_info' => $request->userAgent(),
]);
// 结果示例
[
'success' => true,
'chest_id' => 123,
'quantity' => 1,
'results' => [
[
[
'item_id' => 456,
'quantity' => 2,
'is_pity' => false,
],
[
'item_id' => 789,
'quantity' => 1,
'is_pity' => true,
]
]
],
'pity_triggered' => true,
'log_id' => 10001,
]
// 获取宝箱内容预览
$preview = $chestService->getChestContentPreview($chestId);
// 合成物品
$result = $craftService->craftItem($userId, $recipeId, [
'ip_address' => $request->ip(),
'device_info' => $request->userAgent(),
]);
// 获取用户可合成配方列表
$recipes = $craftService->getUserAvailableRecipes($userId);
// 分解物品
$result = $dismantleService->dismantleItem($userId, $itemId, $instanceId, $quantity, [
'ip_address' => $request->ip(),
'device_info' => $request->userAgent(),
]);
// 获取物品分解预览
$preview = $dismantleService->getDismantlePreview($userId, $itemId, $instanceId);
物品基础服务,负责物品的基本操作。
/**
* 获取用户物品列表
*
* @param int $userId 用户ID
* @param array $filters 过滤条件
* @param bool $includeExpired 是否包含已过期物品
* @return Collection
*/
public function getUserItems(int $userId, array $filters = [], bool $includeExpired = false): Collection;
/**
* 添加物品到用户背包
*
* @param int $userId 用户ID
* @param int $itemId 物品ID
* @param int $quantity 数量
* @param array $options 选项
* @return array 添加结果
*/
public function addItem(int $userId, int $itemId, int $quantity, array $options = []): array;
/**
* 消耗用户物品
*
* @param int $userId 用户ID
* @param int $itemId 物品ID
* @param int|null $instanceId 物品实例ID(单独属性物品)
* @param int $quantity 数量
* @param array $options 选项
* @return array 消耗结果
*/
public function consumeItem(int $userId, int $itemId, ?int $instanceId, int $quantity, array $options = []): array;
/**
* 检查用户物品数量
*
* @param int $userId 用户ID
* @param int $itemId 物品ID
* @param int|null $instanceId 物品实例ID(单独属性物品)
* @return int 物品数量
*/
public function getItemQuantity(int $userId, int $itemId, ?int $instanceId = null): int;
/**
* 检查物品是否过期
*
* @param int $itemId 物品ID
* @param int|null $instanceId 物品实例ID
* @return bool 是否过期
*/
public function isItemExpired(int $itemId, ?int $instanceId = null): bool;
宝箱服务,负责宝箱开启和内容管理。
/**
* 开启宝箱
*
* @param int $userId 用户ID
* @param int $chestId 宝箱ID
* @param int $quantity 开启数量
* @param array $options 选项
* @return array 开启结果
*/
public function openChest(int $userId, int $chestId, int $quantity = 1, array $options = []): array;
/**
* 获取宝箱内容预览
*
* @param int $chestId 宝箱ID
* @return array 宝箱内容预览
*/
public function getChestContentPreview(int $chestId): array;
合成服务,负责物品合成和配方管理。
/**
* 合成物品
*
* @param int $userId 用户ID
* @param int $recipeId 配方ID
* @param array $options 选项
* @return array 合成结果
*/
public function craftItem(int $userId, int $recipeId, array $options = []): array;
/**
* 获取用户可合成配方列表
*
* @param int $userId 用户ID
* @param array $filters 过滤条件
* @return Collection 配方列表
*/
public function getUserAvailableRecipes(int $userId, array $filters = []): Collection;
/**
* 解锁用户配方
*
* @param int $userId 用户ID
* @param int $recipeId 配方ID
* @return bool 是否成功
*/
public function unlockRecipe(int $userId, int $recipeId): bool;
分解服务,负责物品分解和规则管理。
/**
* 分解物品
*
* @param int $userId 用户ID
* @param int $itemId 物品ID
* @param int|null $instanceId 物品实例ID
* @param int $quantity 数量
* @param array $options 选项
* @return array 分解结果
*/
public function dismantleItem(int $userId, int $itemId, ?int $instanceId, int $quantity, array $options = []): array;
/**
* 获取物品分解预览
*
* @param int $userId 用户ID
* @param int $itemId 物品ID
* @param int|null $instanceId 物品实例ID
* @return array 分解预览
*/
public function getDismantlePreview(int $userId, int $itemId, ?int $instanceId): array;
物品基础信息模型,定义物品的基本属性。
/**
* 物品基础信息
*
* field start
* @property int $id 物品ID,主键
* @property string $name 物品名称
* @property string $description 物品描述
* @property int $category_id 物品分类ID,外键关联kku_item_categories表
* @property int $type 物品类型(1:可使用, 2:可装备, 3:可合成, 4:可交任务, 5:可开启...)
* @property int $is_unique 是否是单独属性物品(0:否,默认, 1:是)
* @property int $max_stack 最大堆叠数量
* @property int $sell_price 出售价格
* @property int $tradable 是否可交易(0:不可交易, 1:可交易,默认)
* @property int $dismantlable 是否可分解(0:不可分解, 1:可分解,默认)
* @property int $default_expire_seconds 玩家获取物品后的默认有效秒数(0表示永久有效)
* @property object|array $display_attributes 展示属性,以JSON格式存储键值对,用于界面展示和描述的属性
* @property object|array $numeric_attributes 数值属性,以JSON格式存储键值对,用于计算和游戏逻辑的属性
* @property string $global_expire_at 物品全局过期时间(可为空)
* @property \Carbon\Carbon $created_at 创建时间
* @property \Carbon\Carbon $updated_at 更新时间
* field end
*/
class Item extends ModelCore
{
// 模型实现...
}
宝箱配置模型(新系统),使用消耗组/奖励组/条件组来定义宝箱的开启消耗和产出。
/**
* 宝箱配置(新系统)
*
* field start
* @property int $id 记录ID,主键
* @property int $item_id 宝箱物品ID,外键关联kku_item_items表
* @property int $consume_group_id 消耗组ID,外键关联kku_game_consume_groups表(可为空)
* @property int $reward_group_id 奖励组ID,外键关联kku_game_reward_groups表
* @property int $condition_group_id 条件组ID,外键关联kku_game_condition_groups表(可为空)
* @property bool $is_active 是否激活(0:否, 1:是)
* @property \Carbon\Carbon $created_at 创建时间
* @property \Carbon\Carbon $updated_at 更新时间
* field end
*/
class ItemChestConfig extends ModelCore
{
// 模型实现...
}
用户物品关联模型,记录用户拥有的物品。
/**
* 用户物品关联
*
* field start
* @property int $id 记录ID,主键
* @property int $user_id 用户ID
* @property int $item_id 统一属性物品ID,外键关联kku_item_items表
* @property int $instance_id 单独属性物品ID,外键关联kku_item_instances表(可为空)
* @property int $quantity 数量(对于单独属性物品,该值始终为1)
* @property string $expire_at 用户物品过期时间(可为空)
* @property \Carbon\Carbon $created_at 获取时间
* @property \Carbon\Carbon $updated_at 更新时间
* field end
*/
class ItemUser extends ModelCore
{
// 模型实现...
}
模型之间的关系定义如下:
Logics层包含所有业务逻辑处理类,负责具体的业务规则实现。这些类不直接对外提供服务,而是由Services层调用。
物品逻辑类,处理物品相关的业务逻辑。
/**
* 物品逻辑类
*/
class Item
{
/**
* 判断物品是否为宝箱
*
* @param ItemModel $item 物品模型
* @return bool
*/
public function isChest(ItemModel $item): bool;
/**
* 检查物品是否已过期(全局过期)
*
* @param ItemModel $item 物品模型
* @return bool
*/
public function isExpired(ItemModel $item): bool;
}
保底计数逻辑类,处理宝箱保底机制相关的业务逻辑。
/**
* 宝箱保底计数逻辑类
*/
class PityTime
{
/**
* 增加保底计数
*
* @param ItemPityTime $pityTime 保底计数模型
* @param int $count 增加的数量,默认为1
* @return bool
*/
public function incrementCount(ItemPityTime $pityTime, int $count = 1): bool;
/**
* 重置保底计数
*
* @param ItemPityTime $pityTime 保底计数模型
* @return bool
*/
public function resetCount(ItemPityTime $pityTime): bool;
}
// 在任务完成后添加奖励物品
public function completeQuest(int $userId, int $questId)
{
// 获取任务信息
$quest = $this->questRepository->find($questId);
// 验证任务是否可完成
if (!$this->questService->canComplete($userId, $questId)) {
throw new QuestCannotCompleteException("任务无法完成");
}
// 开始事务
DB::beginTransaction();
try {
// 标记任务完成
$this->questService->markAsCompleted($userId, $questId);
// 添加奖励物品
foreach ($quest->rewards as $reward) {
$this->itemService->addItem(
$userId,
$reward['item_id'],
$reward['quantity'],
[
'source_type' => 'quest_reward',
'source_id' => $questId,
'details' => ['quest_name' => $quest->name],
]
);
}
DB::commit();
return ['success' => true, 'message' => '任务完成,奖励已发放'];
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
// 在控制器中实现宝箱开启功能
public function openChest(Request $request, int $chestId)
{
// 验证请求
$validated = $request->validate([
'quantity' => 'required|integer|min:1|max:10',
]);
try {
// 获取当前用户ID
$userId = Auth::id();
// 开启宝箱
$result = $this->chestService->openChest(
$userId,
$chestId,
$validated['quantity'],
[
'ip_address' => $request->ip(),
'device_info' => $request->userAgent(),
]
);
return response()->json([
'success' => true,
'data' => $result,
]);
} catch (Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 400);
}
}
// 在控制器中实现物品合成功能
public function craftItem(Request $request, int $recipeId)
{
try {
// 获取当前用户ID
$userId = Auth::id();
// 合成物品
$result = $this->craftService->craftItem(
$userId,
$recipeId,
[
'ip_address' => $request->ip(),
'device_info' => $request->userAgent(),
]
);
return response()->json([
'success' => true,
'data' => $result,
]);
} catch (Exception $e) {
return response()->json([
'success' => false,
'message' => $e->getMessage(),
], 400);
}
}
Enums/ITEM_TYPE.php 中添加新的类型常量Models/Item.php 中添加相关的关联方法(如果需要)Logics/Item.php 中添加处理新类型的逻辑方法Services/ItemService.php 中添加对外提供的服务方法Models/ItemChestContent.php 中添加新的字段(如果需要)Logics/ChestContent.php 中添加新机制的逻辑方法Services/ChestService.php 中修改 openChest 方法以支持新机制