cp新功能
(cherry picked from commit 12647246d0b4a94923b991b54c260ebaac291706)
This commit is contained in:
parent
9ff70aa3e4
commit
2d61819a42
@ -70,7 +70,12 @@ public enum PropsCommodityType {
|
||||
/**
|
||||
* 红包封面.
|
||||
*/
|
||||
RED_PACKET;
|
||||
RED_PACKET,
|
||||
|
||||
/**
|
||||
* CP戒指.
|
||||
*/
|
||||
CP_RING;
|
||||
|
||||
|
||||
public boolean eq(String name) {
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package com.red.circle.other.inner.model.dto.user;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* CP戒指信息.
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class CpRingDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 道具资源ID.
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long propsId;
|
||||
|
||||
/**
|
||||
* 戒指名称.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 戒指封面图.
|
||||
*/
|
||||
private String cover;
|
||||
|
||||
/**
|
||||
* 过期时间戳(毫秒).
|
||||
*/
|
||||
private Long expireTime;
|
||||
|
||||
}
|
||||
@ -82,4 +82,54 @@ public class CpSimpleUserProfileCO implements Serializable {
|
||||
|
||||
private Timestamp createTime;
|
||||
|
||||
/**
|
||||
* 当前CP等级(未达到Lv1门槛为null).
|
||||
*/
|
||||
private Integer cpLevel;
|
||||
|
||||
/**
|
||||
* 下一级所需累计CP值(满级为null).
|
||||
*/
|
||||
private Long nextLevelExp;
|
||||
|
||||
/**
|
||||
* 爱心样式等级(0=无, 1-3).
|
||||
*/
|
||||
private Integer loveHeartLevel;
|
||||
|
||||
/**
|
||||
* 邻麦动效等级(0=无, 1-3).
|
||||
*/
|
||||
private Integer micEffectLevel;
|
||||
|
||||
/**
|
||||
* 资料卡背景等级(0=无, 1-3).
|
||||
*/
|
||||
private Integer profileCardLevel;
|
||||
|
||||
/**
|
||||
* 赠礼飘窗等级(0=无, 1-3).
|
||||
*/
|
||||
private Integer giftWindowLevel;
|
||||
|
||||
/**
|
||||
* 是否解锁非邻麦动效.
|
||||
*/
|
||||
private Boolean hasNonMicEffect;
|
||||
|
||||
/**
|
||||
* 是否解锁CP头饰.
|
||||
*/
|
||||
private Boolean hasCpHeadwear;
|
||||
|
||||
/**
|
||||
* 我方当前佩戴的CP戒指(未佩戴为null).
|
||||
*/
|
||||
private CpRingDTO selfRing;
|
||||
|
||||
/**
|
||||
* CP方当前佩戴的CP戒指(未佩戴为null).
|
||||
*/
|
||||
private CpRingDTO cpRing;
|
||||
|
||||
}
|
||||
|
||||
@ -2,10 +2,15 @@ package com.red.circle.other.app.command.material;
|
||||
|
||||
import com.red.circle.other.app.dto.cmd.material.SwitchUsePropsCmd;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import java.util.Objects;
|
||||
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||
import com.red.circle.other.inner.enums.material.PropsCommodityType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 用户切换使用道具.
|
||||
*
|
||||
@ -16,6 +21,8 @@ import org.springframework.stereotype.Component;
|
||||
public class UserSwitchUsePropsCmdExe {
|
||||
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final CpRelationshipService cpRelationshipService;
|
||||
private final CpRelationshipCacheService cpRelationshipCacheService;
|
||||
|
||||
public void execute(SwitchUsePropsCmd cmd) {
|
||||
if (Objects.equals(cmd.getUnload(), Boolean.TRUE)) {
|
||||
@ -23,13 +30,21 @@ public class UserSwitchUsePropsCmdExe {
|
||||
cmd.requiredReqUserId(),
|
||||
Objects.toString(cmd.getType())
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
userProfileGateway.switchUseProps(
|
||||
cmd.requiredReqUserId(),
|
||||
cmd.getPropsId()
|
||||
);
|
||||
}
|
||||
|
||||
// CP戒指切换后清除双方缓存
|
||||
if (Objects.equals(cmd.getType(), PropsCommodityType.CP_RING)) {
|
||||
List<Long> cpUserIds = cpRelationshipService.getCpUserId(cmd.requiredReqUserId());
|
||||
cpRelationshipCacheService.remove(List.of(cmd.requiredReqUserId()));
|
||||
if (cpUserIds != null && !cpUserIds.isEmpty()) {
|
||||
cpRelationshipCacheService.remove(cpUserIds);
|
||||
}
|
||||
}
|
||||
userProfileGateway.switchUseProps(
|
||||
cmd.requiredReqUserId(),
|
||||
cmd.getPropsId()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -4,11 +4,18 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.red.circle.component.redis.service.RedisService;
|
||||
import com.red.circle.other.infra.database.cache.key.user.UserKey;
|
||||
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
|
||||
import com.red.circle.other.infra.database.rds.entity.props.PropsBackpack;
|
||||
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpLevelConfig;
|
||||
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
|
||||
import com.red.circle.other.infra.database.rds.service.props.PropsBackpackService;
|
||||
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
|
||||
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
|
||||
import com.red.circle.other.inner.enums.material.PropsCommodityType;
|
||||
import com.red.circle.other.inner.model.dto.user.CpRingDTO;
|
||||
import com.red.circle.other.inner.model.dto.user.CpSimpleUserProfileCO;
|
||||
import com.red.circle.tool.core.collection.CollectionUtils;
|
||||
import com.red.circle.tool.core.date.DateUtils;
|
||||
@ -35,6 +42,8 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
|
||||
private final RedisService redisService;
|
||||
private final BaseInfoService baseInfoService;
|
||||
private final CpValueService cpValueService;
|
||||
private final PropsBackpackService propsBackpackService;
|
||||
private final PropsSourceRecordService propsSourceRecordService;
|
||||
|
||||
|
||||
private static final long CACHE_EXPIRE_SECONDS = 7200L;
|
||||
@ -84,7 +93,7 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
|
||||
String firstDay = cpRelationship.getCreateTime().toInstant()
|
||||
.atZone(ZoneId.systemDefault()).toLocalDate().toString();
|
||||
|
||||
return new CpSimpleUserProfileCO()
|
||||
CpSimpleUserProfileCO co = new CpSimpleUserProfileCO()
|
||||
.setMeUserId(baseInfo.getId())
|
||||
.setMeAccount(baseInfo.getAccount())
|
||||
.setMeUserAvatar(baseInfo.getUserAvatar())
|
||||
@ -98,6 +107,25 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
|
||||
.setCreateTime(cpRelationship.getCreateTime())
|
||||
.setDays(days)
|
||||
.setFirstDay(firstDay);
|
||||
|
||||
// 填充等级权益
|
||||
CpLevelConfig levelConfig = CpLevelConfig.of(cpValue);
|
||||
if (levelConfig != null) {
|
||||
co.setCpLevel(levelConfig.getLevel())
|
||||
.setNextLevelExp(levelConfig.nextExpThreshold())
|
||||
.setLoveHeartLevel(levelConfig.getLoveHeartLevel())
|
||||
.setMicEffectLevel(levelConfig.getMicEffectLevel())
|
||||
.setProfileCardLevel(levelConfig.getProfileCardLevel())
|
||||
.setGiftWindowLevel(levelConfig.getGiftWindowLevel())
|
||||
.setHasNonMicEffect(levelConfig.isHasNonMicEffect())
|
||||
.setHasCpHeadwear(levelConfig.isHasCpHeadwear());
|
||||
}
|
||||
|
||||
// 实时查双方背包中正在使用的CP戒指
|
||||
co.setSelfRing(buildCpRing(userId));
|
||||
co.setCpRing(buildCpRing(cpRelationship.getCpUserId()));
|
||||
|
||||
return co;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.sorted(Comparator.comparing(CpSimpleUserProfileCO::getCpValue).reversed()
|
||||
@ -117,6 +145,23 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
|
||||
return UserKey.CP.getKey(userId);
|
||||
}
|
||||
|
||||
private CpRingDTO buildCpRing(Long userId) {
|
||||
PropsBackpack backpack = propsBackpackService
|
||||
.getUserNotExpiredUseProps(userId, PropsCommodityType.CP_RING);
|
||||
if (backpack == null) {
|
||||
return null;
|
||||
}
|
||||
PropsSourceRecord source = propsSourceRecordService.getById(backpack.getPropsId());
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return new CpRingDTO()
|
||||
.setPropsId(backpack.getPropsId())
|
||||
.setName(source.getName())
|
||||
.setCover(source.getCover())
|
||||
.setExpireTime(backpack.getExpireTime().getTime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(List<Long> userIds) {
|
||||
userIds.forEach(userId -> {
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package com.red.circle.other.infra.database.rds.entity.user.user;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* CP等级配置.
|
||||
* <p>
|
||||
* 字段说明:
|
||||
* - expThreshold : 达到该等级所需的累计CP值(对应 user_cp_value.cp_val)
|
||||
* - loveHeartLevel : 爱心样式等级(0=无, 1-3=对应样式,展示在资料卡和用户头像旁)
|
||||
* - micEffectLevel : 邻麦动效等级(0=无, 1-3,仅在左右相邻麦位时触发)
|
||||
* - profileCardLevel: 资料卡动态背景等级(0=无, 1-3,展示在CP资料卡内层元素)
|
||||
* - giftWindowLevel : 赠礼飘窗等级(0=无, 1-3,双方赠送CP礼物时触发)
|
||||
* - hasNonMicEffect : 是否解锁非邻麦动效(true=解锁,非相邻时也可展示动效)
|
||||
* - hasCpHeadwear : 是否解锁CP头饰(true=解锁,展示在双方头像周期性飞出效果)
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Getter
|
||||
public enum CpLevelConfig {
|
||||
|
||||
LV1 (1, 500000L, 1, 1, 0, 0, false, false),
|
||||
LV2 (2, 1000000L, 2, 1, 0, 0, false, false),
|
||||
LV3 (3, 3000000L, 2, 2, 1, 0, false, false),
|
||||
LV4 (4, 5000000L, 2, 2, 1, 1, false, false),
|
||||
LV5 (5, 15500000L, 3, 2, 2, 1, true, true ),
|
||||
LV6 (6, 40000000L, 3, 3, 2, 1, true, true ),
|
||||
LV7 (7, 70000000L, 3, 3, 3, 1, true, true ),
|
||||
LV8 (8, 100000000L, 3, 3, 3, 2, true, true ),
|
||||
LV9 (9, 130000000L, 3, 3, 3, 3, true, true ),
|
||||
LV10(10, 200000000L, 3, 3, 3, 3, true, true );
|
||||
|
||||
private final int level;
|
||||
private final long expThreshold;
|
||||
private final int loveHeartLevel;
|
||||
private final int micEffectLevel;
|
||||
private final int profileCardLevel;
|
||||
private final int giftWindowLevel;
|
||||
private final boolean hasNonMicEffect;
|
||||
private final boolean hasCpHeadwear;
|
||||
|
||||
CpLevelConfig(int level, long expThreshold,
|
||||
int loveHeartLevel, int micEffectLevel,
|
||||
int profileCardLevel, int giftWindowLevel,
|
||||
boolean hasNonMicEffect, boolean hasCpHeadwear) {
|
||||
this.level = level;
|
||||
this.expThreshold = expThreshold;
|
||||
this.loveHeartLevel = loveHeartLevel;
|
||||
this.micEffectLevel = micEffectLevel;
|
||||
this.profileCardLevel = profileCardLevel;
|
||||
this.giftWindowLevel = giftWindowLevel;
|
||||
this.hasNonMicEffect = hasNonMicEffect;
|
||||
this.hasCpHeadwear = hasCpHeadwear;
|
||||
}
|
||||
|
||||
/** 按 expThreshold 降序,用于 of() 从高到低匹配. */
|
||||
private static final List<CpLevelConfig> DESC = Arrays.stream(values())
|
||||
.sorted(Comparator.comparingLong(CpLevelConfig::getExpThreshold).reversed())
|
||||
.toList();
|
||||
|
||||
/**
|
||||
* 根据累计CP值推算当前等级,未达到Lv1门槛返回 null.
|
||||
*/
|
||||
public static CpLevelConfig of(BigDecimal cpVal) {
|
||||
if (cpVal == null) {
|
||||
return null;
|
||||
}
|
||||
long val = cpVal.longValue();
|
||||
return DESC.stream()
|
||||
.filter(lv -> val >= lv.expThreshold)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一等级经验门槛,满级返回 null.
|
||||
*/
|
||||
public Long nextExpThreshold() {
|
||||
int nextOrdinal = this.ordinal() + 1;
|
||||
CpLevelConfig[] all = values();
|
||||
return nextOrdinal < all.length ? all[nextOrdinal].expThreshold : null;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user