前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >跨服夺矿战——java游戏服务器功能

跨服夺矿战——java游戏服务器功能

作者头像
深雾
发布2020-07-10 10:37:11
1.3K1
发布2020-07-10 10:37:11
举报
文章被收录于专栏:工具类工具类

开头

以前开发的游戏活动,在普通的游戏活动上添加了跨服玩法,需要用到世界服务器中转,提供思路给大家参考

功能

简单介绍就是以帮会为组织的攻城类玩法,首先对服务器进行分组,每组的服务器玩家共同开采矿产,互相争夺矿产主权

1、主要数据结构

代码语言:javascript
复制
public class MineGamer {
	/**
	 * 跨服国战分组id
	 */
	private int groupId;
	/**
	 * 区服标志
	 */
	private int serverType;
	/**
	 * 服务器ID
	 */
	private int serverId;
	/**
	 * 源服务器ID
	 */
	private int sourceId;
	/**
	 * 玩家ID
	 */
	private long gamerId;
	/**
	 * 工会ID
	 */
	private long armyId;
	/**
	 * 昵称
	 */
	private String nickName;
	/**
	 * 头像
	 */
	private String avatar;
	/**
	 * 战力
	 */
	private long power;
	/**
	 * 等级
	 */
	private int level;

玩家实体类,主要是服务器和展示信息。

代码语言:javascript
复制
public class WorldMineSimpleDto {
	/**
	 * 矿ID
	 */
	private int mineId;

	/**
	 * 矿区
	 */
	private int page;

	/**
	 * 矿类型
	 */
	private int type;
	/**
	 * 矿级别
	 */
	private int level;
	/**
	 * 天降宝箱状态
	 */
	private int boxActive;
	/**
	 * 天降宝箱id
	 */
	private int exboxId;
	/**
	 * 占领时间  小于10min为保护状态
	 */
	private long occupeTime;
	/**
	 * 预计占领结束时间
	 */
	private long occupeEndTime;
	/**
	 * 领取宝箱状态
	 */
	private List<Integer> boxReward;
	/**
	 * 玩家信息
	 */
	private MineGamer mineGamer;

矿产实体类,为矿产分区占领等信息,其余类怪物npc,活动状态及时间,玩家占领等信息都比较少。

2、活动管理

跨服功能的主要重心都在世界服,主要处理和保存活动信息

活动分组管理:初始读取夺矿战分组配置表

代码语言:javascript
复制
public class CrossMineGroupService extends ConfigServiceAdapter {
	private static Map<Integer, SeizeMineGroupServerConfig> CONFIG_MAPS = new HashMap<>();

	@Override
	public void clear() {
		CONFIG_MAPS.clear();
	}

	@Override
	public void initialize() {
		Collection<SeizeMineGroupServerConfig> list = dataConfig.listAll(this, SeizeMineGroupServerConfig.class);
		for (SeizeMineGroupServerConfig cfg : list) {
			CONFIG_MAPS.put(cfg.getId(), cfg);
		}
	}

	public static SeizeMineGroupServerConfig get(int id) {
		return CONFIG_MAPS.get(id);
	}

	public static SeizeMineGroupServerConfig get(int serverId, int serverType) {
		Collection<SeizeMineGroupServerConfig> groupServerConfigList = getCrossBattleGroupServerList();
		for (SeizeMineGroupServerConfig groupServerConfig : groupServerConfigList) {
			Set<ServerStruct> serverStructs = groupServerConfig.getServerStructs();
			for (ServerStruct serverStruct : serverStructs) {
				if (serverStruct.getServerId() == serverId && serverStruct.getServerType() == serverType) {
					return groupServerConfig;
				}
			}
		}
		return null;
	}

/**
 * 服务器简单结构
 * @author CharonWang
 *
 */
public class ServerStruct {
	/**
	 * 服务器类型
	 */
	private int serverType;
	/**
	 * 服务器ID
	 */
	private int serverId;

