375 lines
13 KiB
PHP
375 lines
13 KiB
PHP
<?php
|
||
/**
|
||
* Created by PhpStorm.
|
||
* User: zn
|
||
* Date: 2017/7/31
|
||
* Time: 16:23
|
||
*/
|
||
|
||
namespace common\utils;
|
||
|
||
use common\models\Item;
|
||
use common\models\User;
|
||
use common\modules\achievement\AchievementUtil;
|
||
use common\modules\dailytask\DailyTaskUtil;
|
||
use common\modules\safe\SafeUtil;
|
||
use common\modules\systemlog\SystemLog;
|
||
use common\modules\systemlog\SystemLogUtil;
|
||
use common\services\GameConfigServices;
|
||
use common\services\ItemServices;
|
||
use common\services\ResultStatusServices;
|
||
use common\services\StatusException;
|
||
|
||
class MoneyUtil
|
||
{
|
||
const REMOVED_BOX_ITEM_TYPE = 400;
|
||
const REMOVED_BOX_ITEM_IDS = [
|
||
201012,
|
||
201013,
|
||
201014,
|
||
201015,
|
||
201016,
|
||
];
|
||
|
||
/**
|
||
* 修改仓库物品
|
||
* @param int $pUserID
|
||
* @param int $pItemType
|
||
* @param bool $pIsAdd
|
||
* @param int $pNum
|
||
* @param SystemLog $logoVo
|
||
* @throws StatusException
|
||
*/
|
||
public static function checkAndModifyNumByItemType($pUserID, $pItemType, $pIsAdd, $pNum, SystemLog $logoVo)
|
||
{
|
||
$itemID = GameConfigServices::getItemIDByType2($pItemType);
|
||
if (empty($itemID)) throw new StatusException(ResultStatusServices::RS_ITEM_TYPE_ERROR);
|
||
|
||
self::checkAndModifyNum($pUserID, $itemID, $pIsAdd, $pNum, $logoVo);
|
||
}
|
||
|
||
/**
|
||
* 修改仓库物品
|
||
* @param int $userID
|
||
* @param int $itemID
|
||
* @param bool $isAdd
|
||
* @param int $num
|
||
* @param SystemLog $logoVo
|
||
* @return Item
|
||
* @throws StatusException
|
||
*/
|
||
public static function checkAndModifyNum($userID, $itemID, $isAdd, $num, SystemLog $logoVo)
|
||
{
|
||
//正负验证
|
||
if ($isAdd && $num < 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
if (!$isAdd && $num > 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
|
||
return SafeUtil::redisLockOperate(function ($tUserID, $tItemID, $tIsAdd, $tNum, SystemLog $logoVo) {
|
||
//获取信息
|
||
$itemDbData = Item::findByUserIDAndItemID($tUserID, $tItemID);
|
||
|
||
$config = GameConfigServices::getParamByPath('item_list.' . $tItemID);
|
||
|
||
if (empty($config)) throw new StatusException(ResultStatusServices::RS_NOT_FIND_IN_CONFIG);
|
||
|
||
if (!$tIsAdd && empty($itemDbData)) throw new StatusException(ResultStatusServices::RS_ITEM_NOT_ENOUGH);
|
||
|
||
//添加操作,并且数据不存在则新建数据
|
||
if (empty($itemDbData)) {
|
||
$itemDbData = new Item();
|
||
$itemDbData->user_id = $tUserID;
|
||
$itemDbData->item_id = $tItemID;
|
||
$itemDbData->num = 0;
|
||
$itemDbData->name = $config['name'];
|
||
$itemDbData->type = $config['type2'];
|
||
}
|
||
|
||
//修改数量
|
||
$itemDbData->num += $tNum;
|
||
|
||
//数量不够减
|
||
if ($itemDbData->num < 0) throw new StatusException(ResultStatusServices::RS_ITEM_NOT_ENOUGH);
|
||
|
||
//判断能否买多个
|
||
$onlyBuyOne = in_array($itemDbData->type, ItemServices::ITEM_ONLY_BUY_ONE_LIST);
|
||
if ($onlyBuyOne && $itemDbData->num > 1) throw new StatusException(ResultStatusServices::RS_ITEM_CAN_NOT_BY_MORE);
|
||
|
||
//减少操作,如果数量为0,则删除数据
|
||
if (!$tIsAdd && !$itemDbData->getIsNewRecord() && $itemDbData->num <= 0) {
|
||
if (!$itemDbData->delete()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); //删除操作
|
||
} elseif (!$itemDbData->save())
|
||
throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR); //保存操作
|
||
|
||
if (!$logoVo->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR);
|
||
if ($config['type2'] == ItemServices::ITEM_TYPE2_STONE && $tNum > 0) AchievementUtil::addCount($tUserID, AchievementUtil::ID_ACCUMULATION_STONE, $tNum);
|
||
|
||
return $itemDbData;
|
||
|
||
}, [$userID, $itemID, $isAdd, $num, $logoVo], RedisKeyUtil::lockItem($userID, $itemID));
|
||
}
|
||
|
||
/**
|
||
* 判断并修改更改金钱
|
||
* isAdd 是否为添加操作
|
||
* @param int $userID
|
||
* @param bool $isAdd
|
||
* @param int $gold
|
||
* @param SystemLog $logoVo
|
||
* @throws StatusException
|
||
*/
|
||
public static function checkAndModifyRes($userID, $isAdd, $num, $type, SystemLog $logoVo)
|
||
{
|
||
//正负验证
|
||
if ($isAdd && $num < 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
if (!$isAdd && $num > 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
|
||
SafeUtil::redisLockOperate(function ($userID, $num, $type, SystemLog $logoVo) {
|
||
|
||
//获取用户信息
|
||
$userDbData = User::findById($userID);
|
||
if (!$userDbData) throw new StatusException(ResultStatusServices::RS_NOT_FIND_IN_DB);
|
||
|
||
//修改资源
|
||
if ($type == ItemServices::ITEM_TYPE2_GOLD) {
|
||
$userDbData->gold += $num;
|
||
if ($userDbData->gold < 0) throw new StatusException(ResultStatusServices::RS_GOLD_NOT_ENOUGH);
|
||
if (!$userDbData->save(true, ['gold', 'updated_at'])) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR);
|
||
}
|
||
if ($type == ItemServices::ITEM_TYPE2_GEM) {
|
||
$userDbData->gem += $num;
|
||
if ($userDbData->gem < 0) throw new StatusException(ResultStatusServices::RS_GEM_NOT_ENOUGH);
|
||
if (!$userDbData->save(true, ['gem', 'updated_at'])) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR);
|
||
|
||
//任务记录
|
||
DailyTaskUtil::addTaskCount($userID, DailyTaskUtil::TYPE_EXPEND_GEM, null, 1);
|
||
}
|
||
|
||
if (!$logoVo->save()) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR);
|
||
|
||
}, [$userID, $num, $type, $logoVo], RedisKeyUtil::lockUser($userID));
|
||
}
|
||
|
||
public static function addUserExp($userID, $exp)
|
||
{
|
||
$exp = (int)$exp;
|
||
|
||
return SafeUtil::redisLockOperate(function ($userID, $exp) {
|
||
|
||
if ($exp <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
|
||
//获取用户信息
|
||
$userDbData = User::findById($userID);
|
||
if (!$userDbData) throw new StatusException(ResultStatusServices::RS_NOT_FIND_IN_DB);
|
||
|
||
//达到用户最大等级
|
||
// if ($userDbData->level >= GameConfigServices::getMaxPlayerLevel()) throw new StatusException(ResultStatusServices::RS_PLAYER_MAX_LEVEL);
|
||
|
||
$config = GameConfigServices::getParamByPath('player_level.' . $userDbData->level);
|
||
|
||
//增加经验
|
||
$userDbData->exp += $exp;
|
||
if ($userDbData->exp >= $config['exp'] && $userDbData->level < GameConfigServices::getMaxPlayerLevel()) {
|
||
$userDbData->level++;
|
||
$userDbData->exp = 0;
|
||
$userDbData->get_level_gift = EnumUtil::PLAYER_LEVEL_GIFT_NOT_GET;
|
||
}
|
||
|
||
if (!$userDbData->save(true, ['exp', 'level', 'get_level_gift', 'updated_at'])) throw new StatusException(ResultStatusServices::RS_SAVE_DB_ERROR, $userDbData->getErrors());
|
||
|
||
return $userDbData;
|
||
}, [$userID, $exp], RedisKeyUtil::lockUser($userID));
|
||
}
|
||
|
||
/**
|
||
* 解析物品,102001:10,101006:2,201000:10
|
||
* @param $itemStr
|
||
* @param $count
|
||
* @param $isAdd
|
||
* @param $userID
|
||
* @param $logFromType
|
||
* @param $logDetail
|
||
* @return array
|
||
*/
|
||
public static function parseAllItem($itemStr, $count, $isAdd, $userID, $logFromType, $logDetail)
|
||
{
|
||
$list = CommUtil::converStrList(',', $itemStr, 0);
|
||
if (empty($list)) return [];
|
||
|
||
$getList = [];
|
||
|
||
foreach ($list as $item) {
|
||
|
||
if (empty($item)) continue;
|
||
$getItem = MoneyUtil::parseItem($item, $count, $isAdd, $userID, $logFromType, $logDetail);
|
||
if (!empty($getItem)) array_push($getList, $getItem);
|
||
}
|
||
|
||
return $getList;
|
||
}
|
||
|
||
public static function parseAllItemIndex($itemStr, $index, $count, $isAdd, $userID, $logFromType, $logDetail)
|
||
{
|
||
$list = CommUtil::converStrList(',', $itemStr, 0);
|
||
if (empty($list) || !isset($list[$index])) return [];
|
||
|
||
$getList = [];
|
||
|
||
$item = $list[$index];
|
||
if (empty($item)) return [];
|
||
|
||
$getItem = MoneyUtil::parseItem($item, $count, $isAdd, $userID, $logFromType, $logDetail);
|
||
if (!empty($getItem)) array_push($getList, $getItem);
|
||
|
||
return $getList;
|
||
}
|
||
|
||
/**
|
||
* 解析物品,102001:10
|
||
* @param $itemStr
|
||
* @param $isAdd
|
||
* @param $userID
|
||
* @param $logFromType
|
||
* @param $logDetail
|
||
* @return array
|
||
* @throws StatusException
|
||
*/
|
||
public static function parseItem($itemStr, $count, $isAdd, $userID, $logFromType, $logDetail)
|
||
{
|
||
$count = (int)$count;
|
||
if ($count <= 0) throw new StatusException(ResultStatusServices::RS_PARAM_ERROR);
|
||
|
||
$list = CommUtil::converStrList(':', $itemStr, 2);
|
||
if (empty($list)) return null;
|
||
|
||
list($itemID, $num) = $list;
|
||
$itemID = (int)$itemID;
|
||
$num = (int)$num;
|
||
$num *= $count;
|
||
|
||
if (in_array($itemID, self::REMOVED_BOX_ITEM_IDS, true)) return null;
|
||
|
||
if (empty($itemID) || $num < 0) throw new StatusException(ResultStatusServices::RS_CONFIG_ERROR);
|
||
|
||
if ($num == 0) return null;
|
||
|
||
$itemConfig = GameConfigServices::getParamByPath('item_list.' . $itemID);
|
||
if (empty($itemConfig)) throw new StatusException(ResultStatusServices::RS_CONFIG_ERROR);
|
||
|
||
if (!$isAdd) {
|
||
$num *= -1;
|
||
if ($num >= 0) throw new StatusException(ResultStatusServices::RS_CONFIG_ERROR);
|
||
} else {
|
||
if ($num <= 0) throw new StatusException(ResultStatusServices::RS_CONFIG_ERROR);
|
||
}
|
||
|
||
$itemType = intval($itemConfig['type2']);
|
||
if ($itemType == ItemServices::ITEM_TYPE2_GOLD) {
|
||
|
||
$log = SystemLogUtil::get($userID, SystemLogUtil::TYPE_GOLD, $num, 0, $logFromType, $logDetail);
|
||
MoneyUtil::checkAndModifyRes($userID, $isAdd, $num, ItemServices::ITEM_TYPE2_GOLD, $log);
|
||
|
||
} else if ($itemType == ItemServices::ITEM_TYPE2_GEM) {
|
||
|
||
$log = SystemLogUtil::get($userID, SystemLogUtil::TYPE_GEM, $num, 0, $logFromType, $logDetail);
|
||
MoneyUtil::checkAndModifyRes($userID, $isAdd, $num, ItemServices::ITEM_TYPE2_GEM, $log);
|
||
|
||
}else if ($itemType == self::REMOVED_BOX_ITEM_TYPE) {
|
||
|
||
return null;
|
||
|
||
} else {
|
||
$log = SystemLogUtil::get($userID, SystemLogUtil::TYPE_ITEM, $itemID, $num, $logFromType, $logDetail);
|
||
MoneyUtil::checkAndModifyNum($userID, $itemID, $isAdd, $num, $log);
|
||
|
||
if (!$isAdd && $itemType == ItemServices::ITEM_TYPE2_FRUIT) {
|
||
AchievementUtil::addCount($userID, AchievementUtil::ID_CONSUME_FRUIT, abs($num));
|
||
}
|
||
|
||
if ($isAdd && $itemType == ItemServices::ITEM_TYPE2_CHIP) {
|
||
AchievementUtil::addCount($userID, AchievementUtil::ID_FRAGMENT_COUNT, abs($num));
|
||
}
|
||
}
|
||
|
||
//if (!$isAdd) {
|
||
// AchievementUtil::addCount($userID, AchievementUtil::ID_CONSUME, 1);
|
||
//}
|
||
|
||
return ['item_id' => $itemID, 'num' => $num];
|
||
}
|
||
|
||
/**
|
||
* 解析物品,物品ID:概率:数量
|
||
* 201012:85:1,201013:5:1,201014:5:1,201015:5:1
|
||
* @param $itemStr
|
||
* @param $isAdd
|
||
* @param $userID
|
||
* @param $logFromType
|
||
* @param $logDetail
|
||
* @return array
|
||
*/
|
||
public static function parseAllItemOdds($itemStr, $isAdd, $userID, $logFromType, $logDetail)
|
||
{
|
||
$list = CommUtil::converStrList(',', $itemStr, 0);
|
||
if (empty($list)) return null;
|
||
$oddList = [];
|
||
foreach ($list as $str) {
|
||
$list2 = CommUtil::converStrList(':', $str, 3);
|
||
if (empty($list2)) continue;
|
||
list($itemID, $odds, $count) = $list2;
|
||
if (empty($itemID) || empty($odds) || empty($count)) continue;
|
||
|
||
array_push($oddList, ['itemID' => $itemID, 'odds' => $odds, 'count' => $count]);
|
||
}
|
||
|
||
$item = CommUtil::oddsOne($oddList, "odds");
|
||
|
||
if (empty($item)) return null;
|
||
|
||
$itemID = $item['itemID'];
|
||
$count = $item['count'];
|
||
$str = sprintf('%s:%d', $itemID, $count);
|
||
|
||
$getItem = MoneyUtil::parseItem($str, 1, $isAdd, $userID, $logFromType, $logDetail);
|
||
if (empty($getItem)) return null;
|
||
|
||
return ['item_id' => $itemID, 'num' => $count];
|
||
}
|
||
|
||
/**
|
||
* 随机几个,102001:10,101006:2,201000:10
|
||
* @param $itemStr
|
||
* @param $count
|
||
* @param $isAdd
|
||
* @param $userID
|
||
* @param $logFromType
|
||
* @param $logDetail
|
||
* @return array
|
||
*/
|
||
public static function parseAllOddsItem($itemStr, $count, $isAdd, $userID, $logFromType, $logDetail)
|
||
{
|
||
$count = intval($count);
|
||
if ($count <= 0) return [];
|
||
|
||
$list = CommUtil::converStrList(',', $itemStr, 0);
|
||
if (empty($list)) return [];
|
||
|
||
$getList = [];
|
||
while ($count > 0) {
|
||
$listCount = count($list);
|
||
if ($listCount == 0) return $getList;
|
||
$listCount--;
|
||
|
||
$index = rand(0, $listCount);
|
||
$item = $list[$index];
|
||
if (empty($item)) continue;
|
||
$getItem = MoneyUtil::parseItem($item, 1, $isAdd, $userID, $logFromType, $logDetail);
|
||
if (!empty($getItem)) array_push($getList, $getItem);
|
||
|
||
$count--;
|
||
}
|
||
|
||
return $getList;
|
||
}
|
||
|
||
}
|