/* * Copyright 2014 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon.spi.pvp; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import javax.inject.Inject; import org.skfiy.typhon.AbstractComponent; import org.skfiy.typhon.ComponentException; import org.skfiy.typhon.ConnectionProvider; import org.skfiy.typhon.Typhons; import org.skfiy.typhon.dobj.HeroItemDobj; import org.skfiy.typhon.domain.FightGroup; import org.skfiy.typhon.domain.GlobalData; import org.skfiy.typhon.domain.HeroProperty; import org.skfiy.typhon.domain.HeroPropertyKeys; import org.skfiy.typhon.domain.IHeroEntity; import org.skfiy.typhon.domain.ITroop; import org.skfiy.typhon.domain.Incident; import org.skfiy.typhon.domain.Mail; import org.skfiy.typhon.domain.Normal; import org.skfiy.typhon.domain.Player; import org.skfiy.typhon.domain.PvpReport; import org.skfiy.typhon.domain.Role; import org.skfiy.typhon.domain.Troop; import org.skfiy.typhon.domain.VacantData; import org.skfiy.typhon.domain.item.HeroItem; import org.skfiy.typhon.packet.GeneralPacket; import org.skfiy.typhon.packet.MultipleValue; import org.skfiy.typhon.packet.Namespaces; import org.skfiy.typhon.packet.Packet; import org.skfiy.typhon.packet.PacketError; import org.skfiy.typhon.packet.PacketNotice; import org.skfiy.typhon.packet.PvpPacket; import org.skfiy.typhon.packet.SingleValue; import org.skfiy.typhon.repository.GlobalDataRepository; import org.skfiy.typhon.repository.IncidentRepository; import org.skfiy.typhon.session.Session; import org.skfiy.typhon.session.SessionContext; import org.skfiy.typhon.session.SessionManager; import org.skfiy.typhon.session.SessionUtils; import org.skfiy.typhon.spi.ConfigurationLoader; import org.skfiy.typhon.spi.IncidentConstants; import org.skfiy.typhon.spi.ItemProvider; import org.skfiy.typhon.spi.NoticeBoardProvider; import org.skfiy.typhon.spi.RoleProvider; import org.skfiy.typhon.spi.ServerSettingKeys; import org.skfiy.typhon.spi.Vip; import org.skfiy.typhon.spi.pvp.PvpRobot.Hero; import org.skfiy.typhon.spi.society.SocietyProvider; import org.skfiy.typhon.spi.war.Direction; import org.skfiy.typhon.spi.war.FightObject; import org.skfiy.typhon.spi.war.Terrain; import org.skfiy.typhon.spi.war.WarInfo; import org.skfiy.typhon.spi.war.WarProvider; import org.skfiy.typhon.spi.war.WarReport; import org.skfiy.typhon.spi.war.WarReport.Effect; import org.skfiy.typhon.util.ComponentUtils; import org.skfiy.typhon.util.DbUtils; import org.skfiy.typhon.util.FastRandom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import java.util.Collection; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.commons.math.util.MathUtils; import org.skfiy.typhon.DbException; import org.skfiy.typhon.util.RandomUtils; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class PvpProvider extends AbstractComponent { private static final Logger LOG = LoggerFactory.getLogger(PvpProvider.class); private final Timer TIMER = new Timer("PVP-Timer", true); private final Random RANK_RANDOM = new FastRandom(); private final Map<Integer, PvpRobot> pvpRobots = new HashMap<>(); // new private final List<PvpObject> pvpObjectList = new CopyOnWriteArrayList<>(); private final Map<Integer, Integer> pvpRankingMappings = new ConcurrentHashMap<>(); private final List<PvpAward> pvpAwards = new ArrayList<>(); private final List<PvpHighestRank> pvpHighestRanks = new ArrayList<>(); private final List<Integer> pvpBuyCounts = new ArrayList<>(); private int maxPvpHigestRanking; private Calendar settlementCal; @Inject private ConfigurationLoader configurationLoader; @Inject private ItemProvider itemProvider; @Inject private WarProvider warProvider; @Inject private GlobalDataRepository globalDataReposy; @Inject private SessionManager sessionManager; @Inject private RoleProvider roleProvider; @Inject private IncidentRepository incidentReposy; @Inject private ConnectionProvider connectionProvider; @Inject private NoticeBoardProvider noticeBoardProvider; @Inject private SocietyProvider societyProvider; @Override protected void doInit() { // PVP奖励 String content = ComponentUtils.readDataFile("pvp_awards.json"); JSONArray awards = JSON.parseArray(content); for (int i = 0; i < awards.size(); i++) { JSONObject json = awards.getJSONObject(i); pvpAwards.add(new PvpAward(json.getIntValue("beginRanking"), itemProvider.getItem(json .getString("#item.id")), json.getIntValue("count"))); } Collections.sort(pvpAwards); // PVP最高排名奖励 content = ComponentUtils.readDataFile("pvp_highest_ranks.json"); JSONArray ranks = JSON.parseArray(content); for (int i = 0; i < ranks.size(); i++) { JSONObject json = ranks.getJSONObject(i); pvpHighestRanks.add(new PvpHighestRank(json.getIntValue("beginRanking"), json .getIntValue("endRanking"), json.getIntValue("count"))); } maxPvpHigestRanking = pvpHighestRanks.get(pvpHighestRanks.size() - 1).endRanking; // PVP刷新CD时间 content = ComponentUtils.readDataFile("pvp_buy_count.json"); JSONArray counts = JSON.parseArray(content); for (int i = 0; i < counts.size(); i++) { pvpBuyCounts.add(counts.getIntValue(i)); } // PVP机器人 content = ComponentUtils.readDataFile("pvp_robots.json"); List<PvpRobot> robots = JSON.parseArray(content, PvpRobot.class); for (int i = 1; i <= robots.size(); i++) { pvpRobots.put(-i, robots.get(i - 1)); } try { SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); settlementCal = Calendar.getInstance(); settlementCal.setTime(sdf.parse(Typhons.getProperty("typhon.spi.pvp.settlementTime"))); } catch (ParseException e) { throw new ComponentException("Pvp: settlementTime[" + Typhons.getProperty("typhon.spi.pvp.settlementTime") + "]", e); } // 初始化机器人 if (!configurationLoader.getServerBoolean(ServerSettingKeys.SERVER_PVP_ROBOT_INITED)) { for (int i = 1; i <= robots.size(); i++) { PvpObject po = new PvpObject(); po.setRid(-i); po.setRobot(true); pvpObjectList.add(po); } configurationLoader.setServerProperty(ServerSettingKeys.SERVER_PVP_ROBOT_INITED, true); } else { // 加载PVP数据 GlobalData pvpData = globalDataReposy.getGlobalData(GlobalData.Type.pvp_data); pvpObjectList.addAll(JSON.parseArray(pvpData.getData(), PvpObject.class)); int ranking = 1; for (PvpObject po : pvpObjectList) { if (!po.isRobot()) { pvpRankingMappings.put(po.getRid(), ranking); } ranking++; } // for (Map.Entry<String, Object> entry : JSON.parseObject(pvpData.getData()).entrySet()) { // pvpObjects.put(entry.getKey(), // JSON.toJavaObject((JSON) entry.getValue(), PvpObject.class)); // // } } // 定时器 Calendar curCal = Calendar.getInstance(); int hour = settlementCal.get(Calendar.HOUR_OF_DAY); int minute = settlementCal.get(Calendar.MINUTE); int second = settlementCal.get(Calendar.SECOND); Calendar nextCal = Calendar.getInstance(); nextCal.set(Calendar.HOUR_OF_DAY, hour); nextCal.set(Calendar.MINUTE, minute); nextCal.set(Calendar.SECOND, second); nextCal.set(Calendar.MILLISECOND, 0); if (curCal.get(Calendar.HOUR_OF_DAY) >= hour && curCal.get(Calendar.MINUTE) >= minute && curCal.get(Calendar.SECOND) >= second) { nextCal.add(Calendar.DAY_OF_MONTH, 1); } long delay = nextCal.getTimeInMillis() - curCal.getTimeInMillis(); TIMER.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // 发送奖励 long curTime = System.currentTimeMillis(); PvpAward pa; Mail mail; int ranking = 1; for (PvpObject po : pvpObjectList) { if (po.isRobot()) { continue; } pa = findPvpAward(ranking); mail = new Mail(); mail.setTitle("竞技场每日奖励"); mail.setContent(String.format("今日您在竞技场排行%1d名,获得", ranking)); mail.setAppendix(pa.item.getId()); mail.setCount(pa.count); mail.setType(Mail.REWARD_NOTICE_TYPE); mail.setCreationTime(curTime); roleProvider.sendMail(po.getRid(), mail); ranking++; } } PvpAward findPvpAward(int ranking) { for (PvpAward pa : pvpAwards) { if (ranking >= pa.beginRanking) { return pa; } } return pvpAwards.get(pvpAwards.size() - 1); } }, delay, 24 * 60 * 60 * 1000); // 定时保存PVP数据 TIMER.scheduleAtFixedRate(new TimerTask() { @Override public void run() { savePvpData(); } }, Typhons.getLong("typhon.spi.pvp.saveDataFixedRateMs"), Typhons.getLong("typhon.spi.pvp.saveDataFixedRateMs")); } @Override protected void doReload() { } @Override protected void doDestroy() { savePvpData(); } /** * * @param packet */ public void buyCount(Packet packet) { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); Vip vip = roleProvider.getVip(normal.getVipLevel()); if (normal.getPvpBuyCount() >= vip.privileged.max_pvp_buy_count) { PacketError error = PacketError.createResult(packet, PacketError.Condition.conflict); error.setText("Not enough pvpBuyCount"); player.getSession().write(error); return; } int c = normal.getPvpBuyCount(); if (c >= pvpBuyCounts.size()) { c = pvpBuyCounts.size() - 1; } JSONObject object = new JSONObject(); object.put("place", "PvPBuyCounts"); object.put("buyCounts", c); SessionUtils.decrementDiamond(pvpBuyCounts.get(c), object.toString()); normal.setPvpCount(0); normal.setPvpBuyCount(normal.getPvpBuyCount() + 1); player.getSession().write(Packet.createResult(packet)); } public void refreshCd(Packet packet) { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); if (normal.getPvpCd() > 0) { JSONObject object = new JSONObject(); object.put("place", "PvpCD"); SessionUtils.decrementDiamond(Typhons.getInteger("typhon.spi.pvp.refreshCdDiamond"), object.toString()); normal.setPvpCd(0); } player.getSession().write(Packet.createResult(packet)); } /** * * @param player * @param r * @param index * @return */ public DargonPvpRival loadRoleId(Player player, int r, double index) { PvpObject po = pvpObjectList.get(r - 1); //FIXME if (po == null) { po = new PvpObject(); po.setRid(-RandomUtils.nextInt(pvpRobots.size() - 1)); } DargonPvpRival dargonPvpRival = new DargonPvpRival(); dargonPvpRival.setRid(po.getRid()); dargonPvpRival.setRanking(r); List<Hero> list = new ArrayList<>(); PvpRobot pr = pvpRobots.get(po.getRid()); if (po.isRobot()) { dargonPvpRival.setName(pr.getName()); dargonPvpRival.setLevel(pr.getLevel()); dargonPvpRival.setPowerGuess(pr.getPowerGuess()); dargonPvpRival.setHonour(pr.getHonour()); for (PvpRobot.Hero hero : pr.getHeros()) { list.add(newFightObject(hero, index)); } } else { Session session = sessionManager.getSession(po.getRid()); int powerGuess = 0; String societyName = null; if (session != null) { Player otherPlayer = SessionUtils.getPlayer(session); Normal normal = otherPlayer.getNormal(); FightGroup fightGroup = normal.getFightGroup(FightGroup.PVP_FG_IDX); Role role = otherPlayer.getRole(); dargonPvpRival.setName(role.getName()); dargonPvpRival.setLevel(role.getLevel()); dargonPvpRival.setAvatar(otherPlayer.getNormal().getAvatar()); dargonPvpRival.setAvatarBorder(otherPlayer.getNormal().getAvatarBorder()); societyName = normal.getSocietyName(); Troop troop; HeroItem hero; for (int i = 0; i < fightGroup.getHeroItems().length; i++) { hero = fightGroup.getHeroItem(i); troop = normal.getTroop(ITroop.Type.valueOf(i)); list.add(newFightObject(i, troop, hero, index)); powerGuess += hero.getPowerGuess(); } } else { VacantData vacantData = roleProvider.loadVacantData(po.getRid()); String[] fgids = vacantData.getFightGroup(FightGroup.PVP_FG_IDX); String hid; HeroProperty hero; Troop troop; dargonPvpRival.setName(vacantData.getName()); dargonPvpRival.setLevel(vacantData.getLevel()); dargonPvpRival.setAvatar(vacantData.getAvatar()); dargonPvpRival.setAvatarBorder(vacantData.getAvatarBorder()); societyName = vacantData.getSocietyName(); for (int i = 0; i < fgids.length; i++) { hid = fgids[i]; hero = vacantData.findHeroProperty(hid); troop = vacantData.getTroop(ITroop.Type.valueOf(i)); list.add(newFightObject(i, troop, hero, index)); powerGuess += hero.getPowerGuess(); } } dargonPvpRival.setSocietyName(societyName); dargonPvpRival.setPowerGuess(powerGuess); } dargonPvpRival.setHeros(list); return dargonPvpRival; } /** * 查询PVP排行榜信息. * * @return 前50名玩家信息 */ public List<PvpRival> loadRankingList() { List<PvpRival> list = new ArrayList<>(); for (int i = 1; i <= 50; i++) { list.add(loadRival(i)); } return list; } /** * * @param packet */ public void searchRivals(Packet packet) { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); // 首次进入竞技场 if (normal.getPvpRanking() <= 0) { initPlayerRanking(player); } else { // 如果对应的排名不是自己则重新初始化排名 PvpObject pvpObject = pvpObjectList.get(normal.getPvpRanking() - 1); if (pvpObject == null || pvpObject.getRid() != player.getRole().getRid()) { int oldPvpRanking = normal.getPvpRanking(); initPlayerRanking(player); LOG.error("PvpRankingError -> (user:{}, oldPvpRanking:{}, newPvpRanking:{})", player.getRole().getName(), oldPvpRanking, normal.getPvpRanking()); } } int pvpRanking = normal.getPvpRanking(); MultipleValue result = MultipleValue.createResult(packet); // 查询对手 if (pvpRanking > 3) { result.addVal(firstRival(pvpRanking)); } if (pvpRanking > 2) { result.addVal(secondRival(pvpRanking)); } if (pvpRanking > 1) { result.addVal(thirdRival(pvpRanking)); } player.getSession().write(result); } /** * * @param packet */ public void chooseRival(PvpPacket packet) { synchronized (Integer.toString(packet.getRanking()).intern()) { Player player = SessionUtils.getPlayer(); PvpObject po = pvpObjectList.get(packet.getRanking() - 1); if (po.getRid() != packet.getRivalRid()) { PacketError error = PacketError.createResult(packet, PacketError.Condition.pvp_ranking_changed); error.setText("Pvp ranking changed"); player.getSession().write(error); return; } Normal normal = player.getNormal(); // 是否有PVP挑战次数 if (normal.getPvpCount() >= Typhons.getInteger("typhon.spi.pvp.maxCount")) { PacketError error = PacketError.createResult(packet, PacketError.Condition.conflict); error.setText("Not enough pvpCount"); player.getSession().write(error); return; } if (normal.getPvpCd() != 0 && normal.getPvpCd() + Typhons.getLong("typhon.spi.pvp.chilldownMs") > System .currentTimeMillis()) { PacketError error = PacketError.createResult(packet, PacketError.Condition.conflict); error.setText("Pvp:chilldown"); player.getSession().write(error); return; } int counts = normal.getDailyTask().getTaskPvpCounts(); if (counts >= 0) { normal.getDailyTask().setTaskPvpCounts(counts + 1); } SingleValue result = SingleValue.createResult(packet, reckon(packet, po, normal)); result.setNs(packet.getNs()); player.getSession().write(result); } } /** * * @param packet */ public void playback(SingleValue packet) { SingleValue result = SingleValue.createResult(packet, loadWarReport((int) packet.getVal())); result.setNs(packet.getNs()); SessionContext.getSession().write(result); LOG.debug(JSON.toJSONString(result)); } /** * * @param rid * @return */ public int getRanking(int rid) { Integer ranking = pvpRankingMappings.get(rid); return (ranking == null) ? 0 : ranking; } /** * */ private void savePvpData() { // 保存PVP数据 GlobalData globalData = new GlobalData(); globalData.setType(GlobalData.Type.pvp_data); globalData.setData(JSON.toJSONString(pvpObjectList)); globalDataReposy.updateGlobalData(globalData); } /** * * @param packet * @param po * @param normal * @return */ private WarReport reckon(PvpPacket packet, PvpObject po, Normal normal) { // 战斗信息 WarInfo warInfo = new WarInfo(); warInfo.setTerrain(Terrain.None); // S方 FightGroup f = normal.getFightGroup(packet.getFgidx()); initAttacker(normal, f, warInfo); warInfo.getAttackerEntity().setSuccor( warProvider.loadSuccorFightObject(normal.player().getRole().getRid(), packet.getFgidx(), warInfo.getAttackerEntity().getFightObject(f.getCaptain()))); // N方 initDefender(po, warInfo); warInfo.getDefenderEntity().setSuccor( warProvider.loadSuccorFightObject(po.getRid(), FightGroup.PVP_FG_IDX, warInfo .getDefenderEntity().getFightObject(FightGroup.PRIMARY_POS))); WarReport warReport = warProvider.finalAttack(warInfo); if (warReport.getEffect() == WarReport.Effect.W) { swapRanking(normal, packet.getRanking()); giveHighRankAward(normal); // 公告 if (packet.getRanking() <= Typhons.getInteger("typhon.spi.pvp.noticeMaxRanking", 50)) { PacketNotice notice = new PacketNotice(); notice.setNtype(PacketNotice.PVP_RANKING_TYPE); notice.setName(normal.player().getRole().getName()); notice.setAnnex1(getRoleName(po.getRid())); notice.setAnnex2(packet.getRanking()); noticeBoardProvider.announce(notice); } } normal.setPvpCount(normal.getPvpCount() + 1); normal.setPvpCd(System.currentTimeMillis()); // 保存战报数据 int wid = saveWarReport(warReport); // 自己方战报 PvpReport pvpReport = new PvpReport(); pvpReport.setWid(wid); pvpReport.setName(warInfo.getDefenderEntity().getRoleName()); pvpReport.setLevel(warInfo.getDefenderEntity().getLevel()); pvpReport.setCreationTime(System.currentTimeMillis()); pvpReport.setEffect(warReport.getEffect().name()); pvpReport.setRobot(po.isRobot()); Session beSession = null; if (!po.isRobot()) { beSession = sessionManager.getSession(po.getRid()); if (beSession != null) { Normal beNormal = SessionUtils.getPlayer(beSession).getNormal(); pvpReport.setAvatar(beNormal.getAvatar()); pvpReport.setAvatarBorder(beNormal.getAvatarBorder()); pvpReport.setHero(newHeroJSONObject(warInfo.getDefenderEntity().getFightObject( beNormal.getFightGroup(beNormal.getLastFidx()).getCaptain()))); } else { VacantData vacantData = roleProvider.loadVacantData(po.getRid()); pvpReport.setAvatar(vacantData.getAvatar()); pvpReport.setAvatarBorder(vacantData.getAvatarBorder()); pvpReport.setHero(newHeroJSONObject(warInfo.getDefenderEntity().getFightObject( vacantData.getCaptain()))); } } else { pvpReport.setHero(newHeroJSONObject(pvpRobots.get(po.getRid()).getHero( FightGroup.PRIMARY_POS))); } normal.addPvpReport(pvpReport); if (warReport.getEffect() == Effect.W) { normal.setPvpWinCounts(normal.getPvpWinCounts() + 1); } if (!po.isRobot()) { // 对方战报 pvpReport = new PvpReport(); pvpReport.setWid(wid); pvpReport.setName(warInfo.getAttackerEntity().getRoleName()); pvpReport.setLevel(warInfo.getAttackerEntity().getLevel()); pvpReport.setHero(newHeroJSONObject(warInfo.getAttackerEntity().getFightObject( normal.getFightGroup(normal.getLastFidx()).getCaptain()))); pvpReport.setCreationTime(System.currentTimeMillis()); if (warReport.getEffect() == Effect.D) { pvpReport.setEffect(Effect.W.name()); } else { pvpReport.setEffect(Effect.D.name()); } pvpReport.setAvatar(normal.getAvatar()); pvpReport.setAvatarBorder(normal.getAvatarBorder()); if (beSession != null) { Normal beNormal = SessionUtils.getPlayer(beSession).getNormal(); beNormal.addPvpReport(pvpReport); } else { // 添加一个事件 Incident inc = new Incident(); inc.setUid(po.getRid()); inc.setEventName(IncidentConstants.EVENT_PVP_REPORT); inc.setData(JSONObject.toJSONString(pvpReport)); incidentReposy.save(inc); } } return warReport; } /** * * @param normal * @param br */ private synchronized void swapRanking(Normal normal, int beRanking) { int ranking = normal.getPvpRanking(); PvpObject temp = pvpObjectList.get(beRanking - 1); pvpObjectList.set(beRanking - 1, pvpObjectList.get(ranking - 1)); pvpObjectList.set(ranking - 1, temp); normal.setPvpRanking(beRanking); // 设置名次 pvpRankingMappings.put(normal.player().getRole().getRid(), beRanking); if (!temp.isRobot()) { pvpRankingMappings.put(temp.getRid(), ranking); } if (temp.getRid() > 0) { // 如果对方在线则设置对方的排名 Session beSession = sessionManager.getSession(temp.getRid()); if (beSession != null) { Normal beNormal = SessionUtils.getPlayer(beSession).getNormal(); beNormal.setPvpRanking(ranking); } else { // add event Incident incident = new Incident(); incident.setUid(temp.getRid()); incident.setEventName(IncidentConstants.EVENT_PVP_RANKING_CHANGED); incident.setData(Integer.toString(ranking)); incidentReposy.save(incident); } } } private void giveHighRankAward(Normal normal) { int lastRanking; if (normal.getPvpHighRanking() <= 0) { lastRanking = maxPvpHigestRanking; } else { lastRanking = normal.getPvpHighRanking() - 1; } // 名次不符合要求 if (normal.getPvpRanking() > lastRanking || normal.getPvpRanking() > maxPvpHigestRanking) { return; } // 获得的钻石 int diamond = 0; int i = pvpHighestRanks.size() - 1; PvpHighestRank highestRank; for (;;) { highestRank = pvpHighestRanks.get(i); // 在排名区间内 if (highestRank.beginRanking <= lastRanking && highestRank.endRanking >= lastRanking) { if (normal.getPvpRanking() >= highestRank.beginRanking) { diamond += (lastRanking - normal.getPvpRanking() + 1) * highestRank.count; lastRanking = normal.getPvpRanking(); } else { diamond += (lastRanking - highestRank.beginRanking + 1) * highestRank.count; lastRanking = highestRank.beginRanking - 1; } } // 如果最后排名小于等于当前排名则退出循环 if (i <= 0 || normal.getPvpRanking() > highestRank.endRanking) { break; } i--; } if (diamond > 100) { diamond = (int) MathUtils.round(diamond / 100D, 0); } else { diamond = 1; } // 发送钻石 Mail mail = new Mail(); mail.setTitle("最高排名奖励"); mail.setContent(String.format("您在竞技场获得%1d名(历史最高,提升%2d名),获得", normal.getPvpRanking(), normal.getPvpHighRanking() - normal.getPvpRanking())); mail.setAppendix(Typhons.getProperty("typhon.spi.singleDiamondItemId")); mail.setCount(diamond); mail.setType(Mail.REWARD_NOTICE_TYPE); roleProvider.sendMail(normal.player().getRole().getRid(), mail); // 设置最高排名 normal.setPvpHighRanking(normal.getPvpRanking()); } /** * 初始化玩家PVP排名信息. * * @param player */ private synchronized void initPlayerRanking(Player player) { Integer pvpRanking = pvpRankingMappings.get(player.getRole().getRid()); if (pvpRanking != null) { player.getNormal().setPvpRanking(pvpRanking); LOG.error("pvp ranking error, rid: {}, ranking: {}.", player.getRole().getRid(), pvpRanking); return; } PvpObject po = new PvpObject(); po.setRid(player.getRole().getRid()); int ranking = pvpObjectList.size() + 1; player.getNormal().setPvpRanking(ranking); // 设置最高排名 if (player.getNormal().getPvpHighRanking() <= 0) { player.getNormal().setPvpHighRanking(player.getNormal().getPvpRanking()); } pvpObjectList.add(po); pvpRankingMappings.put(player.getRole().getRid(), ranking); } // ===========================获取对手信息======================================================== private PvpRival firstRival(int ranking) { int min = Math.max((int) (ranking / 3D - ranking / 30D), 0); int max = Math.max(ranking / 2 - 1, 1); int x = max - min; if (x > 0) { x = RANK_RANDOM.nextInt(x + 1); } int r = min + x; return loadRival(r); } private PvpRival secondRival(int ranking) { int min = ranking / 2; int max = Math.max((int) (ranking / 50D * 49 - 1), 1); int x = max - min; if (x > 0) { x = RANK_RANDOM.nextInt(x + 1); } int r = min + x; return loadRival(r); } private PvpRival thirdRival(int ranking) { int min = (int) (ranking / 50D * 49); int max = ranking - 1; int x = max - min; if (x > 0) { x = RANK_RANDOM.nextInt(x + 1); } int r = min + x; return loadRival(r); } /** * * @param packet */ public void showHero(GeneralPacket packet) { Player player = SessionUtils.getPlayer(); int rid = 0; if (packet.getRid() == null) { //判断是不是排行榜查询玩家信息 rid = pvpObjectList.get((int) packet.getVal() - 1).getRid(); } else { rid = (int) packet.getRid(); } int index = (int) packet.getGeneral(); List<Object> heros = new ArrayList<>(); //机器人 if (rid <= 0) { PvpRobot pr = pvpRobots.get(rid); for (int i = 0; i < pr.getHeros().size(); i++) { PvpRobot.Hero hero = pr.getHero(i); heros.add(newHeroJSONObject(hero)); } } else { //玩家不在线 Session session = sessionManager.getSession(rid); if (session == null) { VacantData vacantData = roleProvider.loadVacantData(rid); String[] fightGroup = vacantData.getFightGroup(index); for (String heroId : fightGroup) { HeroProperty hero = vacantData.findHeroProperty(heroId); heros.add(newHeroJSONObject(hero)); } } else { //在线 Player beplayer = SessionUtils.getPlayer(session); FightGroup fightGroup = beplayer.getNormal().getFightGroup(index); for (HeroItem hero : fightGroup.getHeroItems()) { heros.add(newHeroJSONObject(hero)); } } } JSONObject result = new JSONObject(); result.put("val", heros); result.put("id", packet.getId()); result.put("type", Packet.Type.rs); player.getSession().write(Namespaces.HERO_PROPERTIES, result); } /** * * @param r 排名 * @return */ private PvpRival loadRival(int r) { PvpRival rs = new PvpRival(); PvpObject po = pvpObjectList.get(r - 1); rs.setRid(po.getRid()); rs.setRanking(r); // 机器人 if (po.isRobot()) { PvpRobot pr = pvpRobots.get(po.getRid()); rs.setName(pr.getName()); rs.setLevel(pr.getLevel()); rs.setPowerGuess(pr.getPowerGuess()); rs.setHonour(pr.getHonour()); // 武将信息 PvpRobot.Hero hero = pr.getHero(FightGroup.PRIMARY_POS); rs.setHero(newHeroJSONObject(hero)); } else { Session session = sessionManager.getSession(po.getRid()); String societyName = null; if (session == null) { // 不在线 VacantData vacantData = roleProvider.loadVacantData(po.getRid()); rs.setName(vacantData.getName()); rs.setLevel(vacantData.getLevel()); rs.setAvatar(vacantData.getAvatar()); rs.setAvatarBorder(vacantData.getAvatarBorder()); societyName = vacantData.getSocietyName(); String[] fightGroup = vacantData.getFightGroup(FightGroup.PVP_FG_IDX); int powerGuess = 0; for (String id : fightGroup) { powerGuess += vacantData.findHeroProperty(id).getPowerGuess(); } rs.setPowerGuess(powerGuess); rs.setSocietyName(societyName); HeroProperty hero = vacantData.findHeroProperty(fightGroup[vacantData.getCaptain()]); rs.setHero(newHeroJSONObject(hero)); } else { // 在线 Player player = SessionUtils.getPlayer(session); Role role = player.getRole(); rs.setName(role.getName()); rs.setLevel(role.getLevel()); rs.setAvatar(player.getNormal().getAvatar()); rs.setAvatarBorder(player.getNormal().getAvatarBorder()); Normal normal = player.getNormal(); int powerGuess = 0; societyName = normal.getSocietyName(); FightGroup fightGroup = normal.getFightGroup(FightGroup.PVP_FG_IDX); for (HeroItem heroItem : fightGroup.getHeroItems()) { powerGuess += heroItem.getPowerGuess(); } rs.setPowerGuess(powerGuess); rs.setSocietyName(societyName); HeroItem hero = fightGroup.getHeroItem(fightGroup.getCaptain()); rs.setHero(newHeroJSONObject(hero)); } } return rs; } private JSONObject newHeroJSONObject(PvpRobot.Hero hero) { JSONObject json = new JSONObject(); json.put(HeroPropertyKeys.ID, hero.getIid()); json.put(HeroPropertyKeys.LEVEL, hero.getLevel()); json.put(HeroPropertyKeys.STAR, hero.getStar()); json.put(HeroPropertyKeys.LADDER, hero.getLadder()); return json; } public JSONObject newHeroJSONObject(IHeroEntity hero) { JSONObject json = new JSONObject(); json.put(HeroPropertyKeys.ID, hero.getId()); json.put(HeroPropertyKeys.LEVEL, hero.getLevel()); json.put(HeroPropertyKeys.STAR, hero.getStar()); json.put(HeroPropertyKeys.LADDER, hero.getLadder()); return json; } private JSONObject newHeroJSONObject(FightObject hero) { JSONObject json = new JSONObject(); json.put(HeroPropertyKeys.ID, hero.getHeroId()); json.put(HeroPropertyKeys.LEVEL, hero.getLevel()); json.put(HeroPropertyKeys.STAR, hero.getStar()); json.put(HeroPropertyKeys.LADDER, hero.getLadder()); return json; } // ===========================获取对手信息======================================================== private void initAttacker(Normal normal, FightGroup fightGroup, WarInfo warInfo) { List<FightObject> fightObjects = new ArrayList<>(); Troop troop; HeroItem hero; int powerGuess = 0; for (int i = 0; i < fightGroup.getHeroItems().length; i++) { hero = fightGroup.getHeroItem(i); troop = normal.getTroop(ITroop.Type.valueOf(i)); fightObjects.add(warProvider.newFightObject(i, troop, hero)); powerGuess += hero.getPowerGuess(); } WarInfo.Entity attackerEntity = new WarInfo.Entity(Direction.S, fightObjects); attackerEntity.setFindAttackGoal(PvpFindAttackGoal.INSTANCE); attackerEntity.setCaptain(fightGroup.getCaptain()); attackerEntity.setRid(normal.player().getRole().getRid()); attackerEntity.setRoleName(normal.player().getRole().getName()); attackerEntity.setLevel(normal.getLevel()); attackerEntity.setSocietyName(normal.getSocietyName()); attackerEntity.setPowerGuess(powerGuess); warInfo.setAttackerEntity(attackerEntity); // 主将位武将信息 // return newHeroJSONObject(fightGroup.getHeroItem(FightGroup.PRIMARY_POS)); } private void initDefender(PvpObject po, WarInfo warInfo) { List<FightObject> fightObjects = new ArrayList<>(); WarInfo.Entity defenderEntity = new WarInfo.Entity(Direction.N, fightObjects); if (po.isRobot()) { PvpRobot pr = pvpRobots.get(po.getRid()); int i = 0; for (PvpRobot.Hero hero : pr.getHeros()) { fightObjects.add(newFightObject(i++, hero)); } defenderEntity.setRid(po.getRid()); defenderEntity.setRoleName(pr.getName()); defenderEntity.setLevel(pr.getLevel()); defenderEntity.setPowerGuess(pr.getPowerGuess()); } else { Session session = sessionManager.getSession(po.getRid()); int powerGuess = 0; if (session != null) { Player p = SessionUtils.getPlayer(session); Normal normal = p.getNormal(); FightGroup fightGroup = normal.getFightGroup(FightGroup.PVP_FG_IDX); Troop troop; HeroItem hero; for (int i = 0; i < fightGroup.getHeroItems().length; i++) { hero = fightGroup.getHeroItem(i); troop = normal.getTroop(ITroop.Type.valueOf(i)); fightObjects.add(warProvider.newFightObject(i, troop, hero)); powerGuess += hero.getPowerGuess(); } defenderEntity.setCaptain(fightGroup.getCaptain()); defenderEntity.setRid(p.getRole().getRid()); defenderEntity.setRoleName(p.getRole().getName()); defenderEntity.setLevel(normal.getLevel()); defenderEntity.setSocietyName(normal.getSocietyName()); } else { VacantData vacantData = roleProvider.loadVacantData(po.getRid()); String[] fgids = vacantData.getFightGroup(FightGroup.PVP_FG_IDX); String hid; HeroProperty hero; Troop troop; for (int i = 0; i < fgids.length; i++) { hid = fgids[i]; hero = vacantData.findHeroProperty(hid); troop = vacantData.getTroop(ITroop.Type.valueOf(i)); fightObjects.add(warProvider.newFightObject(i, troop, hero)); powerGuess += hero.getPowerGuess(); } defenderEntity.setRid(vacantData.getRid()); defenderEntity.setRoleName(vacantData.getName()); defenderEntity.setLevel(vacantData.getLevel()); defenderEntity.setSocietyName(vacantData.getSocietyName()); } defenderEntity.setPowerGuess(powerGuess); } // ==================== 防守队默认3格怒气 for (FightObject fo : fightObjects) { fo.setFury(Typhons.getInteger("typhon.spi.pvp.defenderDefaultFury", 3)); } defenderEntity.setFindAttackGoal(PvpFindAttackGoal.INSTANCE); warInfo.setDefenderEntity(defenderEntity); } private int saveWarReport(WarReport warReport) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; int id = 0; try { conn = connectionProvider.getConnection(); ps = conn.prepareStatement( "insert into t_pvp_report(data,creationTime) values(?,?)", Statement.RETURN_GENERATED_KEYS); ps.setString(1, JSON.toJSONString(warReport)); ps.setLong(2, System.currentTimeMillis()); if (ps.executeUpdate() > 0) { rs = ps.getGeneratedKeys(); rs.next(); id = rs.getInt(1); } DbUtils.commitQuietly(conn); } catch (SQLException e) { DbUtils.rollbackQuietly(conn); throw new DbException(e); } finally { DbUtils.closeQuietly(conn, ps, rs); } return id; } private WarReport loadWarReport(int id) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; WarReport warReport = null; try { conn = connectionProvider.getConnection(); ps = conn.prepareStatement("select t.data from t_pvp_report t where t.id=?"); ps.setInt(1, id); rs = ps.executeQuery(); if (rs.next()) { warReport = JSON.parseObject(rs.getString("data"), WarReport.class); } DbUtils.commitQuietly(conn); } catch (SQLException ex) { DbUtils.rollbackQuietly(conn); } finally { DbUtils.closeQuietly(conn, ps, rs); } return warReport; } /** * * @return */ Collection<PvpRobot> getPvpRobots() { return pvpRobots.values(); } /** * * @param rid * @return */ private String getRoleName(int rid) { if (rid <= 0) { return pvpRobots.get(rid).getName(); } Session session = sessionManager.getSession(rid); if (session != null) { return SessionUtils.getPlayer(session).getRole().getName(); } VacantData vacantData = roleProvider.loadVacantData(rid); return vacantData.getName(); } // ============================================================================================= private FightObject newFightObject(int idx, PvpRobot.Hero hero) { HeroItemDobj heroItemDobj = itemProvider.getItem(hero.getIid()); FightObject fo = new FightObject(idx, hero.getLevel(), hero.getLadder(), hero.getStar(), heroItemDobj); fo.setBaseAtk(hero.getAtk()); fo.setMaxDef(hero.getDef()); fo.setBaseMatk(hero.getMatk()); fo.setMaxMdef(hero.getMdef()); fo.setMaxHp(hero.getHp()); fo.setMaxCritRate(hero.getCritRate()); fo.setMaxDecritRate(hero.getDecritRate()); fo.setMaxCritMagn(hero.getCritMagn()); fo.setMaxParryRate(hero.getParryRate()); fo.setMaxDeparryRate(hero.getDeparryRate()); fo.setMaxParryValue(hero.getParryValue()); fo.setShots(warProvider.getHeroItemDobjShots(heroItemDobj, hero.getLadder())); return fo; } private Hero newFightObject(PvpRobot.Hero hero, double index) { Hero he = new Hero(); he.setIid(hero.getIid()); he.setLadder(hero.getLadder()); he.setStar(hero.getStar()); he.setLevel(hero.getLevel()); he.setAtk((int) (hero.getAtk() * index)); he.setDef((int) (hero.getDef())); he.setMatk((int) (hero.getMatk() * index)); he.setMdef((int) (hero.getMdef())); he.setHp((int) (hero.getHp() * index)); he.setCritRate(hero.getCritRate()); he.setDecritRate(hero.getDecritRate()); he.setCritMagn(hero.getCritMagn()); he.setParryRate(hero.getParryRate()); he.setDeparryRate(hero.getDeparryRate()); he.setParryValue(hero.getParryValue()); return he; } private Hero newFightObject(int pos, Troop troop, IHeroEntity hero, double factor) { Hero he = new Hero(); he.setIid(hero.getId()); he.setLadder(hero.getLadder()); he.setStar(hero.getStar()); he.setLevel(hero.getLevel()); he.setAtk((int) (warProvider.getAtk(troop, hero) * factor)); he.setDef((int) warProvider.getDef(troop, hero)); he.setMatk((int) (warProvider.getMatk(troop, hero) * factor)); he.setMdef((int) warProvider.getMdef(troop, hero)); he.setHp((int) (warProvider.getHp(troop, hero) * factor)); he.setCritRate(warProvider.getCritRate(troop, hero)); he.setDecritRate(warProvider.getDecritRate(troop, hero)); he.setCritMagn(warProvider.getCritMagn(troop, hero)); he.setParryRate(warProvider.getParryRate(troop, hero)); he.setDeparryRate(warProvider.getDeparryRate(troop, hero)); he.setParryValue(warProvider.getParryValue(troop, hero)); return he; } }