	public static ServerStruct valueOf(int serverType, int serverId) {
		ServerStruct model = new ServerStruct();
		model.serverType = serverType;
		model.serverId = serverId;
		return model;
	}

//矿产分组表
@DataFile(fileName = "seize_mine_groups_server_config")
public class SeizeMineGroupServerConfig implements ModelAdapter {
	/**
	 * 组ID
	 */
	private int id;
	/**
	 * 服务器列表
	 */
	private String servers;
	/**
	 * 组名称
	 */
	private String name;

	@FieldIgnore
	private Set<ServerStruct> serverStructs = new HashSet<>();

	@Override
	public void initialize() {
		List<String> serverList = JSONObject.parseArray(servers, String.class);
		for (String server : serverList) {
			String[] strArray = server.split("-");
			serverStructs.add(ServerStruct.valueOf(Integer.valueOf(strArray[0]), Integer.valueOf(strArray[1])));
		}
	}

活动时间管理

代码语言:javascript
复制
/**
 * 跨服夺矿战信息
 * @author aurora
 *
 */
public class MineEntity extends RedisEntity {
	
	/**
	 * 状态
	 */
	private int state;
	/**
	 * 状态结束时间
	 */
	private long stateEndTime;

根据配置的活动时间,定时器控制活动状态,具体方法代码如下,战斗功能不是写我的也比较长最后再贴,其余的就是基本的增删改查

代码语言:javascript
复制
@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		mineEntity = mineDao.get();
		if (mineEntity.getState() == 0) {
			mineEntity.setStateEndTime(System.currentTimeMillis());
			mineEntity.setState(MineState.PREPARE.getId());
			mineDao.update(mineEntity);
		}
		mineWorldDao.initMineWorld(mineEntity.getState());
		schedule.addEverySecond(new Runnable() {
			@Override
			public void run() {
				processMineState();
			}
		}, 5);
	}

// 跨服夺矿战战状态处理
	@SuppressWarnings("incomplete-switch")
	private void processMineState() {
		MineState state = MineState.getState(mineEntity.getState());
		if (state != MineState.PREPARE) {
			isfreshMine();
		}
		if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
			return;
		}
		switch (state) {
		case MESSPLAY:
			if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
				return;
			}
			// 发送宝箱倒计时
			processMineBox();
			// 更新时间,延长30min
			mineEntity.setStateEndTime(mineEntity.getStateEndTime() + 30 * 60 * 1000);
			mineEntity.setState(MineState.SENDREWARD.getId());
			mineDao.update(mineEntity);
			break;
		case SENDREWARD:
			if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
				return;
			}
			// 发送邮件宝箱
			sendMineBoxReward();
			// 更新发宝箱的时间
			mineEntity.setStateEndTime(getBoxTime());
			mineEntity.setState(WarState.MESSPLAY.getId());
			mineDao.update(mineEntity);
			break;
		case PREPARE:
			clean();
			initMine();
			// 初始化发宝箱时间
			mineEntity.setStateEndTime(getBoxTime());
			mineEntity.setState(MineState.MESSPLAY.getId());
			mineDao.update(mineEntity);
			break;
		}
	}
代码语言:javascript
复制
	private void isfreshMine() {
		Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
		for (Integer groupId : allGroupIds) {
			List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
			for (MineWorldPlayerEntity mineWorld : mineList) {
				if (mineWorld == null) {
					LOGGER.error("mineWorld can't find groupId:{}", groupId);
					continue;
				}
				// 判断是否为有主高级矿 占领时间已过
				if (mineWorld != null && mineWorld.getOccuperId() != 0) {
					if (System.currentTimeMillis() >= mineWorld.getOccupeEndTime()) {
						boolean settleReward = settleReward(mineWorld, 1);
						if (settleReward) {
							mineWorld.initi();
							mineWorldDao.update(mineWorld);
						}
					}
				}
			}
		}
	}

	private long getBoxTime() {
		long boxtime1 = TimeUtils.getTodayFixTime(12);
		long boxtime2 = TimeUtils.getTodayFixTime(21);
		long timeMillis = System.currentTimeMillis();
		if (timeMillis <= boxtime1) {
			timeMillis = boxtime1;
		} else if (timeMillis > boxtime1 && timeMillis <= boxtime2) {
			timeMillis = boxtime2;
		} else {
			// 设置为第二天12点
			timeMillis = boxtime1 + 24 * 60 * 60 * 1000;
		}
		return timeMillis;
	}

