Merge branch 'wings' into hjb

This commit is contained in:
aozhiwei 2023-09-27 11:47:10 +08:00
commit 666df98266
16 changed files with 528 additions and 0 deletions

88
doc/Avatar.py Normal file
View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
import _common
class Avatar(object):
def __init__(self):
self.apis = [
{
'name': 'avatarMetaList',
'desc': 'item配置表中装饰列表',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=avatarMetaList',
'params': [
_common.ReqHead(),
],
'response': [
_common.RspHead(),
['!list', [], '装饰列表(参数见item.xlsx字段)']
]
},{
'name': 'avatarList',
'desc': '获取装饰物品列表',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=avatarList',
'params': [
_common.ReqHead(),
],
'response': [
_common.RspHead(),
['!list', [_common.AvatarInfo()], '装饰列表']
]
},{
'name': 'equip',
'desc': '穿戴装饰物品',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=equip',
'params': [
_common.ReqHead(),
['hero_uniid', '', '英雄唯一id'],
['avatar_uniid', '', '装饰唯一id'],
],
'response': [
_common.RspHead(),
['property_chg', _common.PropertyChg(), '属性变更'],
]
},{
'name': 'buyAvatar',
'desc': '购买装饰物品',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=buyAvatar',
'params': [
_common.ReqHead(),
['item_id', '', '装饰物品itemId'],
],
'response': [
_common.RspHead(),
]
},{
'name': 'remove',
'desc': '卸下装饰物品',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=remove',
'params': [
_common.ReqHead(),
['avatar_uniid', '', '装饰唯一id'],
],
'response': [
_common.RspHead(),
['property_chg', _common.PropertyChg(), '属性变更'],
]
},{
'name': 'clearAvatar',
'desc': '全部卸下',
'group': 'Avatar',
'url': 'webapp/index.php?c=Avatar&a=clearAvatar',
'params': [
_common.ReqHead(),
['hero_uniid', '', '英雄唯一id'],
],
'response': [
_common.RspHead(),
['property_chg', _common.PropertyChg(), '属性变更'],
]
},
]

View File

@ -272,6 +272,7 @@ class Hero(object):
['advanced_count', 0, '进阶次数'],
['offer_reward_state', 0, '是否悬赏中'],
['tags', '', '1Gen状态'],
['!avatarInfo', [AvatarInfo()], '装饰信息'],
]
@ -1480,6 +1481,19 @@ class StakingPreview(object):
['interest', 0, '利息'],
]
class AvatarInfo(object):
def __init__(self):
self.fields = [
['avatar_uniid', '', '装饰唯一id'],
['account_id', '', 'account_id'],
['token_id', '', 'token_id'],
['item_id', 0, 'item_id'],
['item_type', 0, '1:翅膀'],
['status', 0, '0:为穿戴 1:已穿戴'],
['hero_uniid', 0, '穿戴的英雄唯一id'],
]
class BattleData(object):
def __init__(self):

View File

