/*
* 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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.inject.Inject;
import org.skfiy.typhon.AbstractComponent;
import org.skfiy.typhon.domain.FightGroup;
import org.skfiy.typhon.domain.Normal;
import org.skfiy.typhon.domain.Player;
import org.skfiy.typhon.domain.Troop;
import org.skfiy.typhon.domain.item.HeroItem;
import org.skfiy.typhon.packet.AttackPacket;
import org.skfiy.typhon.packet.Namespaces;
import org.skfiy.typhon.packet.OnlinePvpPacket;
import org.skfiy.typhon.packet.Packet;
import org.skfiy.typhon.packet.PacketError;
import org.skfiy.typhon.packet.SingleValue;
import org.skfiy.typhon.session.Session;
import org.skfiy.typhon.session.SessionManager;
import org.skfiy.typhon.session.SessionUtils;
import org.skfiy.typhon.spi.war.Direction;
import org.skfiy.typhon.spi.war.FightObject;
import org.skfiy.typhon.spi.war.WarInfo;
import org.skfiy.typhon.spi.war.WarProvider;
import org.skfiy.typhon.spi.war.WarReport;
import org.skfiy.util.Assert;
/**
*
* @author Kevin Zou <kevinz@skfiy.org>
*/
public class OnlinePvpProvider extends AbstractComponent {
private static final String ONLINE_PVP_SESSION_KEY = "__onlinePvpSessionKey";
private final AtomicInteger OP_ID_SEQ = new AtomicInteger();
private final Map<String, OnlinePvpWarInfo> onlinePvpWarInfos = new HashMap<>();
@Inject
private SessionManager sessionManager;
@Inject
private WarProvider warProvider;
@Override
protected void doInit() {
}
@Override
protected void doReload() {
}
@Override
protected void doDestroy() {
}
// invite 邀请对战
public void invite(SingleValue packet) {
Player player = SessionUtils.getPlayer();
Session otherSession = sessionManager.getSession((int) packet.getVal());
if (otherSession == null) {
// No online.
player.getSession().write(PacketError.createResult(packet,
PacketError.Condition.not_online));
return;
}
// 对方已经存在战斗
if (otherSession.getAttribute(ONLINE_PVP_SESSION_KEY) != null) {
player.getSession().write(PacketError.createResult(packet,
PacketError.Condition.opvp_unable_connect));
return;
}
String opid = generateId();
OnlinePvpWarInfo opInfo = new OnlinePvpWarInfo(opid);
onlinePvpWarInfos.put(opid, opInfo);
// 设置攻击方基本信息
WarInfo.Entity attackerEntity = new WarInfo.Entity(Direction.S);
attackerEntity.setRid(player.getRole().getRid());
attackerEntity.setRoleName(player.getRole().getName());
attackerEntity.setLevel(player.getRole().getLevel());
opInfo.setAttackerEntity(attackerEntity);
// 在Session中保存战斗信息
player.getSession().setAttribute(ONLINE_PVP_SESSION_KEY, opInfo);
Player otherPlayer = SessionUtils.getPlayer(otherSession);
// 通知对方邀请信息
JSONObject result = new JSONObject();
result.put("id", packet.getId());
result.put("opid", opid);
result.put("name", otherPlayer.getRole().getName());
otherSession.write(Namespaces.OPVP_INVITED, result);
}
// accept 接受对战
public void accept(SingleValue packet) {
// 发送好友列表信息
String opid = (String) packet.getVal();
OnlinePvpWarInfo opInfo = onlinePvpWarInfos.get(opid);
if (opInfo == null) {
return;
}
Session otherSession = sessionManager.getSession(opInfo.getAttackerEntity().getRid());
if (SessionUtils.isSessionAvailable(otherSession)) {
Packet result = Packet.createResult(packet);
result.setNs(Namespaces.OPVP_ACCEPTED);
otherSession.write(result);
}
Player player = SessionUtils.getPlayer();
// 设置防御方基本信息
WarInfo.Entity defenderEntity = new WarInfo.Entity(Direction.N);
defenderEntity.setRid(player.getRole().getRid());
defenderEntity.setRoleName(player.getRole().getName());
defenderEntity.setLevel(player.getRole().getLevel());
opInfo.setDefenderEntity(defenderEntity);
// 在Session中保存战斗信息
player.getSession().setAttribute(ONLINE_PVP_SESSION_KEY, opInfo);
}
/**
*
* @param packet
*/
public void reject(SingleValue packet) {
String opid = (String) packet.getVal();
OnlinePvpWarInfo opInfo = onlinePvpWarInfos.remove(opid);
if (opInfo != null) {
Session otherSession = sessionManager.getSession(opInfo.getAttackerEntity().getRid());
if (SessionUtils.isSessionAvailable(otherSession)) {
otherSession.removeAttribute(ONLINE_PVP_SESSION_KEY);
Packet result = Packet.createResult(packet);
result.setNs(Namespaces.OPVP_REJECTED);
otherSession.write(result);
}
}
}
/**
*
* @param packet
*/
public void prepare(OnlinePvpPacket packet) {
Player player = SessionUtils.getPlayer();
OnlinePvpWarInfo onlinePvpWarInfo = onlinePvpWarInfos.get(packet.getOpid());
initWarInfoEntity(getWarInfoEntity(player, onlinePvpWarInfo), player, packet);
// 开战
if (onlinePvpWarInfo.getAttackerEntity() != null
&& onlinePvpWarInfo.getDefenderEntity() != null) {
warProvider.prepare(onlinePvpWarInfo);
sendRival(onlinePvpWarInfo.getAttackerEntity().getRid(),
onlinePvpWarInfo.getDefenderEntity());
sendRival(onlinePvpWarInfo.getDefenderEntity().getRid(),
onlinePvpWarInfo.getAttackerEntity());
sendReady(packet, onlinePvpWarInfo);
}
}
// attack 攻击
public void attack(AttackPacket packet) {
// Player player = SessionUtils.getPlayer();
//
// // 判断是哪个方向的人
// OnlinePvpWarInfo opWarInfo = (OnlinePvpWarInfo) player.getSession().getAttribute(
// ONLINE_PVP_SESSION_KEY);
//
// // 计算战斗返回结果集
// List<Object> details = new ArrayList<>();
//// WarReport.Effect effect = warProvider.attack(packet.getHoldPoints(), opWarInfo,
//// getWarInfoEntity(player, opWarInfo).getDire(), details);
//
// // 战斗结果
// SingleValue result = SingleValue.createResult(packet, details);
// String str = JSON.toJSONString(result);
//
// sendAttack(opWarInfo.getAttackerEntity(), str);
// sendAttack(opWarInfo.getDefenderEntity(), str);
//
// switch (effect) {
// case W:
// break;
// case D:
// break;
// default:
// // 通知下一次攻击方
// }
}
private WarInfo.Entity getWarInfoEntity(Player player, OnlinePvpWarInfo onlinePvpWarInfo) {
int rid = player.getRole().getRid();
if (rid == onlinePvpWarInfo.getAttackerEntity().getRid()) {
return onlinePvpWarInfo.getAttackerEntity();
} else if (rid == onlinePvpWarInfo.getDefenderEntity().getRid()) {
return onlinePvpWarInfo.getDefenderEntity();
} else {
// FIXME 修改异常处理
throw new RuntimeException();
}
}
private boolean sendAttack(WarInfo.Entity entity, String str) {
Session session = sessionManager.getSession(entity.getRid());
if (!SessionUtils.isSessionAvailable(session)) {
return false;
}
session.write(Namespaces.OPVP_ATTACK, str);
return true;
}
private boolean sendRival(int sid, WarInfo.Entity entity) {
Session session = sessionManager.getSession(sid);
if (!SessionUtils.isSessionAvailable(session)) {
return false;
}
String str = JSON.toJSONString(warProvider.newWarReportEntity(entity));
session.write(Namespaces.OPVP_RIVAL, str);
return true;
}
private boolean sendReady(Packet packet, OnlinePvpWarInfo onlinePvpWarInfo) {
Session otherSession;
switch (onlinePvpWarInfo.getNextDire()) {
case S:
otherSession = sessionManager.getSession(onlinePvpWarInfo.getAttackerEntity().getRid());
break;
default:
otherSession = sessionManager.getSession(onlinePvpWarInfo.getDefenderEntity().getRid());
}
if (!SessionUtils.isSessionAvailable(otherSession)) {
return false;
}
Packet result = Packet.createResult(packet);
result.setNs(Namespaces.OPVP_READY);
otherSession.write(result);
return true;
}
private void initWarInfoEntity(WarInfo.Entity entity, Player player, OnlinePvpPacket packet) {
// Normal normal = player.getNormal();
// FightGroup fightGroup = normal.getFightGroup(packet.getGidx());
// List<FightObject> fightObjects = new ArrayList<>();
//
// Troop troop;
// HeroItem hero;
// for (int i = 0; i < fightGroup.getHeroItems().length; i++) {
// hero = fightGroup.getHeroItem(i);
// troop = warProvider.getTroop(normal, i);
// fightObjects.add(warProvider.newFightObject(i, troop, hero));
// }
//
// entity.setFightObjects(fightObjects);
// entity.setSuccor(warProvider.loadSuccorFightObject(packet.getSuccorRid(), packet.getSuccorIid(),
// fightObjects.get(FightGroup.PRIMARY_POS)));
}
private String generateId() {
int seq = OP_ID_SEQ.incrementAndGet();
OP_ID_SEQ.compareAndSet(Integer.MAX_VALUE, 0);
return Integer.toHexString(seq);
}
/**
*
*/
private static class OnlinePvpWarInfo extends WarInfo {
String opid;
long lastAccessedTime = System.currentTimeMillis();
OnlinePvpWarInfo(String opid) {
this.opid = opid;
}
long updateLastAccessTime() {
lastAccessedTime = System.currentTimeMillis();
return lastAccessedTime;
}
}
}