	// 跨服国夺矿战宝箱发送倒计时
	private void processMineBox() {
		Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
		for (Integer groupId : allGroupIds) {
			List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
			for (MineWorldPlayerEntity mineWorld : mineList) {
				if (mineWorld == null) {
					LOGGER.error("mineWorld can't find groupId:{}", groupId);
					continue;
				}
				SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineWorld.getMineId());
				// 判断是否为有主高级矿 是激活&& mineConfig.getMineType() == 2
				if (mineWorld.getOccuperId() != 0) {
					if (!mineConfig.getExBox().isEmpty() && mineConfig.getExBoxId() > 0) {
						mineWorld.setBoxActive(1);
						mineWorld.setExboxId(mineConfig.getExBoxId());
						mineWorldDao.update(mineWorld);
					}
				}
			}
		}
	}

	// 跨服国夺矿战宝箱处理
	private void sendMineBoxReward() {
		Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
		for (Integer groupId : allGroupIds) {
			List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
			for (MineWorldPlayerEntity mineWorld : mineList) {
				if (mineWorld == null) {
					LOGGER.error("mineWorld can't find groupId:{}", groupId);
					continue;
				}
				// 判断是否为已激活有主矿
				if (mineWorld.getBoxActive() == 1) {
					// 发放奖励
					int exboxId = mineWorld.getExboxId();
					mineWorld.setBoxActive(0);
					mineWorld.setExboxId(0);
					mineWorldDao.update(mineWorld);
					if (mineWorld.getOccuperId() != 0) {
						SeizeMineExboxConfig exboxConfig = MineExBoxConfigService.getMineConfig(exboxId);
						if (exboxConfig != null && exboxConfig.getRewards() != null) {
							sendExBoxReward(mineWorld, exboxConfig.getRewards());
						}
					}

				}
			}
		}
	}

	/**
	 * 初始化矿类
	 */
	private void initMine() {
		Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
		for (Integer groupId : allGroupIds) {
			Set<Integer> mineIds = MineWorldService.getMineId();
			for (Integer mineId : mineIds) {
				MineWorldPlayerEntity mineEntiy = MineWorldPlayerEntity.valueof(groupId, mineId, MineWorldService.getMineConfig(mineId).getPage(),
						MineWorldService.getBattleMonster(mineId));
				mineWorldDao.update(mineEntiy);
			}
		}
	}

	/**
	 * 清理夺矿战上期数据
	 */
	public void clean() {
		if (mineEntity.getState() != WarState.PREPARE.getId()) {
			return;
		}
		Collection<Integer> allGroupIds = CrossWarGroupServerService.allGroupIds();
		for (Integer groupId : allGroupIds) {
			mineWorldDao.cleanMine(groupId);
		}
		mineWorldDao.cleanMap();
	}

3、游戏功能

夺矿玩法分为游戏服和世界服,游戏服主要是储存玩家数据,和客户端对接协议,和世界服信息交互。

查询矿产一套流程代码

代码语言:javascript
复制
	/**
	 * 一键搜索剩余矿区信息   
	 * 
	 * @param object
	 * @return
	 */
	@RequestMapping(value = "/queryMineList", method = RequestMethod.POST)
	public @ResponseBody GaloshesJsonResultProtocol queryMineList(@RequestBody JSONObject object) {

		return handle(object, new HandlerResultCallBack<Object>() {
			@Override
			public Object call(Long gamerId, JSONObject object) throws Exception {
				MineTypeListDto queryMineList = mineFacade.queryMineList(gamerId);
				return queryMineList;
			}
		});
	}


    public MineTypeListDto queryMineList(Long gamerId) {
		JSONObject param = new JSONObject();
		param.put("gamerId", gamerId);
		MineTypeListDto queryDto = worldService.obtainTCrossBattle(param, "mine/queryMineList", MineTypeListDto.class);
		return queryDto;
	}

与世界服建立连接,后面的新项目使用了RPC协议会比现在舒服很多

代码语言:javascript
复制
@Component
public class WorldService implements GameInit {