@ -1671,3 +1671,26 @@ CREATE TABLE `t_mail` (
KEY `account_id_mailid` (`account_id`, `mailid`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `t_avatar`
--
DROP TABLE IF EXISTS `t_avatar`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `t_avatar` (
`idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id',
`account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)',
`token_id` varchar(60) COMMENT 'token_id',
`item_id` int(11) NOT NULL COMMENT 'item_id',
`item_type` int(11) NOT NULL COMMENT 'item类型',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '装备状态',
`hero_idx` bigint DEFAULT NULL COMMENT '英雄外键id',
`createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
`modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
PRIMARY KEY (`idx`),
UNIQUE KEY `hero_idx_type` (`hero_idx`, `item_type`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

View File

@ -0,0 +1,19 @@
begin;
CREATE TABLE `t_avatar` (
`idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id',
`account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)',
`token_id` varchar(60) COMMENT 'token_id',
`item_id` int(11) NOT NULL COMMENT 'item_id',
`item_type` int(11) NOT NULL COMMENT 'item类型',
`status` int(11) NOT NULL DEFAULT '0' COMMENT '装备状态',
`hero_idx` bigint DEFAULT NULL COMMENT '英雄外键id',
`createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
`modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
PRIMARY KEY (`idx`),
UNIQUE KEY `hero_idx_type` (`hero_idx`, `item_type`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
insert into version (version) values(2023092001);
commit;

0
sql/migrate/.gitkeep Normal file
View File

View File

@ -0,0 +1,163 @@
<?php
require_once('mt/Item.php');
require_once('models/Hero.php');
require_once('models/Avatar.php');
require_once('services/LogService.php');
require_once('services/PropertyChgService.php');
use models\Hero;
use models\Avatar;
use services\LogService;
class AvatarController extends BaseAuthedController {
public function avatarMetaList(){
$metaList = \mt\Item::getMetaListByType(\mt\Item::AVATAR_TYPE);
$this->_rspData(array(
'list' => $metaList
));
}
public function avatarList(){
$avatarList = array();
Avatar::getAvatarList(function ($row) use (&$avatarList){
array_push($avatarList,Avatar::toDto($row));
});
$this->_rspData(array(
'list' => $avatarList
));
}
public function equip(){
$heroUniid = trim(getReqVal('hero_uniid', 0));
$avatarUniid = trim(getReqVal('avatar_uniid', 0));
$heroDb = Hero::find($heroUniid);
if (!$heroDb){
$this->_rspErr(1, 'hero_uniid error');
return;
}
$avatarDb = Avatar::find($avatarUniid);
if (!$avatarDb){
$this->_rspErr(1, 'avatar_uniid error');
return;
}
if ($heroDb['idx'] == $avatarDb['hero_idx']){
$this->_rspErr(1, 'avatar_uniid error');
return;
}
$randAttr = emptyReplace(json_decode($heroDb['rand_attr'], true), array());
$itemMeta = \mt\Item::get($avatarDb['item_id']);
$quality = 1;
foreach ($randAttr as $value){
$quality = max($quality,$value['quality']);
}
switch ($itemMeta['quality']){
case 2 : {
if ($quality < 3){
$this->_rspErr(1, 'Can not meet the wearing condition');
return;
}
}
break;
case 3 :{
if ($quality < 4){
$this->_rspErr(1, 'Can not meet the wearing condition');
return;
}
}
break;
case 4 :{
if ($quality < 5){
$this->_rspErr(1, 'Can not meet the wearing condition');
return;
}
}
}
Avatar::equipUpdate($avatarDb,$heroUniid);
$propertyChgService = new services\PropertyChgService();
$propertyChgService->addHeroChg();
$this->_rspData(array(
'property_chg' => $propertyChgService->toDto(),
));
}
public function remove(){
$avatarUniid = trim(getReqVal('avatar_uniid', 0));
$avatarDb = Avatar::find($avatarUniid);
if (!$avatarDb){
$this->_rspErr(1, 'avatar_uniid error');
return;
}
Avatar::update($avatarUniid,array(
'hero_idx' => null,
'status' => 0,
'modifytime' => myself()->_getNowTime(),
));
$propertyChgService = new services\PropertyChgService();
$propertyChgService->addHeroChg();
$this->_rspData(array(
'property_chg' => $propertyChgService->toDto(),
));
}
public function clearAvatar(){
$heroUniid = trim(getReqVal('hero_uniid', 0));
$heroDb = Hero::find($heroUniid);
if (!$heroDb){
$this->_rspErr(1, 'hero_uniid error');
return;
}
$avatarDbs = Avatar::getAvatarByHeroIdx($heroUniid);
if (!$avatarDbs){
$this->_rspErr(1, 'Meaningless operation');
return;
}
foreach ($avatarDbs as $avatarDb){
Avatar::update($avatarDb['idx'],array(
'hero_idx' => null,
'status' => 0,
'modifytime' => myself()->_getNowTime(),
));
}
$propertyChgService = new services\PropertyChgService();
$propertyChgService->addHeroChg();
$this->_rspData(array(
'property_chg' => $propertyChgService->toDto(),
));
}
public function buyAvatar(){
$itemId = trim(getReqVal('item_id', 0));
$itemMeta = \mt\Item::get($itemId);
if (!$itemMeta || $itemMeta['type'] != \mt\Item::AVATAR_TYPE){
$this->_rspErr(1, 'item id error');
return;
}
//检验钻石是否足够 并消耗钻石
$costItems = array(
array(
'item_id' => V_ITEM_DIAMOND,
'item_num' => $itemMeta['diamond']
),
);
$lackItem = null;
if (!$this->_hasEnoughItems($costItems, $lackItem)) {
$this->_rspErr(3, $this->_getLackItemErrMsg($lackItem));
return;
}
$this->_decItems($costItems);
{
//埋点
$event = [
'name' => LogService::BUY_HERO_AVATAR,
'val' => $itemMeta['diamond']
];
LogService::consumeDiamond($event);
}
Avatar::addAvatar($itemMeta);
$this->_rspOk();
}
}

View File

@ -15,6 +15,7 @@ require_once('models/UserSeasonRing.php');
require_once('models/Parachute.php');
require_once('models/Chip.php');
require_once('models/Pass.php');
require_once('models/Avatar.php');
require_once('mt/Parameter.php');
require_once('mt/RankSeason.php');
require_once('mt/LevelUp.php');
@ -36,6 +37,7 @@ use models\Parachute;
use models\UserSeasonRing;
use models\Chip;
use models\Pass;
use models\Avatar;
use services\LogService;
class BaseAuthedController extends BaseController {
@ -555,6 +557,11 @@ class BaseAuthedController extends BaseController {
$this->_openRandomBox($itemMeta,$awardService,$propertyService);
}
break;
case mt\Item::AVATAR_TYPE:
{
Avatar::addAvatar($itemMeta);
}
break;
default:
{
$this->_addLog('additems', 'invalid_item', array(

View File

@ -293,6 +293,7 @@ class BattleController extends BaseAuthedController {
if ($heroDb) {
$info['is_valid_battle'] = 1;
$info['hero_dto'] = Hero::toDto($heroDb);
$info['hero_dto']['avatar_info'] = Hero::avatarInfo($heroDb);
} else {
$info['errcode'] = 51;
$info['errmsg'] = 'paramater error';

View File

@ -70,7 +70,10 @@ class DailyRequestController extends BaseAuthedController {
}
error_log("DailyRequestController : Mission Star Season ".$season." Settlement Success !" . " Request Time : ". date('Y-M-D h:i:s',time()));
RealtimeData::setMissionSeason($currMissionSeasonMeta['id']);
$this->_rspData(array('message'=>'星星之路结算成功'));
return;
}
$this->_rspOk();
}
/**
@ -90,7 +93,10 @@ class DailyRequestController extends BaseAuthedController {
);
error_log("DailyRequestController : Battle Pass Season ".$season." Settlement Success !" . " Request Time : ". date('Y-M-D h:i:s',time()));
RealtimeData::setPassSeason($currSeasonMeta['id']);
$this->_rspData(array('message'=>'通行证结算成功'));
return;
}
$this->_rspOk();
}
/**
@ -155,6 +161,8 @@ class DailyRequestController extends BaseAuthedController {
}
error_log("DailyRequestController : Battle Ranking Season ".$season." Settlement Success !" . " Request Time : ". date('Y-M-D h:i:s',time()));
RealtimeData::setRankSeason($lastSeasonMeta['id']);
$this->_rspData(array('message'=>'排位结算成功'));
return;
}
$this->_rspOk();
}
@ -176,6 +184,8 @@ class DailyRequestController extends BaseAuthedController {
error_log("computingPowerRewards : ACCOUNT_ID_{$row['account_id']} CEC Reward record completion");
}
}
$this->_rspData(array('message'=>'算力结算成功'));
return;
}
$this->_rspOk();
}

View File

@ -88,6 +88,7 @@ class HeroController extends BaseAuthedController {
$resetLv_state = $this->_getDailyV(TN_DAILY_RESET_HERO_LEVEL_STATE, $unique_id);
$hero = Hero::toDto($heroDb);
$hero['avatarInfo'] = Hero::avatarInfo($heroDb);
$hero['resetLv_state'] = $resetLv_state;
$this->_rspData(array(
'data' => $hero

177
webapp/models/Avatar.php Normal file
View File

@ -0,0 +1,177 @@
<?php
namespace models;
use mt;
use phpcommon\SqlHelper;
use services\NftService;
class Avatar extends BaseModel
{
public static function find($avatarUniId){
return self::internalFind(myself()->_getAccountId(), myself()->_getAddress(), $avatarUniId);
}
private static function internalFind($accountId, $address, $avatarUniId)
{
$row = SqlHelper::ormSelectOne(
myself()->_getMysql($accountId),
't_avatar',
array(
'idx' => $avatarUniId,
)
);
if ($row) {
$row['avatar_uniid'] = $row['idx'];
if ($row['account_id'] != $accountId) {
$openId = $address;
if (!NftService::isAvatarOwner($openId, $row['token_id'])) {
$row = null;
}
}
}
return $row;
}
public static function getAvatarByHeroIdx($heroUniid){
$rows = SqlHelper::ormSelect(
myself()->_getSelfMysql(),
't_avatar',
array(
'hero_idx' => $heroUniid,
)
);
$avatarList = array();
if (count($rows) > 0){
foreach ($rows as $row){
$row['avatar_uniid'] = $row['idx'];
if ($row['account_id'] != myself()->_getAccountId()) {
$openId = myself()->_getAddress();
if (NftService::isAvatarOwner($openId, $row['token_id'])) {
array_push($avatarList,$row);
}
}else{
array_push($avatarList,$row);
}
}
}
return $avatarList;
}
public static function getOneByType($heroUniid,$itemType){
$row = SqlHelper::ormSelectOne(
myself()->_getSelfMysql(),
't_avatar',
array(
'hero_idx' => $heroUniid,
'item_type' => $itemType,
)
);
if ($row) {
$row['avatar_uniid'] = $row['idx'];
if ($row['account_id'] != myself()->_getAccountId()) {
$openId = myself()->_getAddress();
if (!NftService::isAvatarOwner($openId, $row['token_id'])) {
$row = null;
}
}
}
return $row;
}
public static function getAvatarList($cb){
SqlHelper::ormSelect(
myself()->_getSelfMysql(),
't_avatar',
array(
'account_id' => myself()->_getAccountId()
),
function ($row) use($cb) {
$cb($row);
}
);
foreach (NftService::getAvatar(myself()->_getAddress()) as $nftDb) {
if (! $nftDb['deleted']){
$row = SqlHelper::ormSelectOne(
myself()->_getSelfMysql(),
't_avatar',
array(
'token_id' => $nftDb['token_id'],
)
);
$cb($row);
}
}
}
public static function toDto($row){
$dto = array(
'idx' => $row['idx'],
'avatar_uniid' => $row['idx'],
'token_id' => $row['token_id'],
'hero_uniid' => $row['hero_idx'],
'item_id' => $row['item_id'],
'item_type' => $row['item_type'],
'status' => $row['status'],
);
return $dto;
}
public static function addAvatar($avatarMeta){
SqlHelper::insert(
myself()->_getSelfMysql(),
't_avatar',
array(
'account_id' => myself()->_getAccountId(),
'item_id' => $avatarMeta['id'],
'item_type' => $avatarMeta['sub_type'],
'createtime' => myself()->_getNowTime(),
'modifytime' => myself()->_getNowTime(),
)
);
}
public static function equipUpdate($avatarDb,$heroUniid){
$row = self::getOneByType($heroUniid,$avatarDb['item_type']);
if ($row){
SqlHelper::update(
myself()->_getSelfMysql(),
't_avatar',
array(
'idx' => $row['idx'],
),
array(
'status' => 0,
'hero_idx' => null,
'modifytime' => myself()->_getNowTime(),
)
);
}
SqlHelper::update(
myself()->_getSelfMysql(),
't_avatar',
array(
'idx' => $avatarDb['idx'],
),
array(
'status' => 1,
'hero_idx' => $heroUniid,
'modifytime' => myself()->_getNowTime(),
)
);
}
public static function update($avatarUniid,$feildKv){
SqlHelper::update(
myself()->_getSelfMysql(),
't_avatar',
array(
'idx' => $avatarUniid,
),
$feildKv
);
}
}

View File

@ -11,6 +11,7 @@ require_once('mt/Item.php');
require_once('models/HeroSkin.php');
require_once('models/Chip.php');
require_once('models/User.php');
require_once('models/Avatar.php');
require_once('models/ChipPlugin.php');
require_once('services/NftService.php');
require_once('services/FormulaService.php');
@ -313,6 +314,17 @@ class Hero extends BaseModel {
return $dto;
}
public static function avatarInfo($row){
$avatarDbs = Avatar::getAvatarByHeroIdx($row['idx']);
$avatarInfos = array();
if ($avatarDbs){
foreach ($avatarDbs as $avatarDb){
array_push($avatarInfos,Avatar::toDto($avatarDb));
}
}
return $avatarInfos;
}
public static function addFreeHero($heroMeta)
{
return self::internalAddHero(

View File

@ -26,6 +26,7 @@ class Nft extends BaseModel
const GENESIS_TYPE = 7; //创世徽章
const PLANET_TYPE = 8; //星球
const RING_TYPE = 19; //戒指
const AVATAR_TYPE = 30; //装饰
const GENESIS_TAG = 1;

View File

@ -104,6 +104,7 @@ class Item {
const CHEST_BOX_TYPE = 23;
const PLANET_TYPE = 28;
const AVATAR_TYPE = 29;
const FUNC_RENAME_CARD_SUBTYPE = 1;
const FUNC_GUILD_CARD_SUBTYPE = 3;

View File

@ -17,6 +17,7 @@ class LogService extends BaseService
const CHIP_LEVEL_UP = "chip_level_Up"; //芯片升级
const BUY_BATTLE_PASS = "buy_battle_pass"; //通行证购买
const BUY_PASS_EXP = "buy_pass_exp"; //购买通行证经验
const BUY_HERO_AVATAR = "buy_hero_avatar"; //购买英雄装饰
const SHOP_BUY_ITEM = "shop_buy_item_normal"; //商城购买物品
const SHOP_BUY_ITEM_DAILY = "shop_buy_item_daily"; //商城每日精选购买物品

View File

@ -21,6 +21,7 @@ class NftService extends BaseService {
'equip' => Nft::EQUIP_TYPE,
'chip' => Nft::CHIP_TYPE,
'ring' => Nft::RING_TYPE,
'avatar' => Nft::AVATAR_TYPE,
);
public static function getChipBlance($account, $tokenId)
@ -28,6 +29,11 @@ class NftService extends BaseService {
return Nft::getChipBlance($account, $tokenId);
}
public static function isAvatarOwner($openId, $tokenId)
{
return self::internalIsOwner($openId, 'avatar', $tokenId);
}
public static function isHeroOwner($openId, $tokenId)
{
return self::internalIsOwner($openId, 'hero', $tokenId);
@ -62,6 +68,10 @@ class NftService extends BaseService {
{
return self::internalGetList($openId, 'ring');
}
public static function getAvatar($openId)
{
return self::internalGetList($openId, 'avatar');
}
private static function internalGetList($openId, $name)
{