diff --git a/netty/src/main/java/com/ljsd/jieling/netty/handler/ChannelHandlerHolder.java b/netty/src/main/java/com/ljsd/jieling/netty/handler/ChannelHandlerHolder.java new file mode 100644 index 000000000..3f86f1bc9 --- /dev/null +++ b/netty/src/main/java/com/ljsd/jieling/netty/handler/ChannelHandlerHolder.java @@ -0,0 +1,8 @@ +package com.ljsd.jieling.netty.handler; + +import io.netty.channel.ChannelHandler; + +public interface ChannelHandlerHolder { + + public ChannelHandler[] handlers(); +} \ No newline at end of file diff --git a/netty/src/main/java/com/ljsd/jieling/netty/handler/ConnectionWatchdog.java b/netty/src/main/java/com/ljsd/jieling/netty/handler/ConnectionWatchdog.java new file mode 100644 index 000000000..1804552c4 --- /dev/null +++ b/netty/src/main/java/com/ljsd/jieling/netty/handler/ConnectionWatchdog.java @@ -0,0 +1,121 @@ +package com.ljsd.jieling.netty.handler; + +import com.ljsd.jieling.netty.server.SkyEyeClient; +import io.netty.bootstrap.Bootstrap; +import io.netty.buffer.ByteBuf; +import io.netty.channel.*; +import io.netty.channel.ChannelHandler; +import io.netty.util.Timeout; +import io.netty.util.Timer; +import io.netty.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import rpc.protocols.ChatProto; + +import java.util.concurrent.TimeUnit; + +@ChannelHandler.Sharable +public class ConnectionWatchdog extends ChannelInboundHandlerAdapter implements TimerTask,ChannelHandlerHolder{ + private static final Logger logger = LoggerFactory.getLogger(ConnectionWatchdog.class); + + private final Bootstrap bootstrap; + private final Timer timer; + private final int port; + + private final String host; + + private volatile boolean reconnect; + private int attempts = 0; + + public ConnectionWatchdog(Bootstrap bootstrap, Timer timer, int port, String host, boolean reconnect) { + this.bootstrap = bootstrap; + this.timer = timer; + this.port = port; + this.host = host; + this.reconnect = reconnect; + } + + /** + * channel链路每次active的时候,将其连接的次数重新☞ 0 + */ + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + logger.info("-------客户端上线----------"); + SkyEyeClient.channel = ctx.channel(); + + + logger.info("当前链路已经激活了,重连尝试次数重新置为0"); + attempts = 0; + ctx.fireChannelActive(); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + logger.info("-------客户端下线----------"); + boolean isChannelActive = true; + if (null == SkyEyeClient.channel || !SkyEyeClient.channel.isActive()) { + isChannelActive = false; + } + if (reconnect && true) { + logger.info("链接关闭,将进行重连"); + + if (attempts < 10) { + int timeout = 60; + timer.newTimeout(this, timeout, TimeUnit.SECONDS); + } + } else { + logger.info("链接关闭"); + } + } + + public void run(Timeout timeout) throws Exception { + + ChannelFuture future; + //bootstrap已经初始化好了,只需要将handler填入就可以了 + synchronized (bootstrap) { + bootstrap.handler(new ChannelInitializer() { + + @Override + protected void initChannel(Channel ch) throws Exception { + + ch.pipeline().addLast(handlers()); + } + }); + future = bootstrap.connect(host,port); + } + + //future对象监听 + future.addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture f) throws Exception { + boolean succeed = f.isSuccess(); + Channel channel=f.channel(); + if (!succeed) { + logger.info("重连失败"); + f.channel().pipeline().fireChannelInactive(); + }else{ + logger.info("重连成功"); + } + } + }); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + ByteBuf in = (ByteBuf)msg; + int length = in.readableBytes(); + if(length<=6){ + return; + } + byte[] b = new byte[length-6]; + in.readBytes(6); + for(int i =0;i() { + //初始化channel + @Override + protected void initChannel(Channel ch) throws Exception { + ch.pipeline().addLast(watchdog.handlers()); + } + }); + future = bootstrap.connect(host,port); + } + future.sync(); + +// f = bootstrap.connect(); +// f.addListener(new ConnectionListener()); + channel = future.channel(); +// channel.closeFuture().sync(); + } catch (Throwable t) { + LOGGER.error("客户端连接失败------------,ip为{},端口为{}",host,port); + if (null != future) { + try { + timer.newTimeout(watchdog,60, TimeUnit.SECONDS); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + }finally { +// group.shutdownGracefully(); + } + } + + public boolean invoke(Object request){ + try{ + if(check(channel)){ + channel.writeAndFlush(request); + return true;// 写消息 + }else{ + LOGGER.error("【天眼链接失败】由于远端的服务器不能提供服务!{}"); + return false; + } + } + catch(Exception e){ + LOGGER.error("【天眼链接失败】由于远端的服务器不能提供服务,或者本地连接耗尽!"); + } + return false; + } + + /** + * 检查channel健康状况 + * @param channel + * @return + */ + public boolean check(Channel channel) { + if (channel == null) { + return false; + } + if (!channel.isActive()) { + return false; + } + if (!channel.isWritable()) { + return false; + } + return true; + } + +} diff --git a/serverlogic/src/main/java/com/ljsd/GameApplication.java b/serverlogic/src/main/java/com/ljsd/GameApplication.java index 7370a9272..a859db0b5 100644 --- a/serverlogic/src/main/java/com/ljsd/GameApplication.java +++ b/serverlogic/src/main/java/com/ljsd/GameApplication.java @@ -56,7 +56,7 @@ public class GameApplication { setRegisterTime();// might loop GameLogicService.getInstance().onStart(); NetManager.getInstance().init(); - + SkyEyeService.getInstance().onStart(); //控制台gm Scanner sc = new Scanner(System.in); while(sc.hasNext()) diff --git a/serverlogic/src/main/java/com/ljsd/SkyEyeService.java b/serverlogic/src/main/java/com/ljsd/SkyEyeService.java new file mode 100644 index 000000000..995e92e15 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/SkyEyeService.java @@ -0,0 +1,45 @@ +package com.ljsd; + +import com.ljsd.jieling.netty.config.EndPortCfg; +import com.ljsd.jieling.netty.server.SkyEyeClient; +import com.ljsd.jieling.network.NettyProperties; +import com.ljsd.jieling.network.NettyServerAutoConfiguration; +import com.ljsd.jieling.network.server.SessionManager; +import com.ljsd.jieling.util.ConfigurableApplicationContextManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SkyEyeService implements IService { + + private static final Logger LOGGER = LoggerFactory.getLogger(GameLogicService.class); + private static SkyEyeService instance = new SkyEyeService(); + private static SkyEyeClient skyEyeClient = null; + + @Override + public void onStart() throws Exception { + final NettyServerAutoConfiguration netServerConfig = ConfigurableApplicationContextManager.getBean(NettyServerAutoConfiguration.class); + NettyProperties properties = netServerConfig.getNettyProperties(); + skyEyeClient = new SkyEyeClient(); + skyEyeClient.start(); + } + + @Override + public void init() throws Exception { + + } + + @Override + public void exit() throws Exception { + + } + + public static void sendMsg(Object obj){ + if(skyEyeClient != null){ + skyEyeClient.invoke(obj); + } + } + + public static SkyEyeService getInstance() { + return instance; + } +} diff --git a/serverlogic/src/main/java/com/ljsd/jieling/chat/logic/ChatLogic.java b/serverlogic/src/main/java/com/ljsd/jieling/chat/logic/ChatLogic.java index c42d67656..5b59fc2e1 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/chat/logic/ChatLogic.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/chat/logic/ChatLogic.java @@ -118,13 +118,17 @@ public class ChatLogic { User user = UserManager.getUser(uid); PlayerManager playerInfoManager = user.getPlayerInfoManager(); FriendManager friendManager = user.getFriendManager(); - + MessageUtil.sendSkyEyeMsg(message,user,friendId,chatType); long nowTime = System.currentTimeMillis(); String unSymbolWord = ShieldedWordUtils.replaceUnword(message); String tmp = SensitivewordFilter.replaceSensitiveWord(unSymbolWord, 1, "*"); - if(tmp.contains("*") && !tmp.equals(message)||playerInfoManager.getSilence()==1){ + boolean silence = false; + if(playerInfoManager.getSilence() == 1 || playerInfoManager.getSkyEyeBanTime()>System.currentTimeMillis()){ + silence = true; + } + if(tmp.contains("*") && !tmp.equals(message)||silence){ char[] chars = message.toCharArray(); char[] original = unSymbolWord.toCharArray(); char[] tmpChar = tmp.toCharArray(); @@ -237,7 +241,11 @@ public class ChatLogic { private void onSendChatSuccess(User user,int chatType,String message){ RedisUtil redisUtil = RedisUtil.getInstence(); String key = RedisKey.getKey(RedisKey.CHAT_INFO_CACHE, String.valueOf(chatType), false); - ChatRedisEntity chatRedisEntity = new ChatRedisEntity(user.getId(), user.getPlayerInfoManager().getNickName(), chatType, message, TimeUtils.now(), user.getPlayerInfoManager().getSilence()); + int silence = 0; + if(user.getPlayerInfoManager().getSilence() == 1 || user.getPlayerInfoManager().getSkyEyeBanTime()>System.currentTimeMillis()){ + silence = 1; + } + ChatRedisEntity chatRedisEntity = new ChatRedisEntity(user.getId(), user.getPlayerInfoManager().getNickName(), chatType, message, TimeUtils.now(), silence); String chatInfo = gson.toJson(chatRedisEntity); long l = redisUtil.lGetListSize(key); diff --git a/serverlogic/src/main/java/com/ljsd/jieling/handler/GetPlayerInfoHandler.java b/serverlogic/src/main/java/com/ljsd/jieling/handler/GetPlayerInfoHandler.java index 4f97f3561..d83690173 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/handler/GetPlayerInfoHandler.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/handler/GetPlayerInfoHandler.java @@ -70,7 +70,6 @@ public class GetPlayerInfoHandler extends BaseHandler{ PlayerManager playerInfoManager = user.getPlayerInfoManager(); ActivityLogic.getInstance().flushForLogin(user,iSession); GlobalDataManaager.checkNeedReFlush(iSession,user,null); - GuildLogic.sendWelfareRedPacketInfo(user); BuyGoodsNewLogic.refreshWelfareState(user); // Poster.getPoster().dispatchEvent(new UserOnlineEvent(userId)); user.getUserMissionManager().onGameEvent(user, GameEvent.LOGIN_GAME,0); diff --git a/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeye.java b/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeye.java new file mode 100644 index 000000000..a6328dfb9 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeye.java @@ -0,0 +1,17 @@ +package com.ljsd.jieling.kefu; + +import com.ljsd.jieling.logic.dao.PlayerManager; +import com.ljsd.jieling.logic.dao.root.User; +import util.TimeUtils; + +public class Cmd_skyeye extends GmRoleAbstract { + @Override + public boolean exec(String[] args) throws Exception { + User user = getUser(); + int min = Integer.valueOf(args[0]); + PlayerManager playerInfoManager = user.getPlayerInfoManager(); + //设置禁言 + playerInfoManager.setSkyEyeBanTime(System.currentTimeMillis()+ min * TimeUtils.ONE_MINUTE); + return true; + } +} diff --git a/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeyec.java b/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeyec.java new file mode 100644 index 000000000..c0ed5fb87 --- /dev/null +++ b/serverlogic/src/main/java/com/ljsd/jieling/kefu/Cmd_skyeyec.java @@ -0,0 +1,15 @@ +package com.ljsd.jieling.kefu; + +import com.ljsd.jieling.logic.dao.PlayerManager; +import com.ljsd.jieling.logic.dao.root.User; + +public class Cmd_skyeyec extends GmRoleAbstract { + @Override + public boolean exec(String[] args) throws Exception { + User user = getUser(); + PlayerManager playerInfoManager = user.getPlayerInfoManager(); + //设置禁言 + playerInfoManager.setSkyEyeBanTime(0); + return true; + } +} \ No newline at end of file diff --git a/serverlogic/src/main/java/com/ljsd/jieling/logic/dao/PlayerManager.java b/serverlogic/src/main/java/com/ljsd/jieling/logic/dao/PlayerManager.java index 9d88959e4..c2111342e 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/logic/dao/PlayerManager.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/logic/dao/PlayerManager.java @@ -155,6 +155,8 @@ public class PlayerManager extends MongoBase { private int dailyWelfareRedPacket; + private long skyEyeBanTime; + public PlayerManager(){ this.setRootCollection(User._COLLECTION_NAME); @@ -1075,4 +1077,13 @@ public class PlayerManager extends MongoBase { this.dailyWelfareRedPacket = dailyWelfareRedPacket; updateString("dailyWelfareRedPacket",dailyWelfareRedPacket); } + + public long getSkyEyeBanTime() { + return skyEyeBanTime; + } + + public void setSkyEyeBanTime(long skyEyeBanTime) { + this.skyEyeBanTime = skyEyeBanTime; + updateString("skyEyeBanTime",skyEyeBanTime); + } } diff --git a/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java b/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java index 775c184d0..2d4cb4afc 100644 --- a/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java +++ b/serverlogic/src/main/java/com/ljsd/jieling/util/MessageUtil.java @@ -1,9 +1,11 @@ package com.ljsd.jieling.util; import com.google.gson.Gson; +import com.google.protobuf.ByteString; import com.google.protobuf.GeneratedMessage; import com.googlecode.protobuf.format.JsonFormat; import com.ljsd.GameApplication; +import com.ljsd.SkyEyeService; import com.ljsd.jieling.chat.messge.MessageCache; import com.ljsd.jieling.core.GlobalsDef; import com.ljsd.jieling.core.SimpleTransaction; @@ -19,11 +21,15 @@ import com.ljsd.jieling.netty.PackageConstant; import com.ljsd.jieling.netty.cocdex.Tea; import com.ljsd.jieling.network.server.ProtocolsManager; import com.ljsd.jieling.network.session.ISession; +import com.sun.tools.javac.util.StringUtils; import config.SErrorCodeEerverConfig; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.ZSetOperations; import rpc.protocols.*; +import util.StringUtil; import java.util.*; @@ -73,6 +79,25 @@ public class MessageUtil { return bytes1; } + public static byte[] wrappedBufferSE(GeneratedMessage generatedMessage) { + byte[] idByte = short2byte((short) 0xd6ac); + byte[] backMessage = generatedMessage.toByteArray(); + byte[] verifyByte = new byte[2+4+backMessage.length]; + byte[] lengthByte =int2bytes(backMessage.length); + int length = 2+4+backMessage.length; + byte[] bytes = new byte[length]; + for(short i = 0;i{}",e.toString()); } } + + public static void sendSkyEyeMsg(String msg,User me,int uid,int channel)throws Exception{ + if(channel == 2){ + channel = 4; + }else if(channel == 3){ + channel = 8; + } + User he = null; + if(uid != 0){ + he = UserManager.getUser(uid); + } + ChatProto.ChatV3.Builder v3 = buildChatV3(msg,me,he,channel); + byte[] byteBuf = wrappedBufferSE(v3.build()); +// session.writeAndFlush(byteBuf); +// session.putBackMassageToMap(byteBuf); + ByteBuf bb = PooledByteBufAllocator.DEFAULT.heapBuffer(); + bb.writeBytes(byteBuf); + SkyEyeService.sendMsg(bb); + } + + public static ChatProto.ChatV3.Builder buildChatV3(String msg,User me,User he,int type){ + ChatProto.ChatV3.Builder v3 = ChatProto.ChatV3.newBuilder(); + String uuid = UUID.randomUUID().toString().replaceAll("-",""); + v3.setId(uuid); + v3.setChannel(type+""); + v3.setFrom(buildChatUser(me)); + if(he != null){ + v3.setTo(buildChatUser(he)); + } + v3.setContent(msg); + ISession iSession = OnlineUserManager.getSessionByUid(me.getId()); + String ip = iSession.getChannel().getLocalAddress().getHostString(); + v3.setIp(ip); + return v3; + } + + public static ChatProto.ChatUserV3.Builder buildChatUser(User user){ + ChatProto.ChatUserV3.Builder v3 = ChatProto.ChatUserV3.newBuilder(); + v3.setPlayerId(String.valueOf(user.getId())); + v3.setUserId(user.getPlayerInfoManager().getOpenId()); + v3.setNickname(user.getPlayerInfoManager().getNickName()); + v3.setLevel(user.getPlayerInfoManager().getLevel()); + v3.setVipLevel(user.getPlayerInfoManager().getVipLevel()); + v3.setZoneId(String.valueOf(GameApplication.serverId)); + v3.setZoneName(String.valueOf(GameApplication.serverId)); + v3.setServerId(1+""); + return v3; + } + //高位在前,低位在后 + public static byte[] int2bytes(int num){ + byte[] result = new byte[4]; + result[0] = (byte)((num >>> 24) & 0xff);//说明一 + result[1] = (byte)((num >>> 16)& 0xff ); + result[2] = (byte)((num >>> 8) & 0xff ); + result[3] = (byte)((num >>> 0) & 0xff ); + return result; + } + public static byte[] short2byte(short s){ + byte[] b = new byte[2]; + for(int i = 0; i < 2; i++){ + int offset = 16 - (i+1)*8; //因为byte占4个字节,所以要计算偏移量 + b[i] = (byte)((s >> offset)&0xff); //把16位分为2个8位进行分别存储 + } + return b; + } }