土地系统.md 13 KB

土地系统设计文档

1. 系统概述

土地系统是农场模块的基础组件,为玩家提供种植作物的场所。不同类型的土地具有不同的属性和产出效果,玩家可以通过升级土地来提高产量和解锁更多种植选择。

2. 土地类型

2.1 类型定义

enum LAND_TYPE: int {
    case NORMAL = 1;     // 普通土地
    case RED = 2;        // 红土地
    case BLACK = 3;      // 黑土地
    case GOLD = 4;       // 金色特殊土地
    case BLUE = 5;       // 蓝色特殊土地
    case PURPLE = 6;     // 紫色特殊土地
}

2.2 类型属性

土地类型 产量加成 灾害抵抗 解锁条件 升级材料
普通土地 0% 0% 默认 -
红土地 +10% +5% 任意等级 木材x10
黑土地 +25% +10% 任意等级 石材x10
金色特殊土地 +50% +15% 房屋7级+ 钢材x10+钻石x5
蓝色特殊土地 +40% +25% 房屋7级+ 钢材x10+钻石x5
紫色特殊土地 +60% +10% 房屋7级+ 钢材x10+钻石x5

3. 土地状态

3.1 状态定义

enum LAND_STATUS: int {
    case EMPTY = 0;      // 空闲
    case PLANTED = 1;    // 种植中
    case DISASTER = 2;   // 灾害
    case HARVESTABLE = 3; // 可收获
    case WITHERED = 4;   // 枯萎
}

3.2 状态转换

  • 空闲 → 种植中:玩家种植作物
  • 种植中 → 灾害:随机触发灾害
  • 灾害 → 种植中:玩家处理灾害
  • 种植中 → 可收获:作物成熟
  • 可收获 → 枯萎:超过收获期
  • 枯萎 → 空闲:玩家铲除枯萎作物
  • 可收获 → 空闲:玩家收获作物

4. 土地数量与位置

4.1 初始土地

新用户注册时自动获得6块普通土地,位置编号为1-6。

4.2 土地位置

土地位置使用1-20的编号,预留未来扩展空间。前端可根据位置编号进行布局展示。

4.3 特殊土地限制

特殊土地(金/蓝/紫)的数量受房屋等级限制:

  • 7级房屋:可拥有2块特殊土地
  • 8级房屋:可拥有4块特殊土地
  • 9级房屋:可拥有6块特殊土地
  • 以此类推

5. 土地升级

5.1 升级路径

土地升级遵循固定路径:

普通土地 → 红土地 → 黑土地 → 特殊土地(金/蓝/紫选一)

5.2 升级条件

  1. 土地必须处于空闲状态
  2. 用户必须拥有足够的升级材料
  3. 特殊土地升级还需满足房屋等级要求
  4. 特殊土地数量不超过当前房屋等级允许的上限

5.3 升级材料消耗

  • 普通→红土地:木材x10
  • 红→黑土地:石材x10
  • 黑→特殊土地(金/蓝/紫):钢材x10+钻石x5

注:升级材料配置存储在 farm_land_upgrade_configs 表中,可通过后台配置修改。详细设计请参考 土地配置表设计 文档。

6. 数据结构

6.1 土地表 (farm_land_users)

字段名 类型 说明
id bigint 主键ID
user_id bigint 用户ID
position tinyint 土地位置(1-20)
land_type tinyint 土地类型
status tinyint 土地状态
created_at timestamp 创建时间
updated_at timestamp 更新时间

6.2 土地类型配置表 (farm_land_types)

字段名 类型 说明
id tinyint 土地类型ID
name varchar 土地类型名称
code varchar 土地类型编码
output_bonus decimal 产量加成
disaster_resistance decimal 灾害抵抗
unlock_house_level tinyint 解锁所需房屋等级
is_special tinyint 是否为特殊土地
icon varchar 图标路径
description text 描述
created_at timestamp 创建时间
updated_at timestamp 更新时间

6.3 土地升级配置表 (farm_land_upgrade_configs)

字段名 类型 说明
id int 主键ID
from_type_id tinyint 起始土地类型ID
to_type_id tinyint 目标土地类型ID
materials json 升级所需材料
conditions json 其他升级条件
created_at timestamp 创建时间
updated_at timestamp 更新时间

6.4 索引设计

  • 主键索引:id
  • 复合索引:user_id, position(确保每个用户的土地位置唯一)
  • 普通索引:user_id(加速查询用户的所有土地)
  • 普通索引:status(加速查询特定状态的土地)