	public final static String WORLD_CONTEXT_NAME = "domain-world";

	public final static String REGIST_URI = "system/regist";
	public final static String FORWARD_URI = "system/forward";

	public List<WorldRankInfo> pagodaRanks = Lists.newCopyOnWriteArrayList();

	private static final Logger LOGGER = LoggerFactory.getLogger(WorldService.class);
	@Autowired
	private IHttpClient httpClient;
	@Value("${server.worldUrl}")
	private String worldUrl;
	@Value("${server.worldEnable}")
	private boolean worldEnable = false;
	@Value("${server.flag}")
	public String serverType;
	@Autowired
	@Qualifier("serverId")
	public int serverId;
	@Value("${server.compose}")
	private String compose;

	public boolean registToWord() {
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("serverId", serverId);
		jsonObject.put("port", 30000 + serverId);
		jsonObject.put("serverType", serverType);
		jsonObject.put("composeIds", compose);
		try {
			String res = httpClient.sendPost(getPath(REGIST_URI), jsonObject.toJSONString(), "application/json");
			if (res == null) {
				return false;
			}
			JsonResultProtocol jsonResultProtocol = JSON.parseObject(res, JsonResultProtocol.class);
			if (jsonResultProtocol.getResult() == ResultCode.SUCCESS.getCode()) {
				return true;
			}
			return false;

		} catch (Exception e) {
			LOGGER.error("{}", e);
			return false;
		}
	}

