增加跨服冲榜

master_yuenan
DESKTOP-C3M45P4\dengdan 2025-04-24 20:05:39 +08:00
parent 7f2a428605
commit cf192d935b
6 changed files with 218 additions and 29 deletions

View File

@ -359,11 +359,21 @@ public class RedisKey {
public static final String HERO_RANK = "HERO_RANK";//英雄召唤排行榜
public static final String FABAO_RANK = "FABAO_RANK";//法宝召唤啊排行榜
public static final String XUNXIAN_RANK = "XUNXIAN_RANK";//寻仙召唤排行榜
public static final String CROSS_MONEY_RANK = "CROSS_MONEY_RANK";//跨服现金点券消耗排行榜
public static final String CROSS_HERO_RANK = "CROSS_HERO_RANK";//跨服英雄召唤排行榜
public static final String CROSS_FABAO_RANK = "CROSS_FABAO_RANK";//跨服法宝召唤啊排行榜
public static final String CROSS_XUNXIAN_RANK = "CROSS_XUNXIAN_RANK";//跨服寻仙召唤排行榜
public static final String BACK_MONEY_RANK = "BACK_MONEY_RANK";//备份现金点券消耗排行榜
public static final String BACK_HERO_RANK = "BACK_HERO_RANK";//备份英雄召唤排行榜
public static final String BACK_FABAO_RANK = "BACK_FABAO_RANK";//备份法宝召唤啊排行榜
public static final String BACK_XUNXIAN_RANK = "BACK_XUNXIAN_RANK";//备份寻仙召唤排行榜
public static final String CROSS_BACK_MONEY_RANK = "CROSS_BACK_MONEY_RANK";//跨服备份现金点券消耗排行榜
public static final String CROSS_BACK_HERO_RANK = "CROSS_BACK_HERO_RANK";//跨服备份英雄召唤排行榜
public static final String CROSS_BACK_FABAO_RANK = "CROSS_BACK_FABAO_RANK";//跨服备份法宝召唤啊排行榜
public static final String CROSS_BACK_XUNXIAN_RANK = "CROSS_BACK_XUNXIAN_RANK";//跨服备份寻仙召唤排行榜
public static final String CROSS_CHONG_RANK_LOCK = "CROSS_CHONG_RANK_LOCK";//跨服冲榜结算分布式锁
public static final String CROSS_CHONG_RANK_LOCK_MARK = "CROSS_CHONG_RANK_LOCK_MARK";//跨服冲榜结算锁标记
/**
*

View File

@ -1076,6 +1076,10 @@ public class RedisUtil {
return getZSetScore(type,key,value,true);
}
public Double getCrossZSetScore(String type,String key, String value){
return getZSetScore(type,key,value,false);
}
public void updateZsetScores(String type,String key, Set<ZSetOperations.TypedTuple<String>> tuples){
String rkey = getKeyLocal(type, key);

View File

@ -1,9 +1,12 @@
package com.ljsd.jieling.logic.activity;
import com.ljsd.GameApplication;
import com.ljsd.jieling.db.redis.RedisKey;
import com.ljsd.jieling.db.redis.RedisUtil;
import com.ljsd.jieling.globals.Global;
import com.ljsd.jieling.jbean.ActivityMission;
import com.ljsd.jieling.jbean.ActivityProgressInfo;
import com.ljsd.jieling.logic.GlobleSystemLogic;
import com.ljsd.jieling.logic.activity.event.IEvent;
import com.ljsd.jieling.logic.activity.event.OpenServerActivityEvent;
import com.ljsd.jieling.logic.activity.event.Poster;
@ -51,6 +54,7 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
OpenServerActivityEvent event1 = (OpenServerActivityEvent) event;
int rankType = event1.getRankType();
User user = UserManager.getUser(event1.getUid());
//MONEY_RANK,XUNXIAN_RANK,FABAO_RANK,HERO_RANK要同时检测单服和跨服的活动,只要配置了就触发,可同时触发单服和跨服的
if(rankType == RankEnum.EQUIP_SCORE_RANK.getType()){
equipRankHandle(user);
}else if(rankType == RankEnum.SOUL_SEAL_RANK.getType()){
@ -59,12 +63,16 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
heroStarHandle(user);
}else if(rankType == RankEnum.MONEY_RANK.getType()){
moneyHandle(user,event1.getCost(),id);
crossMoneyHandle(user,event1.getCost(),id);
}else if(rankType == RankEnum.XUNXIAN_RANK.getType()){
xunxianHandle(user,event1.getCost(),id);
crossXunxianHandle(user,event1.getCost(),id);
}else if(rankType == RankEnum.FABAO_RANK.getType()){
fabaoHandle(user,event1.getCost(),id);
crossFabaoHandle(user,event1.getCost(),id);
}else if(rankType == RankEnum.HERO_RANK.getType()){
heroHandle(user,event1.getCost(),id);
crossHeroHandle(user,event1.getCost(),id);
}else{
}
@ -180,6 +188,86 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
rank.addRank(user.getId(),"", scoreCompute);
}
/**
*
* @param user
*/
public static void crossMoneyHandle(User user,int money,int actId){
if(money <= 0){
return;
}
if(!isOpen(RankEnum.CROSS_MONEY_RANK.getType(),actId)){
return;
}
AbstractRank rank = RankContext.getRankEnum(RankEnum.CROSS_MONEY_RANK.getType());
int score = (int)rank.getCrossScoreById(user.getId(),"");
if(score < 0){
score = 0;
}
int scoreCompute = score + money;
rank.addCrossRank(user.getId(),"", scoreCompute);
}
/**
*
* @param user
*/
public static void crossHeroHandle(User user,int cost,int actId){
if(cost <= 0){
return;
}
if(!isOpen(RankEnum.CROSS_HERO_RANK.getType(),actId)){
return;
}
AbstractRank rank = RankContext.getRankEnum(RankEnum.CROSS_HERO_RANK.getType());
int score = (int)rank.getCrossScoreById(user.getId(),"");
if(score < 0){
score = 0;
}
int scoreCompute = score + cost;
rank.addCrossRank(user.getId(),"", scoreCompute);
}
/**
*
* @param user
*/
public static void crossXunxianHandle(User user,int cost,int actId){
if(cost <= 0){
return;
}
if(!isOpen(RankEnum.CROSS_XUNXIAN_RANK.getType(),actId)){
return;
}
AbstractRank rank = RankContext.getRankEnum(RankEnum.CROSS_XUNXIAN_RANK.getType());
int score = (int)rank.getCrossScoreById(user.getId(),"");
if(score < 0){
score = 0;
}
int scoreCompute = score + cost;
rank.addCrossRank(user.getId(),"", scoreCompute);
}
/**
*
* @param user
*/
public static void crossFabaoHandle(User user,int cost,int actId){
if(cost <= 0){
return;
}
if(!isOpen(RankEnum.CROSS_FABAO_RANK.getType(),actId)){
return;
}
AbstractRank rank = RankContext.getRankEnum(RankEnum.CROSS_FABAO_RANK.getType());
int score = (int)rank.getCrossScoreById(user.getId(),"");
if(score < 0){
score = 0;
}
int scoreCompute = score + cost;
rank.addCrossRank(user.getId(),"", scoreCompute);
}
/**
*
*/
@ -327,6 +415,7 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
long rankStartTime = startTime + info.getOpenTime()*1000L;
long rankEndTime = startTime + info.getCloseTime()*1000L;
long now = TimeUtils.now();
activity.getIsOpen();
return now >= rankStartTime && now < rankEndTime;
}
@ -381,6 +470,11 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
*
*/
private void sendReward(int rankType) {
//是开服冲榜走跨服逻辑
if(RankContext.isCrossRank(rankType)){
sendCrossReward(rankType);
return;
}
LOGGER.info("===========================冲榜开始发奖:{}-{}",id,rankType);
// 备份排行榜
@ -404,34 +498,8 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
}
String title = getMailTitle(rankType);
String content = getMailContent(rankType, value, rank);
// 用户信息
User user = UserManager.getUser(uid, true);
if (user == null){
LOGGER.error("开服冲榜id为{}的玩家,{}活动,{}排行奖励发送失败,原因玩家不存在", uid, id, rankType);
continue;
}
LOGGER.info("冲榜发奖中:{}-{}-{}",id,rankType,uid);
AyyncWorker ayyncWorker = new AyyncWorker(user, true, user1 -> {
ActivityMission mission = user.getActivityManager().getActivityMissionMap().get(id);
if (mission == null){
LOGGER.error("开服冲榜id为{}的玩家,{}活动,{}排行奖励发送失败,原因活动不存在", uid, id, rankType);
return;
}
ActivityProgressInfo progressInfo = mission.getActivityMissionMap().get(rankType);
if (progressInfo != null && progressInfo.getState() == 2){
LOGGER.error("开服冲榜id为{}的玩家,{}活动,{}排行奖励发送失败,奖励已发送,{}-{}", uid, id, rankType, progressInfo.getProgrss(),progressInfo.getState());
return;
}
//sendmail
String mailReward = ItemUtil.getMailReward(reward);
MailLogic.getInstance().sendMail(uid, title, content, mailReward, TimeUtils.nowInt(), Global.MAIL_EFFECTIVE_TIME);
//update activity
ActivityProgressInfo info = new ActivityProgressInfo();
info.setState(2);
info.setProgrss(TimeUtils.nowInt());
mission.getActivityMissionMap().put(rankType, info);
});
ProtocolsManager.getInstance().updateAyncWorker(ayyncWorker);
String mailReward = ItemUtil.getMailReward(reward);
MailLogic.getInstance().sendMail(uid, title, content, mailReward, TimeUtils.nowInt(), Global.MAIL_EFFECTIVE_TIME);
rank++;
} catch (Exception e) {
LOGGER.error("冲榜id为{}的玩家,{}活动,{}排行奖励发送失败e={}", uid, id, rankType, e);
@ -441,6 +509,89 @@ public class OpenServerCompeteRankActivity extends AbstractActivity {
LOGGER.info("===========================冲榜发奖结束:{}-{}-{}",id,rankType,rankInfo.size());
}
/**
*
*/
private Set<ZSetOperations.TypedTuple<String>> crossBackRank(int rankType){
LOGGER.info("===========================跨服冲榜开始备份活动id{},排行榜类型:{},时间:{}",id,rankType,TimeUtils.nowInt());
int backRankType = 0;
try {
AbstractRank abstractRank = RankContext.getRankEnum(rankType);
Set<ZSetOperations.TypedTuple<String>> rankInfo = abstractRank.getCrossRankByKey("", 0, -1);
SChongRankInfo chongRankInfo = SChongRankInfo.getMap().get(id).get(rankType);
if (rankInfo == null || chongRankInfo == null){
LOGGER.error("跨服冲榜备份结束排行榜空活动id{},排行榜类型:{}",id,rankType);
return null;
}
backRankType = chongRankInfo.getBackRankType();
AbstractRank backRank = RankContext.getRankEnum(backRankType);
Set<ZSetOperations.TypedTuple<String>> backRankInfo = backRank.getCrossRankByKey("", 0, -1);
if (backRankInfo != null && !backRankInfo.isEmpty()){
LOGGER.info("跨服冲榜备份结束备份数据已存在活动id{},排行榜类型:{},排行榜数量:{}",id,backRankType,backRankInfo.size());
return null;
}
String key = RedisUtil.getInstence().getKeyLocal(backRank.getCrossRedisKey(),"");
RedisUtil.getInstence().zsetAddAall(key,rankInfo);
RedisUtil.getInstence().expire(key,getCleanRankTime(rankType));
LOGGER.info("===========================跨服冲榜备份结束活动id{},排行榜类型:{},时间:{}",id,backRankType,TimeUtils.nowInt());
return rankInfo;
}catch (Exception e){
LOGGER.error("跨服冲榜备份排行榜报错:{}-{}-{}",id,backRankType,e.getMessage());
}
return null;
}
/**
*
*/
private void sendCrossReward(int rankType) {
int crossGroup = GlobleSystemLogic.getInstence().getCrossGroup();
if (crossGroup == -1) {
return;
}
//分布式锁,保证一个组只有一个服进行结算
boolean lock = RedisUtil.getInstence().lock(RedisKey.CROSS_CHONG_RANK_LOCK + RedisKey.Delimiter_colon + rankType + RedisKey.Delimiter_colon + crossGroup, TimeUtils.ONE_HOUR);
if (!lock) {
return;
}
LOGGER.info("===========================跨服冲榜开始发奖:{}-{}",id,rankType);
// 备份排行榜
Set<ZSetOperations.TypedTuple<String>> rankInfo = backRank(rankType);
if (rankInfo == null){
LOGGER.error("===========================跨服冲榜发奖提前结束,备份排行榜返回结果为空:{}-{}",id,rankType);
return;
}
// 遍历发奖
int rank = 1;
for (ZSetOperations.TypedTuple<String> item : rankInfo) {
int uid = Integer.parseInt(item.getValue());
Double score = item.getScore();
try {
// 邮件信息
long value = score.longValue();
int[][] reward = getMailReward(rankType, rank);
if (reward == null){
LOGGER.error("跨服冲榜发奖此排名后玩家不发奖uid{}rankid:{}, score:{}",uid,rank, value);
break;
}
String title = getMailTitle(rankType);
String content = getMailContent(rankType, value, rank);
String mailReward = ItemUtil.getMailReward(reward);
MailLogic.getInstance().sendMail(uid, title, content, mailReward, TimeUtils.nowInt(), Global.MAIL_EFFECTIVE_TIME);
rank++;
} catch (Exception e) {
LOGGER.error("冲榜id为{}的玩家,{}活动,{}排行奖励发送失败e={}", uid, id, rankType, e);
e.printStackTrace();
}
}
//记录结算的组id和服务器id,保留3天
String lockMark = RedisKey.CROSS_CHONG_RANK_LOCK_MARK + RedisKey.Delimiter_colon + rankType + RedisKey.Delimiter_colon + crossGroup;
RedisUtil.getInstence().set(lockMark, String.valueOf(GameApplication.serverId));
RedisUtil.getInstence().expireMills(lockMark, TimeUtils.DAY * 3);
LOGGER.info("===========================跨服冲榜发奖结束:{}-{}-{}",id,rankType,rankInfo.size());
}
private int[][] getMailReward(int rankType, int rank){
LOGGER.info("冲榜获取邮件奖励type:{}, rank:{}",rankType, rank);
SChongRankInfo rankInfo = SChongRankInfo.getMap().get(id).get(rankType);

View File

@ -44,6 +44,10 @@ public enum RankEnum {
HERO_RANK(202,RedisKey.HERO_RANK,MainLevelRank::new,false),//英雄召唤排行榜
FABAO_RANK(203,RedisKey.FABAO_RANK,MainLevelRank::new,false),//法宝召唤排行榜
XUNXIAN_RANK(204,RedisKey.XUNXIAN_RANK,MainLevelRank::new,false),//现寻仙招募排行榜
CROSS_MONEY_RANK(205,RedisKey.CROSS_MONEY_RANK,MainLevelRank::new,true),//跨服现金点券消耗排行榜
CROSS_HERO_RANK(206,RedisKey.CROSS_HERO_RANK,MainLevelRank::new,true),//跨服英雄召唤排行榜
CROSS_FABAO_RANK(207,RedisKey.CROSS_FABAO_RANK,MainLevelRank::new,true),//跨服法宝召唤排行榜
CROSS_XUNXIAN_RANK(208,RedisKey.CROSS_XUNXIAN_RANK,MainLevelRank::new,true),//跨寻仙招募排行榜
//***************************************** 以下开服冲榜活动保留数据排行榜 *****************************************//
BACK_HERO_STAR_RANK(100101,"BACK_HERO_STAR_RANK",MainLevelRank::new,false),//英雄星级排行榜
@ -57,6 +61,10 @@ public enum RankEnum {
BACK_HERO_RANK(100202,RedisKey.BACK_HERO_RANK,MainLevelRank::new,false),//备份英雄召唤排行榜
BACK_FABAO_RANK(100203,RedisKey.BACK_FABAO_RANK,MainLevelRank::new,false),//备份法宝召唤排行榜
BACK_XUNXIAN_RANK(100204,RedisKey.BACK_XUNXIAN_RANK,MainLevelRank::new,false),//备份寻仙招募排行榜
CROSS_BACK_MONEY_RANK(100205,RedisKey.CROSS_BACK_MONEY_RANK,MainLevelRank::new,true),//跨服备份现金点券消耗排行榜
CROSS_BACK_HERO_RANK(100206,RedisKey.CROSS_BACK_HERO_RANK,MainLevelRank::new,true),//跨服备份英雄召唤排行榜
CROSS_BACK_FABAO_RANK(100207,RedisKey.CROSS_BACK_FABAO_RANK,MainLevelRank::new,true),//跨服备份法宝召唤排行榜
CROSS_BACK_XUNXIAN_RANK(100208,RedisKey.CROSS_BACK_XUNXIAN_RANK,MainLevelRank::new,true),//跨服备份寻仙招募排行榜
//***************************************** 以下为跨服排行榜 *****************************************//
GUILD_RED_PACKAGE_RANK(13,RedisKey.GUILD_RED_PACKAGE_RANK,GuildRedPackageRank::new,true),//param1红包总价格 param2无 param3:无

View File

@ -64,7 +64,7 @@ public class RankLogic {
int crossGroup = GlobleSystemLogic.getInstence().getCrossGroup();
PlayerInfoProto.RankResponse rankResponse;
AbstractRank rank = RankContext.getRankEnum(type);
if(RankContext.isCrossRank(type) && isCross == 1 && crossGroup > 0){//跨服
if(RankContext.isCrossRank(type) && crossGroup > 0){//跨服
rankResponse = rank.getCrossRank(session.getUid(),rkey,index/20+1, 20);
}
else{//本地

View File

@ -98,6 +98,18 @@ public abstract class AbstractRank implements IRank {
RedisUtil.getInstence().zsetAddOne(key, String.valueOf(uid), getScore(data));
}
/**
*
* @param uid
* @param rkey
* @param data
*/
public void addCrossRank(int uid, String rkey, double... data) {
String redisKey = this.getCrossRedisKey();
String key = RedisUtil.getInstence().getKeyNew(redisKey, rkey);
RedisUtil.getInstence().zsetAddOne(key, String.valueOf(uid), getScore(data));
}
/**
*
*/
@ -342,6 +354,10 @@ public abstract class AbstractRank implements IRank {
return RedisUtil.getInstence().getZSetScore(redisKey, rkey, String.valueOf(uid));
}
public double getCrossScoreById(int uid, String rkey) {
return RedisUtil.getInstence().getCrossZSetScore(this.getCrossRedisKey(), rkey, String.valueOf(uid));
}
public int getRankIndexByKey(String rkey, int uid) {
return RedisUtil.getInstence().getZSetreverseRank(redisKey, rkey, Integer.toString(uid)).intValue();
}