7. 核心功能

7.1 创建土地

/**
 * 为用户创建新土地
 *
 * @param int $userId 用户ID
 * @param int $position 土地位置
 * @param int $landType 土地类型
 * @return FarmLand 创建的土地对象
 */
public function createLand(int $userId, int $position, int $landType = LAND_TYPE::NORMAL): FarmLand

7.2 升级土地

/**
 * 升级土地
 *
 * @param int $landId 土地ID
 * @param int $targetType 目标土地类型
 * @return bool 升级是否成功
 * @throws InsufficientMaterialsException 材料不足异常
 * @throws InvalidUpgradePathException 无效的升级路径异常
 * @throws HouseLevelTooLowException 房屋等级过低异常
 */
public function upgradeLand(int $landId, int $targetType): bool

7.3 获取用户土地

/**
 * 获取用户的所有土地
 *
 * @param int $userId 用户ID
 * @return Collection 土地集合
 */
public function getUserLands(int $userId): Collection

7.4 获取土地详情

/**
 * 获取土地详细信息,包括当前种植的作物
 *
 * @param int $landId 土地ID
 * @return array 土地详情
 */
public function getLandDetail(int $landId): array

7.5 更新土地状态

/**
 * 更新土地状态
 *
 * @param int $landId 土地ID
 * @param int $status 新状态
 * @return bool 更新是否成功
 */
public function updateLandStatus(int $landId, int $status): bool

8. 业务逻辑

8.1 土地产出加成计算

/**
 * 计算土地的产出加成
 *
 * @param FarmLand $land 土地对象
 * @return float 产出加成系数
 */
public function calculateOutputBonus(FarmLand $land): float

8.2 土地灾害抵抗计算

/**
 * 计算土地的灾害抵抗值
 *
 * @param FarmLand $land 土地对象
 * @return float 灾害抵抗系数
 */
public function calculateDisasterResistance(FarmLand $land): float

8.3 特殊土地数量验证

/**
 * 验证用户是否可以拥有更多特殊土地
 *
 * @param int $userId 用户ID
 * @param int $landType 目标土地类型
 * @return bool 是否可以拥有
 */
public function canHaveMoreSpecialLand(int $userId, int $landType): bool

8.4 获取升级所需材料

/**
 * 获取升级所需材料
 *
 * @param int $currentType 当前土地类型
 * @param int $targetType 目标土地类型
 * @return array 升级所需材料
 */
public function getUpgradeMaterials(int $currentType, int $targetType): array
{
    // 普通→红土地:木材x10
    if ($currentType == LAND_TYPE::NORMAL && $targetType == LAND_TYPE::RED) {
        return [
            ['item_id' => 1001, 'amount' => 10]  // 木材x10
        ];
    }

    // 红→黑土地:石材x10
    if ($currentType == LAND_TYPE::RED && $targetType == LAND_TYPE::BLACK) {
        return [
            ['item_id' => 1002, 'amount' => 10]  // 石材x10
        ];
    }

    // 黑→特殊土地(金/蓝/紫):钢材x10+钻石x5
    if ($currentType == LAND_TYPE::BLACK &&
        in_array($targetType, [LAND_TYPE::GOLD, LAND_TYPE::BLUE, LAND_TYPE::PURPLE])) {
        return [
            ['item_id' => 1003, 'amount' => 10],  // 钢材x10
            ['item_id' => 1004, 'amount' => 5]    // 钻石x5
        ];
    }

    return [];
}

9. 前端交互

9.1 土地展示

前端应展示土地的以下信息:

  • 土地类型(通过不同的视觉效果区分)
  • 土地状态(空闲/种植中/灾害/可收获/枯萎)
  • 当前种植的作物(如果有)
  • 作物生长进度
  • 灾害情况(如果有)

9.2 土地操作

前端应提供以下土地操作:

  • 种植:选择种子种植在空闲土地上
  • 收获:收获成熟的作物
  • 铲除:铲除枯萎的作物
  • 升级:升级土地类型
  • 处理灾害:使用道具处理土地灾害

10. 与其他系统的交互

10.1 与作物系统的交互

  • 土地状态影响作物的种植和生长
  • 土地类型影响作物的最终产量
  • 土地的灾害抵抗影响灾害发生概率