	/**
	 * 从世界服获取消息
	 *
	 * @param jsonObject 数据
	 * @param path       绝对路径,以下划线开头
	 * @return
	 * @return
	 */
	public <T> T obtainTCrossBattle(JSONObject jsonObject, String path, Class<T> tClazz) {

		if (path == null || path.isEmpty()) {
			throw new RuntimeException("path is null!!!!!");
		}
		try {
			String fullUrl = getPath(path);
			jsonObject.put("serverId", serverId);
			jsonObject.put("serverType", serverType);
			String res = httpClient.sendPost(fullUrl, jsonObject.toJSONString(), "application/json");
			if (res == null) {
				throw new CrossBattleRemoteDataException();
			}
			JsonResultProtocol parseObject = JSON.parseObject(res, JsonResultProtocol.class);
			if (parseObject.getMessage() == null || "".equals(parseObject.getMessage())) {
				throw new CrossBattleRemoteDataException();
			}
			return JSON.parseObject(parseObject.getMessage().toString(), tClazz);

		} catch (Exception e) {
			LOGGER.error("{}", e);
			throw new CrossBattleRemoteDataException();
		}
	}

世界服用的redis数据库,主要保存矿产数据,处理玩家间的信息。

代码语言:javascript
复制
	/**
	 * 一键搜索剩余矿区信息
	 * 
	 * @param object
	 * @return
	 */
	@RequestMapping(value = "/queryMineList", method = RequestMethod.POST)
	@ResponseBody
	public JsonResultProtocol queryMineList(@RequestBody JSONObject object) {
		JsonResultProtocol jsonResultProtocol = new JsonResultProtocol();
		try {
			int serverType = object.getIntValue("serverType");
			int serverId = object.getIntValue("serverId");
			MineTypeListDto dto = mineFacade.queryMineList(serverId, serverType);
			jsonResultProtocol.setup(ResultCode.SUCCESS.getCode(), JSON.toJSONString(dto));
		} catch (Exception e) {
			LOGGER.error("{}", e);
			jsonResultProtocol.setup(ResultCode.SERVER_ERROR.getCode());
		}
		return jsonResultProtocol;
	}

/**
	 * 获取矿区矿产信息
	 */
	public MineTypeListDto queryMineList(int serverId, int serverType) {
		List<WorldMineSimpleDto> mineSimpleDtoList = Lists.newArrayList();
		int groupId = CrossMineGroupService.getGroupId(serverId, serverType);
		if (groupId <= 0) {
			LOGGER.error("CrossMine can't find groupId, serverId:{}, serverType:{}", serverId, serverType);
			return null;
		}
		List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
		// 记录剩余矿区信息
		for (MineWorldPlayerEntity mineWorldPlayerEntity : mineList) {
			if (mineWorldPlayerEntity.getOccuperId() != 0) {
				continue;
			}
			int idpage = mineWorldPlayerEntity.getPage();
			int mineId = mineWorldPlayerEntity.getMineId();
			SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineId);
			WorldMineSimpleDto mineSimple = WorldMineSimpleDto.valueOf(mineId, idpage, mineConfig.getMineType(), mineConfig.getMineLevel(),
					mineWorldPlayerEntity.getMineGamer());
			mineSimple.setOccupeTime(mineWorldPlayerEntity.getOccupeTime());
			mineSimple.setOccupeEndTime(mineWorldPlayerEntity.getOccupeEndTime());
			if (mineConfig.getMineType() == 2) {
				// 高级矿信息储存
				mineSimple.setBoxActive(mineWorldPlayerEntity.getBoxActive());
			}
			mineSimpleDtoList.add(mineSimple);
		}
		return MineTypeListDto.valueOf(mineSimpleDtoList);
	}

主要流程就是这样,当初做的比较匆忙,现在回想还是有很多可以优化的地方,也给大家写功能的时候参考

4.跨服战斗

获取矿产占领者的id进入战斗,击败对方则更新占领城池广播,如果对手是玩家,通知对手加入仇人信息

代码语言:javascript
复制
// 获取矿产信息
		MineWorldPlayerEntity mineWorldPlayerEntity = mineWorldDao.get(groupId, mineId);
		SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineId);
		// 判断是否已经占领过矿
		List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
		for (MineWorldPlayerEntity minePlayerEntity : mineList) {
			if (minePlayerEntity.getOccuperId() == gamerId) {
				SeizeMineConfig gamerMine = MineWorldService.getMineConfig(minePlayerEntity.getMineId());
				if (gamerMine.getMineType() == mineConfig.getMineType()) {
					return null;
				}
			}
		}
		long protectTime = globalService.load(GlobalConfigKey.SEIZEMINEPROTECTTIME).findInt() * TimeConstant.ONE_MINUTE_MILLISECOND;
		if (mineConfig.getMineLevel() == 1) {
			// 如果当前未过保护时间 低级矿保护
			if (mineWorldPlayerEntity.getOccupeTime() + protectTime >= System.currentTimeMillis()) {
				return null;
			}
		}
		List<BattleRole> opponentBattleRoleList = Lists.newArrayList();
		WorldMinePlayResultDto playResultDto;
		if (mineWorldPlayerEntity.getOccuperId() == 0) {
			// 对手怪物信息
			opponentBattleRoleList = MineWorldService.getBattleRole(mineId);
			LinkedList<BattleRole> opponentBattleRoles = Lists.newLinkedList();
			for (BattleRole battleRole : opponentBattleRoleList) {
				BattleRole copyBattleRole = new BattleRole(battleRole.getRoleId(), battleRole.getBelong(), battleRole.getVocation(),
						battleRole.getBattleAttr().copy(), battleRole.getTotalAttr().copy(), battleRole.getBattleSkillAttrs());
				opponentBattleRoles.add(copyBattleRole);
			}
			LinkedList<BattleRole> challengeBattleRoles = worldMinePlayDto.getChallengeBattleRoles();
			for (BattleRole battleRole : challengeBattleRoles) {
				battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
			}
			BattleFight battleFight = new BattleFight(gamerId, mineId, challengeBattleRoles, opponentBattleRoles);
			BattleResult battleResult = battleMonitor.playBattle(battleFight, false, PlayType.NONE, null);
			playResultDto = WorldMinePlayResultDto.valueOf(battleResult, 1);
		} else {
			// 对手是玩家
			MineGamer mineGamersource = mineWorldPlayerEntity.getMineGamer();
			GamerBattleRoleDto battle = getBattle(mineGamersource.getServerType(), mineGamersource.getServerId(), mineGamersource.getGamerId());
			if (battle == null) {
				LOGGER.error("CrossMine can't getBattle Message, serverType:{}, serverId:{}", mineGamersource.getServerType(),
						mineGamersource.getServerId());
				return null;
			}
			LinkedList<BattleRole> challengeBattleRoles = worldMinePlayDto.getChallengeBattleRoles();
			for (BattleRole battleRole : challengeBattleRoles) {
				battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
			}
			BattleFight battleFight = new BattleFight(gamerId, mineGamersource.getGamerId(), challengeBattleRoles, battle.getChallengeBattleRoles());
			BattleResult battleResult = battleMonitor.playBattle(battleFight, PlayType.NONE, null);
			playResultDto = WorldMinePlayResultDto.valueOf(battleResult, battle.getPoints(), 2);
			// 更新玩家仇人信息
			mineGamer.setGroupId(groupId);
			saveOppend(mineGamersource, mineGamer, battleResult, mineId);
		}
		// 玩家胜利更新数据
		if (playResultDto.getWinner() == gamerId) {
			// 被攻击玩家结算奖励
			if (mineWorldPlayerEntity.getOccuperId() != 0) {
				boolean settleReward = settleReward(mineWorldPlayerEntity, 3);
				if (!settleReward) {
					return null;
				}
				mineWorldPlayerEntity.initi();
			}
			// 初始矿产占领时长
			long initialTime = globalService.load(GlobalConfigKey.SeizeMineInitialTime).findInt() * TimeConstant.ONE_MINUTE_MILLISECOND;
			mineWorldPlayerEntity.setOccuperId(gamerId);
			mineWorldPlayerEntity.setOccupeTime(System.currentTimeMillis());
			mineWorldPlayerEntity.setOccupeEndTime(mineWorldPlayerEntity.getOccupeTime() + initialTime);
			mineWorldPlayerEntity.setMineGamer(mineGamer);
			mineWorldDao.update(mineWorldPlayerEntity);
			// 记录消息类
			MineWorldMessageEntity messageEntity = MineWorldMessageEntity.valueof(groupId, mineId, mineGamer);
			List<MineWorldMessageEntity> mineMessageList = mineWorldMessageDao.getMineMessageList(groupId);
			// 储存最多30条
			if (mineMessageList.size() >= 30) {
				mineMessageList.remove(0);
			}
			mineMessageList.add(messageEntity);
			mineWorldMessageDao.saveMineMessageList(groupId, mineMessageList);
		}
		return playResultDto;
	}

