帮派作为大功能模块之一,其中承载了相当多的玩法和养成内容
目录
帮派
一:创建帮派
1.前端发起协议
// 创建帮派
message CSGuildCreate{
required string name = 1; // 帮派名称
required string notice = 2; // 帮派宣言
required int32 label = 3; // 帮派标签
}
/**
* 创建帮派
*
* @param name 帮派名字
* @param notice 帮派宣言
* @param label 标签
*/
public void guildCreate(String name, String notice, int label)
{
...
...
玩家等级校验
帮派名字长度校验
宣言长度校验
// 校验屏蔽字,字符串长度,检查并扣除消耗,有问题直接给客户端飘错
if (ChatUtils.containsName(name))
{
// 帮派名字中含有屏蔽字
sendError(BPErrorCodeEnum.GUILD_NAME_HAVE_SENSITIVE_WORD);
return;
}
if (ChatUtils.containsName(notice))
{
// 帮派宣言中含有屏蔽字
sendError(BPErrorCodeEnum.GUILD_NOTICE_HAVE_SENSITIVE_WORD);
return;
}
if (StringUtils.isPureDigital(name))
{
// 帮派名字不能是纯数字
sendError(BPErrorCodeEnum.GUILD_NAME_NOT_ALL_NUMBER);
return;
}
玩家货币消耗校验
校验成功,发送世界
...
...
}
分析:校验成功,发送世界创建帮派。 特别注意这里的屏蔽字校验和是否纯数字的方法, 有时间需要单独细看,屏蔽字校验调用的是聊天接口采用的AC过滤算法。
2.世界帮派创建
/**
* 创建帮派
*
* @param actorID 玩家id
* @param name 帮派名字
* @param notice 帮派宣言
* @param label 帮派标签
* @param showParts 外显部件组
*/
public void guildCreate(long actorID, String name, String notice, int label, int[] showParts)
{
...
...
从世界缓存里,判断当前创建玩家是否已经有帮派
校验本服帮派数量是否满
迭代全服所有帮派数据判断帮派名是否重复
获取帮派序列id
激活一个新的帮派场景
构建帮派基本数据到世界内存
通知帮派场景初始化
添加帮派建筑数据
添加初始帮派基金
计算所有帮派装备总评分
添加帮派创建事件
添加到帮派成员列表
给scene发消息,发给创建玩家
添加到排行榜
}
3.激活一个新的帮派场景
/**
* 激活一个新的帮派场景并返回线id
* @return
*/
public int activeNewGuildSceneline()
{
return activeSceneline(DictSceneDefineData.guildSceneId);
}
/** 激活新场景 */
public int activeSceneline(int sceneID)
{
SceneContainer sceneContainer = allSceneMap.get(sceneID);
if (sceneContainer == null)
{
BPLog.BP_SCENE.warn("no sceneID create, id:{}", sceneID);
return BPErrorCodeEnum.SCENE_NO_SCENE_ID_BE_CREATED;
}
return activeNewSceneline(sceneContainer);
}
/**
* 激活一个新的场景线路,激活,并执行
* @param container
* @return 激活的线id
*/
private int activeNewSceneline(SceneContainer container)
{
//按照顺序,激活一个场景线,取一个SceneUnit就直接return返回了
SceneUnit sceneUnit = container.activeNewSceneLine();
if (sceneUnit == null)
{
return BPErrorCodeEnum.SCENE_LINE_IS_FULL;
}
// 单一派发
if (container.getSceneStructType() == SceneStructTypeEnum.SINGLE)
{
//service派发给processor池执行
runNewSceneLine(sceneUnit);
}
}
分析:帮派是同一个场景,如果有新的帮派创建只是激活一个新的线。
4.通知帮派场景初始化
从世界下发消息到场景初始化帮派基本数据
/**
* 帮派场景初始化
*
* @param message 帮派信息
*/
public void guildSceneInit(BPWSGuildSceneInit message)
{
if (dissolutionState)
{
return;
}
this.guildId = message.getGuildId();
this.guildName = message.getGuildName();
this.lastClearActorTime = 0;
this.leaderShowData = message.getLeaderShowData();
this.actorMaxLevel = message.getActorMaxLevel();
}
5.添加帮派建筑数据
// 添加帮派建筑数据,迭代枚举
for (GuildBuildEnum guildBuildEnum : GuildBuildEnum.values())
{
int buildId = guildBuildEnum.getValue();
WorldGuildBuildData guildBuildData = new WorldGuildBuildData();
guildBuildData.setBuildId(buildId);
// 创建初始,结义堂等级为1级,其他建筑等级为0级
if (buildId == GuildBuildEnum.JIE_YI_TANG.getValue())
{
guildBuildData.setBuildLevel(BPGuildConst.GUILD_INIT_LEVEL);
}
else
{
guildBuildData.setBuildLevel(0);
}
guildData.getBuildDataMap().put(buildId, guildBuildData);
}
分析:迭代建筑枚举类,结义堂等级为1级,其他建筑等级为0级,数据存放在世界线程。
6.推送帮派信息变化时需要特别注意玩家是否在线
/**
* 给玩家发送帮派信息
*
* @param actorId 玩家id
* @param pbGuildData 帮派id
*/
private void guildBaseInfoNotice(long actorId, BPStruct.PBGuildData pbGuildData)
{
if (!getWorldService().playerIsOnline(actorId))
{
return;
}
BPWSGuildBaseInfoNotice message = new BPWSGuildBaseInfoNotice(MessageIDConst.WS_GUILD_BASE_INFO_NOTICE, actorId);
message.setPbGuildData(pbGuildData);
sendMessageToActor(actorId, message);
}
/**
* 发送消息给指定actor所在的场景
* @param actorID
* @param message
*/
public void sendMessageToActor(long actorID, AbstractServiceMessage message)
{
BPActorSceneMessage sceneMessage = new BPActorSceneMessage(actorID, message);
//如果玩家此时不在线了,通过玩家id从world上的场景管理器拿到scene为null,就会报警告
AbstractBPScene scene = sceneManager.getSceneByActorID(actorID);
if (scene != null)
{
sendMessage(scene, sceneMessage);
}
else
{
BPLog.BP_SYSTEM.warn("sendMessageToActor:{}, actor not in the scene, msg:{}", actorID, message);
}
}
从世界线程发送消息到场景玩家,一定要注意判断玩家是否在线,否则会报警告错误。
例如,帮派这种因为帮派建筑物变化就需要通知本帮派所有成员,这就避免不了,有些成员肯定不在线,
所以就要通知在线的成员,在通知的时候需要判断成员是否在线。
类比,时间排行榜奖励称号玩家也有可能不在线的情况。
7.添加帮派创建事件
/**
* 给全帮所有在线玩家推送事件数据到scene上的帮派模块
*
* @param guildData 帮派数据
*/
private void guildEventInfoNoticeToAllMember(WorldGuildData guildData)
{
ArrayList<WorldGuildEventData> eventList = new ArrayList<>();
for (int i = 0, size = guildData.getEventDataList().size(); i < size; i++)
{
// todo todo 重新new事件对象,防止在scene上误改数据影响world
eventList.add(guildData.getEventDataList().get(i).clone());
}
guildData.setTempToSceneEventList(eventList);
TLongObjectIterator<WorldGuildMemberData> iterator = guildData.getMemberDataMap().iterator();
while (iterator.hasNext())
{
iterator.advance();
long toActorId = iterator.value().getActorId();
if (!getWorldService().playerIsOnline(toActorId))
{
continue;
}
BPWSGuildEventInfoNotice eventInfoNotice = new BPWSGuildEventInfoNotice(MessageIDConst.WS_GUILD_EVENT_INFO_NOTICE, toActorId);
eventInfoNotice.setEventList(eventList);
sendMessageToActor(toActorId, eventInfoNotice);
}
}
分析:这里一定不要直接把地址从世界传到场景上,防止场景上会根据地址直接影响world上数据。
二:创建帮派
校验是否纯数字
1.采用java正则表达式
引入java.util.regex.Pattern包
public class StringUtils
{
private static final Pattern PURE_DIGITAL_PATTERN = Pattern.compile("[0-9]*");
/**
* 判断字符串是否是纯数字
*
* @param value 要检验的字符串
* @return true:纯数字 false:否
*/
public static boolean isPureDigital(String value)
{
return PURE_DIGITAL_PATTERN.matcher(value).matches();
}
}