10.2 与房屋系统的交互

  • 房屋等级限制特殊土地的数量
  • 房屋等级影响土地的整体产出

10.3 与物品系统的交互

10.3.1 基本交互

  • 升级土地消耗物品系统中的材料
  • 处理灾害消耗物品系统中的道具

10.3.2 土地升级示例

土地升级时需要消耗对应的材料物品:

/**
 * 升级土地
 */
public function upgradeLand(int $landId, int $targetType): bool
{
    return DB::transaction(function () use ($landId, $targetType) {
        // 获取土地信息
        $land = $this->landRepository->find($landId);
        $userId = $land->user_id;
        $currentType = $land->land_type;

        // 验证升级路径
        if (!$this->isValidUpgradePath($currentType, $targetType)) {
            throw new InvalidUpgradePathException("无效的升级路径");
        }

        // 验证土地状态
        if ($land->status != LAND_STATUS::EMPTY) {
            throw new LandException("土地必须处于空闲状态");
        }

        // 验证房屋等级(对于特殊土地)
        if ($this->isSpecialLandType($targetType)) {
            $houseLevel = $this->farmUserRepository->findByUserId($userId)->house_level;
            if ($houseLevel < 7) {
                throw new HouseLevelTooLowException("房屋等级不足,无法升级到特殊土地");
            }

            // 验证特殊土地数量限制
            if (!$this->canHaveMoreSpecialLand($userId, $targetType)) {
                throw new LandException("已达到特殊土地上限");
            }
        }

        // 获取升级所需材料
        $materials = $this->getUpgradeMaterials($currentType, $targetType);

        // 检查用户是否拥有足够的材料
        foreach ($materials as $material) {
            $hasItem = $this->itemService->checkUserItem(
                $userId,
                $material['item_id'],
                $material['amount']
            );
            if (!$hasItem) {
                throw new InsufficientMaterialsException("材料不足");
            }
        }

        // 消耗材料
        foreach ($materials as $material) {
            $this->itemService->consumeUserItem(
                $userId,
                $material['item_id'],
                $material['amount'],
                "升级土地"
            );
        }

        // 更新土地类型
        $this->landRepository->update($landId, [
            'land_type' => $targetType
        ]);

        // 触发土地升级事件
        event(new LandUpgradedEvent($userId, $landId, $currentType, $targetType));

        return true;
    });
}

10.3.3 处理灾害示例

处理土地灾害时需要消耗对应的工具物品:

/**
 * 处理土地灾害
 */
public function handleLandDisaster(int $landId, int $disasterType, int $toolId): bool
{
    return DB::transaction(function () use ($landId, $disasterType, $toolId) {
        // 获取土地和作物信息
        $land = $this->landRepository->find($landId);
        $userId = $land->user_id;
        $crop = $this->cropRepository->findByLandId($landId);

        // 验证灾害存在
        if (!$this->hasDisaster($crop, $disasterType)) {
            throw new DisasterNotFoundException("该土地没有指定的灾害");
        }

        // 验证工具类型与灾害类型匹配
        if (!$this->isToolMatchDisaster($toolId, $disasterType)) {
            throw new InvalidToolException("该工具不能处理此类灾害");
        }

        // 检查用户是否拥有该工具物品
        $hasItem = $this->itemService->checkUserItem($userId, $toolId, 1);
        if (!$hasItem) {
            throw new InsufficientToolException("用户没有足够的工具");
        }

        // 消耗工具物品
        $this->itemService->consumeUserItem($userId, $toolId, 1, "处理土地灾害");

        // 移除灾害
        $this->removeDisaster($crop, $disasterType);

        // 更新土地状态
        if (count($crop->disasters) == 0) {
            $this->landRepository->update($landId, [
                'status' => LAND_STATUS::PLANTED
            ]);
        }

        return true;
    });
}

11. 扩展性考虑

11.1 新土地类型

系统设计预留了添加新土地类型的可能性,只需:

  1. 在LAND_TYPE枚举中添加新类型
  2. 在配置中添加新类型的属性
  3. 更新前端展示逻辑

11.2 土地特殊效果

未来可以为土地添加特殊效果,如:

  • 季节加成:特定季节产量提升
  • 作物亲和:对特定作物有额外加成
  • 特殊资源:有几率产出额外资源

11.3 土地装饰

未来可以添加土地装饰系统,允许玩家装饰土地周围,提供视觉效果和额外属性加成。