发送信息到被攻击者服务器

代码语言:javascript
复制
/**
	 * 
	 * @param mineGamer
	 *            被攻打者信息
	 * @param oppendMineGamer
	 *            攻打记录的仇敌
	 * @param battleResult
	 * @param mineId
	 * @return
	 */

	private boolean saveOppend(MineGamer mineGamer, MineGamer oppendMineGamer, BattleResult battleResult, int mineId) {
		int serverId = mineGamer.getServerId();
		int serverType = mineGamer.getServerType();
		Server server = serverDao.getServer(serverId, serverType);
		if (server == null) {
			LOGGER.error("serizeMina saveOppend server not found, serverType:{},serverId:{}", serverType, serverId);
			return false;
		}
		String url = "http://" + server.getHost() + ":" + server.getPort() + "/" + PathConstant.GAME_CONTEXT_NAME + PathConstant.WORLD_OPPONENT_MINE;
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("mineGamer", mineGamer);
		jsonObject.put("oppendMineGamer", oppendMineGamer);
		jsonObject.put("battleResult", battleResult);
		jsonObject.put("mineId", mineId);
		String result = innerHttpClient.sendPost(url, jsonObject.toJSONString(), "application/json");
		if (StringUtils.isEmpty(result)) {
			LOGGER.error("serizeMina saveOppend http error, url:{},jsonObject:{}", url, jsonObject.toJSONString());
			return false;
		}
		JsonResultProtocol jsonResultProtocol = JSON.parseObject(result, JsonResultProtocol.class);
		if (jsonResultProtocol.getResult() != ResultCode.SUCCESS.getCode()) {
			LOGGER.error("serizeMina saveOppend result error, url:{},jsonObject:{},result:{}", url, jsonObject.toJSONString(),
					JSONObject.toJSONString(jsonResultProtocol));
			return false;
		}
		boolean istrue = JSONObject.parseObject(jsonResultProtocol.getMessage().toString(), boolean.class);
		return istrue;

	}

