土地系统是农场模块的基础组件,为玩家提供种植作物的场所。不同类型的土地具有不同的属性和产出效果,玩家可以通过升级土地来提高产量和解锁更多种植选择。
enum LAND_TYPE: int {
case NORMAL = 1; // 普通土地
case RED = 2; // 红土地
case BLACK = 3; // 黑土地
case GOLD = 4; // 金色特殊土地
case BLUE = 5; // 蓝色特殊土地
case PURPLE = 6; // 紫色特殊土地
}
| 土地类型 | 产量加成 | 灾害抵抗 | 解锁条件 | 升级材料 |
|---|---|---|---|---|
| 普通土地 | 0% | 0% | 默认 | - |
| 红土地 | +10% | +5% | 任意等级 | 木材x10 |
| 黑土地 | +25% | +10% | 任意等级 | 石材x10 |
| 金色特殊土地 | +50% | +15% | 房屋7级+ | 钢材x10+钻石x5 |
| 蓝色特殊土地 | +40% | +25% | 房屋7级+ | 钢材x10+钻石x5 |
| 紫色特殊土地 | +60% | +10% | 房屋7级+ | 钢材x10+钻石x5 |
enum LAND_STATUS: int {
case EMPTY = 0; // 空闲
case PLANTED = 1; // 种植中
case DISASTER = 2; // 灾害
case HARVESTABLE = 3; // 可收获
case WITHERED = 4; // 枯萎
}
新用户注册时自动获得6块普通土地,位置编号为1-6。
土地位置使用1-20的编号,预留未来扩展空间。前端可根据位置编号进行布局展示。
特殊土地(金/蓝/紫)的数量受房屋等级限制:
土地升级遵循固定路径:
普通土地 → 红土地 → 黑土地 → 特殊土地(金/蓝/紫选一)
注:升级材料配置存储在 farm_land_upgrade_configs 表中,可通过后台配置修改。详细设计请参考 土地配置表设计 文档。
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键ID |
| user_id | bigint | 用户ID |
| position | tinyint | 土地位置(1-20) |
| land_type | tinyint | 土地类型 |
| status | tinyint | 土地状态 |
| created_at | timestamp | 创建时间 |
| updated_at | timestamp | 更新时间 |
| 字段名 | 类型 | 说明 |
|---|---|---|
| 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 | 更新时间 |
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键ID |
| from_type_id | tinyint | 起始土地类型ID |
| to_type_id | tinyint | 目标土地类型ID |
| materials | json | 升级所需材料 |
| conditions | json | 其他升级条件 |
| created_at | timestamp | 创建时间 |
| updated_at | timestamp | 更新时间 |
iduser_id, position(确保每个用户的土地位置唯一)user_id(加速查询用户的所有土地)status(加速查询特定状态的土地)/**
* 为用户创建新土地
*
* @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
/**
* 升级土地
*
* @param int $landId 土地ID
* @param int $targetType 目标土地类型
* @return bool 升级是否成功
* @throws InsufficientMaterialsException 材料不足异常
* @throws InvalidUpgradePathException 无效的升级路径异常
* @throws HouseLevelTooLowException 房屋等级过低异常
*/
public function upgradeLand(int $landId, int $targetType): bool
/**
* 获取用户的所有土地
*
* @param int $userId 用户ID
* @return Collection 土地集合
*/
public function getUserLands(int $userId): Collection
/**
* 获取土地详细信息,包括当前种植的作物
*
* @param int $landId 土地ID
* @return array 土地详情
*/
public function getLandDetail(int $landId): array
/**
* 更新土地状态
*
* @param int $landId 土地ID
* @param int $status 新状态
* @return bool 更新是否成功
*/
public function updateLandStatus(int $landId, int $status): bool
/**
* 计算土地的产出加成
*
* @param FarmLand $land 土地对象
* @return float 产出加成系数
*/
public function calculateOutputBonus(FarmLand $land): float
/**
* 计算土地的灾害抵抗值
*
* @param FarmLand $land 土地对象
* @return float 灾害抵抗系数
*/
public function calculateDisasterResistance(FarmLand $land): float
/**
* 验证用户是否可以拥有更多特殊土地
*
* @param int $userId 用户ID
* @param int $landType 目标土地类型
* @return bool 是否可以拥有
*/
public function canHaveMoreSpecialLand(int $userId, int $landType): bool
/**
* 获取升级所需材料
*
* @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 [];
}
前端应展示土地的以下信息:
前端应提供以下土地操作:
土地升级时需要消耗对应的材料物品:
/**
* 升级土地
*/
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;
});
}
处理土地灾害时需要消耗对应的工具物品:
/**
* 处理土地灾害
*/
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;
});
}
系统设计预留了添加新土地类型的可能性,只需:
未来可以为土地添加特殊效果,如:
未来可以添加土地装饰系统,允许玩家装饰土地周围,提供视觉效果和额外属性加成。