战斗类

代码语言:javascript
复制
public class BattleMonitor {

	@Resource
	private FightMonitor fightMonitor;

	public BattleResult playBattle(BattleFight battleFight, boolean copyAttr, PlayType playType, Object object) {
		if (copyAttr) {
			copyAttr(battleFight);
		}
		return play(battleFight, playType, object);
	}

	private void copyAttr(BattleFight battleFight) {
		LinkedList<BattleRole> challengeRoleAttrs = battleFight.getChallengeRoleAttrs();
		for (BattleRole battleRole : challengeRoleAttrs) {
			battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
		}
		LinkedList<BattleRole> opponentRoleAttrs = battleFight.getOpponentRoleAttrs();
		for (BattleRole battleRole : opponentRoleAttrs) {
			battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
		}
	}

	private BattleResult play(BattleFight battleFight, PlayType playType, Object object) {
		BattleResult battleResult = new BattleResult();
		Iterator<BattleRole> challengeRoles = battleFight.getChallengeRoleAttrs().iterator();
		Iterator<BattleRole> defenceRoles = battleFight.getOpponentRoleAttrs().iterator();

		BattleRole challengeRole = challengeRoles.next();
		while (challengeRoles.hasNext() && !challengeRole.hasAlive()) {
			challengeRole = challengeRoles.next();
		}
		BattleRole defenceRole = defenceRoles.next();
		while (defenceRoles.hasNext() && !defenceRole.hasAlive()) {
			defenceRole = defenceRoles.next();
		}
		boolean challengeFirst = true;
		boolean defenceFirst = true;
		long winner = 0;
		long last = 0;
		long lastLeftHp = 0;
		List<Long> left = Lists.newArrayList();
		for (;;) {
			FightResult fightResult = fightMonitor.fight(challengeRole, defenceRole, challengeFirst, defenceFirst, playType, object);
			battleResult.addReports(fightResult.getReports());
			if (fightResult.hasWinnerWas(challengeRole.getRoleId())) {
				if (!defenceRoles.hasNext()) {
					winner = battleFight.getChallenge();
					last = challengeRole.getRoleId();
					lastLeftHp = challengeRole.getTotalAttr().getHp();
					break;
				}
				defenceRole = defenceRoles.next();
				defenceFirst = true;
				challengeFirst = false;
				challengeRole.cleanAccumulateSpeed();
			} else {
				if (!challengeRoles.hasNext()) {
					winner = battleFight.getOpponent();
					last = defenceRole.getRoleId();
					lastLeftHp = defenceRole.getTotalAttr().getHp();
					break;
				}
				challengeRole = challengeRoles.next();
				challengeFirst = true;
				defenceFirst = false;
				defenceRole.cleanAccumulateSpeed();
			}
		}
		//win
		if (winner == battleFight.getChallenge()) {
			left.add(challengeRole.getRoleId());
			while (challengeRoles.hasNext()) {
				left.add(challengeRoles.next().getRoleId());
			}
		} else {
			left.add(defenceRole.getRoleId());
			while (defenceRoles.hasNext()) {
				left.add(defenceRoles.next().getRoleId());
			}
		}
		battleResult.win(winner, last, lastLeftHp, left);
		return battleResult;
	}

	public BattleResult playBattle(BattleFight battleFight, PlayType playType, Object object) {
		return playBattle(battleFight, true, playType, object);
	}

}


@Component
public class FightMonitor {

	@Resource
	private BaseAttackAct baseAttackAct;

	@Resource
	private BaseSkillAct baseSkillAct;

	@Resource
	private EffectAct effectAct;

	/**
	 * 判断谁先出手
	 * @param challengeRole
	 * @param opponentRole
	 * @param challengeFirst
	 * @param defenceFirst
	 * @return
	 */
	private boolean hasChallengeRoleActFirst(BattleRole challengeRole, BattleRole opponentRole, boolean challengeFirst, boolean defenceFirst) {
		if (challengeFirst) {
			if (defenceFirst) {
				if (challengeRole.getBattleAttr().getSpeed() > opponentRole.getBattleAttr().getSpeed()) {
					return true;
				}
			} else {
				return true;
			}
		}
		return false;
	}

	public FightResult fight(BattleRole challengeRole, BattleRole opponentRole, boolean challengeFirst, boolean defenceFirst, PlayType playType,
			Object object) {
		long winner = 0;
		List<RoundReport> reports = Lists.newArrayList();
		boolean firstAttack = hasChallengeRoleActFirst(challengeRole, opponentRole, challengeFirst, defenceFirst);
		BattleRole attackRole = null;
		BattleRole defenceRole = null;
		if (firstAttack) {
			attackRole = challengeRole;
			defenceRole = opponentRole;
		} else {
			defenceRole = challengeRole;
			attackRole = opponentRole;
			boolean challengeTemp = challengeFirst;
			challengeFirst = defenceFirst;
			defenceFirst = challengeTemp;
		}
		int attackRound = 1;
		int defenceRound = 1;
		for (;;) {
			if (!attackRole.hasAlive()) {
				winner = attackRole.getRoleId();
				break;
			}
			RoundReport roundReport = roundAttack(attackRole, defenceRole, challengeFirst, defenceFirst, attackRound, defenceRound, playType, object);
			challengeFirst = false;
			defenceFirst = false;
			reports.add(roundReport);
			if (!defenceRole.hasAlive()) {
				winner = attackRole.getRoleId();
				break;
			}
			if (!attackRole.hasAlive()) {
				winner = defenceRole.getRoleId();
				break;
			}
			BattleRole tempRole = attackRole;
			attackRole = defenceRole;
			defenceRole = tempRole;
			attackRound++;
			int tempRound = attackRound;
			attackRound = defenceRound;
			defenceRound = tempRound;
		}

		return new FightResult(winner, reports);
	}

	private RoundReport roundAttack(BattleRole attackRole, BattleRole defenceRole, boolean challengeFirst, boolean defenceFirst, int attackRound,
			int defenceRound, PlayType playType, Object object) {
		RoundReport roundReport = new RoundReport(attackRole.getRoleId(), attackRole.getBelong(), defenceRole.getRoleId());

		List<ActResult> bufferActs = effectAct.processEffect(attackRole);
		if (bufferActs.size() > 0) {
			roundReport.addActResults(bufferActs);
		}
		for (BattleSkillAttr battleSkillAttr : attackRole.getBattleSkillAttrs()) {
			//在battleSkillAttr中增加一个方法 用来使技率生效影响基本技能触发几率
			if (battleSkillAttr.canTriggerSkill(attackRound, attackRole.getTotalAttr().getSkillChance())) {

				ActResult result = baseSkillAct.act(battleSkillAttr, attackRole, defenceRole, challengeFirst, attackRound);
				roundReport.addActResult(result);
				break;
			}
		}
		// 判断战斗回合大于100,被攻击着输
		if (attackRound > 100) {
			if (defenceRole.getBattleAttr().getHp() > attackRole.getBattleAttr().getHp()) {
				attackRole.getBattleAttr().setHp(0);
			} else {
				defenceRole.getBattleAttr().setHp(0);
			}
		}
		List<ActResult> act = baseAttackAct.act(attackRole, defenceRole, challengeFirst, defenceFirst, playType, object);
		roundReport.addActResults(act);

		return roundReport;
	}
}

差不多就是这些,现在是用lua语言写起来简单很多,新接的战令功能根据开始时间和活动持续时间自行运转,看看夺矿战状态流程管理复习下,现在记性不行,要把以前学的都慢慢记录下来了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-06-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 开头
  • 功能
  • 1、主要数据结构
  • 2、活动管理
  • 3、游戏功能
  • 4.跨服战斗
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档