Browse Source

1228

master
zhangye 6 years ago
parent
commit
0d9a0c9af6
  1. 29
      cloudutil/src/main/java/com/ccsens/cloudutil/feign/TallFeignClient.java
  2. 14
      game/src/main/java/com/ccsens/game/GameApplication.java
  3. 2
      game/src/main/java/com/ccsens/game/api/ScreenController.java
  4. 2
      game/src/main/java/com/ccsens/game/bean/dto/ScreenDto.java
  5. 32
      game/src/main/java/com/ccsens/game/bean/dto/message/AckMessageDto.java
  6. 34
      game/src/main/java/com/ccsens/game/bean/dto/message/AuthMessageDto.java
  7. 35
      game/src/main/java/com/ccsens/game/bean/dto/message/BaseMessageDto.java
  8. 32
      game/src/main/java/com/ccsens/game/bean/dto/message/ChromeMessageDto.java
  9. 5
      game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageCountIn.java
  10. 31
      game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageCountOut.java
  11. 32
      game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageWithGetUrlDto.java
  12. 23
      game/src/main/java/com/ccsens/game/bean/dto/message/HeartMessageDto.java
  13. 35
      game/src/main/java/com/ccsens/game/bean/dto/message/PPTCtlMessageDto.java
  14. 4
      game/src/main/java/com/ccsens/game/bean/vo/ScreenVo.java
  15. 1
      game/src/main/java/com/ccsens/game/config/SpringConfig.java
  16. 362
      game/src/main/java/com/ccsens/game/netty/ChannelManager.java
  17. 217
      game/src/main/java/com/ccsens/game/netty/GameMessageConstant.java
  18. 200
      game/src/main/java/com/ccsens/game/netty/WrapperedChannel.java
  19. 70
      game/src/main/java/com/ccsens/game/netty/wsserver/NettyWsServer.java
  20. 33
      game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketDecoder.java
  21. 25
      game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketEncoder.java
  22. 135
      game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketHandler.java
  23. 4
      game/src/main/java/com/ccsens/game/persist/dao/GameUserJoinDao.java
  24. 35
      game/src/main/java/com/ccsens/game/service/ClientService.java
  25. 6
      game/src/main/java/com/ccsens/game/service/IClientService.java
  26. 18
      game/src/main/java/com/ccsens/game/service/IMessageService.java
  27. 2
      game/src/main/java/com/ccsens/game/service/IScreenService.java
  28. 67
      game/src/main/java/com/ccsens/game/service/MessageService.java
  29. 65
      game/src/main/java/com/ccsens/game/service/ScreenService.java
  30. 2
      mt/src/main/resources/application-test.yml
  31. 4
      mt/src/main/resources/application.yml
  32. 4
      mt/src/main/resources/druid-test.yml
  33. 7
      pom.xml
  34. 32
      tall/src/main/java/com/ccsens/tall/bean/dto/message/ChromeMessageDto.java
  35. 35
      tall/src/main/java/com/ccsens/tall/bean/dto/message/PPTCtlMessageDto.java
  36. 4
      tall/src/main/java/com/ccsens/tall/bean/dto/message/SyncMessageWithStartDto.java
  37. 1
      tall/src/main/java/com/ccsens/tall/config/SpringConfig.java
  38. 8
      tall/src/main/java/com/ccsens/tall/persist/dao/ProTaskMemberDao.java
  39. 2
      tall/src/main/java/com/ccsens/tall/service/IMessageService.java
  40. 2
      tall/src/main/java/com/ccsens/tall/service/IProMemberService.java
  41. 3
      tall/src/main/java/com/ccsens/tall/service/ITaskMemberService.java
  42. 4
      tall/src/main/java/com/ccsens/tall/service/MessageService.java
  43. 17
      tall/src/main/java/com/ccsens/tall/service/ProMemberService.java
  44. 21
      tall/src/main/java/com/ccsens/tall/service/TaskSubTimeService.java
  45. 10
      tall/src/main/java/com/ccsens/tall/web/UserController.java
  46. 4
      util/src/main/java/com/ccsens/util/CodeEnum.java
  47. 34
      util/src/main/java/com/ccsens/util/WebConstant.java
  48. 34
      util/src/main/java/com/ccsens/util/bean/message/common/MessageConstant.java

29
cloudutil/src/main/java/com/ccsens/cloudutil/feign/TallFeignClient.java

@ -18,6 +18,7 @@ import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
@ -90,6 +91,24 @@ public interface TallFeignClient {
*/ */
@GetMapping("/users/member") @GetMapping("/users/member")
JsonResponse<MemberVo.MemberInfo> getMemberByUserId(@RequestParam( name = "userId") Long userId,@RequestParam( name = "projectId") Long projectId); JsonResponse<MemberVo.MemberInfo> getMemberByUserId(@RequestParam( name = "userId") Long userId,@RequestParam( name = "projectId") Long projectId);
/**
* 获取项目下的所有成员id
* @param projectId
* @return
*/
@GetMapping("/users/allMemberAll")
List<Long> getMemberIdListByProject(@RequestParam( name = "projectId")Long projectId);
/**
* 通过任务id获得项目id(消息系统用)
* @param token
* @return
*/
@GetMapping("/users/claims")
String getUserId(@RequestParam( name = "token")String token);
} }
@Slf4j @Slf4j
@ -142,6 +161,16 @@ class TallFeignClientFallBack implements FallbackFactory<TallFeignClient> {
public JsonResponse<MemberVo.MemberInfo> getMemberByUserId(Long userId,Long projectId) { public JsonResponse<MemberVo.MemberInfo> getMemberByUserId(Long userId,Long projectId) {
return JsonResponse.newInstance().fail(); return JsonResponse.newInstance().fail();
} }
@Override
public List<Long> getMemberIdListByProject(Long projectId) {
return null;
}
@Override
public String getUserId(String token) {
return null;
}
}; };
} }

14
game/src/main/java/com/ccsens/game/GameApplication.java

@ -1,6 +1,9 @@
package com.ccsens.game; package com.ccsens.game;
import com.ccsens.game.netty.wsserver.NettyWsServer;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletComponentScan;
@ -15,10 +18,17 @@ import org.springframework.scheduling.annotation.EnableAsync;
@EnableCircuitBreaker @EnableCircuitBreaker
@EnableFeignClients(basePackages = "com.ccsens.cloudutil.feign") @EnableFeignClients(basePackages = "com.ccsens.cloudutil.feign")
@SpringBootApplication(scanBasePackages = "com.ccsens") @SpringBootApplication(scanBasePackages = "com.ccsens")
public class GameApplication { public class GameApplication implements CommandLineRunner {
@Autowired
private NettyWsServer nettyWsServer;
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(GameApplication.class, args); SpringApplication.run(GameApplication.class,args);
} }
@Override
public void run(String... args) throws Exception {
nettyWsServer.start();
}
} }

2
game/src/main/java/com/ccsens/game/api/ScreenController.java

@ -44,6 +44,7 @@ public class ScreenController {
return JsonResponse.newInstance().ok(gameInfoVo); return JsonResponse.newInstance().ok(gameInfoVo);
} }
@Login
@ApiOperation(value = "获取游戏的状态", notes = "") @ApiOperation(value = "获取游戏的状态", notes = "")
@ApiImplicitParams({ @ApiImplicitParams({
}) })
@ -64,6 +65,7 @@ public class ScreenController {
return JsonResponse.newInstance().ok(); return JsonResponse.newInstance().ok();
} }
@Login
@ApiOperation(value = "再玩一次", notes = "") @ApiOperation(value = "再玩一次", notes = "")
@ApiImplicitParams({ @ApiImplicitParams({
}) })

2
game/src/main/java/com/ccsens/game/bean/dto/ScreenDto.java

@ -9,6 +9,8 @@ public class ScreenDto {
@Data @Data
@ApiModel @ApiModel
public static class MemberGame{ public static class MemberGame{
@ApiModelProperty("项目id")
private Long projectId;
@ApiModelProperty("要创建的小游戏的类型 例如:SQ 代表数钱小游戏") @ApiModelProperty("要创建的小游戏的类型 例如:SQ 代表数钱小游戏")
private String gameType; private String gameType;
} }

32
game/src/main/java/com/ccsens/game/bean/dto/message/AckMessageDto.java

@ -0,0 +1,32 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class AckMessageDto extends BaseMessageDto {
@Setter
@Getter
public static class Data {
Long msgId;
}
private Data data;
public AckMessageDto(){
setType(WebConstant.Message_Type.Ack.phase);
setEvent(WebConstant.Message_Ack_Event.Ack.phase);
setTime(System.currentTimeMillis());
}
public AckMessageDto(Long projectId, Long msgId){
this();
setProjectId(projectId);
Data d = new Data();
d.setMsgId(msgId);
setData(d);
}
}

34
game/src/main/java/com/ccsens/game/bean/dto/message/AuthMessageDto.java

@ -0,0 +1,34 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class AuthMessageDto extends BaseMessageDto {
@Setter
@Getter
public static class Data{
private Long id;
private String userId;
private String channelId;
private String token;
}
private Data data;
public AuthMessageDto(){
setType(WebConstant.Message_Type.Auth.phase);
setEvent(WebConstant.Message_Auth_Event.Auth.phase);
setTime(System.currentTimeMillis());
}
public AuthMessageDto(String userId, String channelId){
this();
Data d = new Data();
d.setUserId(userId);
d.setChannelId(channelId);
setData(d);
}
}

35
game/src/main/java/com/ccsens/game/bean/dto/message/BaseMessageDto.java

@ -0,0 +1,35 @@
package com.ccsens.game.bean.dto.message;
import lombok.Data;
import java.util.List;
@Data
public class BaseMessageDto {
@Data
public static class MessageUser {
private Long id;
private Long userId; //本质上是authId //20190507 本质上是userId
private String nickname;
private String avatarUrl;
private boolean hasRead;
public MessageUser(){
hasRead = false;
}
public MessageUser(Long id,Long userId,String nickname,String avatarUrl){
this();
this.id = id;
this.userId = userId;
this.nickname = nickname;
this.avatarUrl = avatarUrl;
}
}
private Long time;
private String type;
private String event;
private Long projectId;
private MessageUser sender;
private List<MessageUser> receivers;
// private Object data;
}

32
game/src/main/java/com/ccsens/game/bean/dto/message/ChromeMessageDto.java

@ -0,0 +1,32 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* @author __zHangSan
*/
@Data
public class ChromeMessageDto extends BaseMessageDto{
@Setter
@Getter
public static class Data{
private String url;
}
private Data data;
public ChromeMessageDto(){
setType(WebConstant.Message_Type.Chrome.phase);
setTime(System.currentTimeMillis());
}
public ChromeMessageDto(String url){
this();
if(data == null){
data = new Data();
}
data.setUrl(url);
}
}

5
game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageCountIn.java

@ -0,0 +1,5 @@
package com.ccsens.game.bean.dto.message;
public class GameMessageCountIn extends BaseMessageDto{
}

31
game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageCountOut.java

@ -0,0 +1,31 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class GameMessageCountOut extends BaseMessageDto {
@Setter
@Getter
public static class Data{
private int totalTimes;
private int totalScore;
}
private Data data;
public GameMessageCountOut(){
setType(WebConstant.Message_Type.Game.phase);
setEvent(WebConstant.Message_Url_Event.Url.phase);
setTime(System.currentTimeMillis());
}
public GameMessageCountOut(int totalTimes, int totalScore){
this();
Data d = new Data();
d.setTotalTimes(totalTimes);
d.setTotalScore(totalScore);
setData(d);
}
}

32
game/src/main/java/com/ccsens/game/bean/dto/message/GameMessageWithGetUrlDto.java

@ -0,0 +1,32 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class GameMessageWithGetUrlDto extends BaseMessageDto {
@Setter
@Getter
public static class Data{
private Long recordId;
private String url;
}
private Data data;
public GameMessageWithGetUrlDto(){
setType(WebConstant.Message_Type.Game.phase);
setEvent(WebConstant.Message_Url_Event.Url.phase);
setTime(System.currentTimeMillis());
}
public GameMessageWithGetUrlDto(Long recordId, String url){
this();
Data d = new Data();
d.setRecordId(recordId);
d.setUrl(url);
setData(d);
}
}

23
game/src/main/java/com/ccsens/game/bean/dto/message/HeartMessageDto.java

@ -0,0 +1,23 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
@Data
public class HeartMessageDto extends BaseMessageDto{
@Setter
@Getter
public static class Data{
private int major;
private int minor;
}
private Data data;
public HeartMessageDto(){
setType(WebConstant.Message_Type.Heart.phase);
setEvent(WebConstant.Message_Heart_Event.Heart.phase);
setTime(System.currentTimeMillis());
}
}

35
game/src/main/java/com/ccsens/game/bean/dto/message/PPTCtlMessageDto.java

@ -0,0 +1,35 @@
package com.ccsens.game.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* @author __zHangSan
*/
@Data
public class PPTCtlMessageDto extends BaseMessageDto{
@Setter
@Getter
public static class Data{
/**
* Supported Operation: up,down,begin,end
*/
private String oper;
}
private Data data;
public PPTCtlMessageDto(){
setType(WebConstant.Message_Type.PPTCtl.phase);
setTime(System.currentTimeMillis());
}
public PPTCtlMessageDto(String oper){
this();
if(data == null){
data = new Data();
}
data.setOper(oper);
}
}

4
game/src/main/java/com/ccsens/game/bean/vo/ScreenVo.java

@ -12,9 +12,11 @@ public class ScreenVo {
@Data @Data
@ApiModel @ApiModel
public static class UrlVo{ public static class UrlVo{
@ApiModelProperty("大屏的路径")
private Long id;
@ApiModelProperty("大屏的路径") @ApiModelProperty("大屏的路径")
private String url; private String url;
@ApiModelProperty("游戏路径") @ApiModelProperty("游戏规则")
private List<String> ruleList; private List<String> ruleList;
} }

1
game/src/main/java/com/ccsens/game/config/SpringConfig.java

@ -76,7 +76,6 @@ public class SpringConfig implements WebMvcConfigurer {
configurer.favorPathExtension(false); configurer.favorPathExtension(false);
} }
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS"); registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS");

362
game/src/main/java/com/ccsens/game/netty/ChannelManager.java

@ -0,0 +1,362 @@
package com.ccsens.game.netty;
import cn.hutool.core.collection.CollectionUtil;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author wei
*/
public class ChannelManager {
private static Logger logger = LoggerFactory.getLogger(ChannelManager.class);
private static ThreadLocal<Channel> threadLocal = new ThreadLocal<>();
/**
* UserId,WrappedChannel authed channels;
*/
private static Map<String,Set<WrapperedChannel>> authedChannels;
/**
* Channel,WrapperedChannel
*/
private static Map<Channel,WrapperedChannel> rawChannels;
static {
authedChannels = new ConcurrentHashMap<>();
rawChannels = new ConcurrentHashMap<>();
}
/**
* 私有构造,不允许生成该类对象
*/
private ChannelManager(){}
/**
* 设置当前正在错误的channel
* @param channel netty ws/tcp连接
*/
public static void setCurrentChannel(Channel channel){
threadLocal.set(channel);
}
/**
* 获取当前线程的channel对象
* @return channel
*/
public static Channel getCurrentChannel(){
return threadLocal.get();
}
/**
* 删除当前线程的channel对象
*/
public static void removeCurrentChannel(){
threadLocal.remove();
}
/**
* 添加一个新的连接(Channel)
* @param channel 新的连接
* @param serverType 服务器类型
*/
public static synchronized void addChannel(Channel channel,String serverType){
logger.debug("Invoke addChannel({},{})",channel,serverType);
if(null != channel) {
rawChannels.put(channel, new WrapperedChannel(channel, serverType));
logger.debug("Add a new channel: {},{}",channel.id().asLongText(),serverType);
}else{
logger.error("channel is null");
}
}
/**
* 用户认证
* @param channel 连接
* @param userId 用户ID
* @param major 客户端主版本号
* @param minor 客户端次版本号
*/
public static synchronized void authChannel(Channel channel,String userId,Integer major,Integer minor){
logger.debug("Invoke authedChannels({},{},{},{})",channel.id().asLongText(),userId,major,minor);
major = major != null ? major : 0;
minor = minor != null ? minor : 0;
WrapperedChannel wrapperedChannel = rawChannels.get(channel);
if(wrapperedChannel != null){
wrapperedChannel.whenAuthed(userId,major,minor);
Set<WrapperedChannel> authedWchannelSet = authedChannels.computeIfAbsent(userId, k -> new HashSet<>());
authedWchannelSet.add(wrapperedChannel);
logger.debug("Authed channel {} with user {}", channel.id().asLongText(), userId);
}else{
logger.error("Authed channel,but wrappedChannel is null.");
}
}
/**
* 移除一个连接(Channel)
* @param channel 要移除的连接
*/
public static synchronized void removeChannel(Channel channel){
logger.debug("Invoke removeChannel({})",channel.id().asLongText());
WrapperedChannel wrapperedChannel = rawChannels.get(channel);
if(wrapperedChannel != null){
//从rawChannels集合中删除
rawChannels.remove(channel);
logger.debug("Remove a channel from rawChannels: {}",channel.id().asLongText());
if(wrapperedChannel.isAuthed()){
Set<WrapperedChannel> authedChannelSet = authedChannels.get(wrapperedChannel.getUserId());
//从authedChannel集合的value(set)中删除
if(CollectionUtil.isNotEmpty(authedChannelSet)){
authedChannelSet.remove(wrapperedChannel);
logger.debug("Remove a channel from authedChannelSet: {}, {}",wrapperedChannel.getUserId(),channel.id().asLongText());
}
//从authedChannel中删除,此处不用else,因为if中语句执行完毕之后,authedChannelSet也可能变成空集合
if(CollectionUtil.isEmpty(authedChannelSet)){
authedChannels.remove(wrapperedChannel.getUserId());
logger.debug("Remove a user from authedChannels: {}",wrapperedChannel.getUserId());
}
}
}else{
logger.error("Remove channel,but wrappedChannel is null.");
}
if(channel.isOpen() || channel.isActive()){
channel.close();
}
}
/**
* 移除一个用户
* @param userId 要移除的用户
*/
public static synchronized void removeUser(String userId){
logger.debug("Invoke remove user : {}",userId);
Set<WrapperedChannel> wChannelSet = authedChannels.get(userId);
if(CollectionUtil.isNotEmpty(wChannelSet)){
for(WrapperedChannel wChannel : wChannelSet){
//从rawChannel中依次删除
rawChannels.remove(wChannel.getChannel());
logger.debug("Remove a channel from rawChannels: {}",wChannel.getChannel().id().asLongText());
}
}
//从authedChannel中删除
authedChannels.remove(userId);
logger.debug("Remove a user from authedChannels: {}",userId);
}
/**
* 添加版本号
* 只能给已认证的请求添加版本号
* @param channel 连接
* @param major 主版本号
* @param minor 次版本号
*/
public static synchronized void versionChannel(Channel channel,int major,int minor){
logger.debug("Invoke Version channel({},{},{}))",channel.id().asLongText(),major,minor);
WrapperedChannel wChannel = rawChannels.get(channel);
if(wChannel != null){
wChannel.setVersion(major,minor);
logger.debug("Version Channel: {},{},{}",channel.id().asLongText(),major,minor);
}else{
logger.error("Remove channel,but wrappedChannel is null.");
}
}
/**
* 发送广播消息给所有已认证Channel
* @param message 消息
*/
public static synchronized void broadCastAuthed(Object message) {
logger.debug("Invoke broadCastAuthed({})",message);
for (Map.Entry<Channel,WrapperedChannel> entry : rawChannels.entrySet()) {
WrapperedChannel wChannel = entry.getValue();
if(wChannel.isAuthed()) {
wChannel.writeAndFlush(message);
logger.debug("Send Message {} to {},{}",message,wChannel.getUserId(),wChannel.getId());
}
}
}
/**
* 发送广播消息
* @param message 消息
*/
public static synchronized void broadCast(Object message) {
logger.debug("Invoke broadCast({})",message);
for (Map.Entry<Channel,WrapperedChannel> entry : rawChannels.entrySet()) {
entry.getValue().writeAndFlush(message);
logger.debug("Send Message {} to {}",message,entry.getValue().getId());
}
}
/**
* 发送消息给某个连接
* @param channel 连接
* @param message 消息
*/
public static synchronized void sendTo(Channel channel,Object message){
logger.debug("Invoke sendTo({},{})",channel.id().asLongText(),message);
WrapperedChannel wrapperedChannel = rawChannels.get(channel);
if(wrapperedChannel != null) {
wrapperedChannel.writeAndFlush(message);
logger.debug("Write message {} to Channel {}",message,channel);
}else{
logger.error("can't find channel from rawChannels");
}
}
/**
* 发送消息给某个用户
* @param userId 用户ID
* @param message 消息
*/
public static synchronized boolean sendTo(String userId,Object message){
logger.debug("Invoke sendTo({},{})",userId,message);
Set<WrapperedChannel> wChannelSet = authedChannels.get(userId);
if(CollectionUtil.isNotEmpty(wChannelSet)){
for(WrapperedChannel wChannel:wChannelSet){
wChannel.writeAndFlush(message);
logger.debug("Send message {} to channel {}",message,userId);
}
return true;
}else{
return false;
}
}
/**
* 刷新最后一次接收数据时间 每次接收数据需要调用该函数
* @param channel 接收数据的连接
*/
public static synchronized void flushReceiveTimestamp(Channel channel){
logger.debug("Invoke flushReceiveTimestamp({})",channel.id().asLongText());
WrapperedChannel wrapperedChannel = rawChannels.get(channel);
if(wrapperedChannel != null){
wrapperedChannel.whenReceivedData();
}else{
logger.error("can find channel from rawChannels");
}
}
/**
* 关闭所有未认证的连接
* @param unAuthedChannelsMaxAliveTimeInSeconds 未认证的最大时长(s)
* @throws Exception
* @deprecated 已过期该方法在多线程并发下可能出现问题建议使用messageService中的同名方法
*/
@Deprecated
public static synchronized void closeUnAuthedChannels(Long unAuthedChannelsMaxAliveTimeInSeconds) throws Exception {
logger.debug("Inovke closeUnAuthedChannels({})",unAuthedChannelsMaxAliveTimeInSeconds);
Iterator<Map.Entry<Channel,WrapperedChannel>> it = rawChannels.entrySet().iterator();
while(it.hasNext()){
Map.Entry<Channel,WrapperedChannel> entry = it.next();
WrapperedChannel wrapperedChannel = entry.getValue();
if((!wrapperedChannel.isAuthed()) && (wrapperedChannel.getConnectedSeconds() > unAuthedChannelsMaxAliveTimeInSeconds)) {
it.remove();
//关闭连接
wrapperedChannel.getChannel().close();
logger.debug("Remove a unAuthed Channel {}, which has connected {}s,maxOutTime is {}s", wrapperedChannel.getId(),wrapperedChannel.getConnectedSeconds() ,
unAuthedChannelsMaxAliveTimeInSeconds );
}
}
}
/**
* 判断Channel是否存在
* @param channel 连接
* @return 是否存在
*/
public static synchronized boolean channelExist(Channel channel){
return rawChannels.containsKey(channel);
}
/**
* 判断Channel是否已经认证
* @param channel 连接
* @return 是否认证
*/
public static synchronized boolean channelAuthed(Channel channel){
return rawChannels.containsKey(channel) && rawChannels.get(channel).isAuthed();
}
/**
* 判断用户是否在线
* @param userId 用户ID
* @return 是否认证
*/
public static synchronized boolean isUserOnline(String userId){
return authedChannels.containsKey(userId);
}
/**
* 根据Channel获取对应的用户ID
* @param channel 连接
* @return 用户ID
*/
public static synchronized String getUserIdByChannel(Channel channel) {
return rawChannels.containsKey(channel) ? rawChannels.get(channel).getUserId() : null;
}
/**
* 获取所有在线用户
* @return 所有用户的集合列表
*/
public static synchronized Set<String> getOnlineUsers(){
return authedChannels.keySet();
}
/**
* 获取某种类型的所有在线用户的连接
* @param type 客户端类型(ws/tcp modebus/tcp text)
* @return 所有在西安channel的集合列表
*/
public static synchronized Set<Channel> getOnlineChannels(String type){
Set<Channel> onLineChannels = CollectionUtil.newHashSet();
for(Map.Entry<Channel,WrapperedChannel> entry: rawChannels.entrySet()){
WrapperedChannel wrapperedChannel = entry.getValue();
if(wrapperedChannel.isAuthed() && wrapperedChannel.getType().equals(type)){
onLineChannels.add(entry.getKey());
}
}
return onLineChannels;
}
/**
* 获取一个rawChannel的副本
* @return 副本
*/
public static Map<Channel, WrapperedChannel> getCopyOfAllChannels() {
Map<Channel,WrapperedChannel> copyMap = new HashMap<>(rawChannels.size());
copyMap.putAll(rawChannels);
return copyMap;
}
/**
* 根据Channel获取WrapperedChannel
* @param channel channel
* @return 对应的wrapperedChannel
*/
public static WrapperedChannel getWrapperedChannelByChannel(Channel channel) {
return rawChannels.get(channel);
}
public static synchronized void showAuthedChannels(){
for(Map.Entry<String,Set<WrapperedChannel>> entry : authedChannels.entrySet()){
for (WrapperedChannel channel:entry.getValue()){
logger.debug("{}-->{}",entry.getKey(),channel.toString());
}
}
}
public static synchronized void showAllChannels(){
for(Map.Entry<Channel,WrapperedChannel> entry : rawChannels.entrySet()){
logger.debug(entry.getValue().toString());
}
}
public static Set<String> getAllOnlineUsers() {
return authedChannels.keySet();
}
}

217
game/src/main/java/com/ccsens/game/netty/GameMessageConstant.java

@ -0,0 +1,217 @@
package com.ccsens.game.netty;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
* @author wei
* 消息相关常量
*/
public class GameMessageConstant {
public enum ClientMessageType{
//客户端心跳
Ping(0x00),
//客户端认证
Auth(0x01),
//客户端收到消息ACK
Ack(0x02),
//客户端收到消息ACK
HasRead(0x03),
//客户端请求连接状态
GetChannelStatus(0x04),
//不可预期的错误
UnExceptedError(0x21),
ClientIdleClosed(0x22),
ClientAuthTimeOut(0x23),
//设置消息状态消息(disable撤销消息,适用于,消息撤回),针对消息本身(eg:消息撤回)
SetMsgSuccess(0x52),
SetMsgReverted(0x53),
SetMsgDeleted(0x54);
public int value;
ClientMessageType(int value){
this.value = value;
}
/**
* 从int到enum的转换函数
* @param value 枚举int值
* @return 对应的枚举找不到则返回null
*/
public static ClientMessageType valueOf(int value) {
for(ClientMessageType type : values()){
if(type.value == value){
return type;
}
}
return null;
}
}
public enum ServerMessageType{
//客户端心跳
Pong(0x00),
//客户端收到消息ACK
Ack(0x02),
//客户端请求连接状态
ChannelStatus(0x03);
//撤销某个消息
//DelMessage(0x04),
//客户端请求连接状态
//QueueStatus(0x05);
public int value;
ServerMessageType(int value){
this.value = value;
}
/**
* 从int到enum的转换函数
* @param value 枚举int值
* @return 对应的枚举找不到则返回null
*/
public static ServerMessageType valueOf(int value) {
for(ServerMessageType type : values()){
if(type.value == value){
return type;
}
}
return null;
}
}
/**
* JsonFormat是Json Serialize相关配置
*/
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Error{
//Ok
Ok(200,"Ok"),
/**
* 通用消息错误
*/
//消息无接收者错误
MessageNoReceiversError(1001,"[用户]消息至少应该有一个接收者"),
//消息无数据错误
MessageNoDataError(1002,"不允许消息内容为空"),
/**
* server消息错误
*/
//server消息无type错误
MessageNoTypeError(1003,"发送至Server域的消息必须有type字段"),
//Ack参数错误,没有找到对应的msgId
AckParameterError(1103,"Ack参数错误,没有找到对应的msgId"),
//SetSuccess参数错误,没有找到对应的msgId
SetSuccessParameterError(1104,"SetSuccess参数错误,没有找到对应的msgId"),
//SetStatusParameterError
SetStatusParameterError(1105,"SetStatus参数错误,没有找到对应的msgId"),
//HasRead参数错误,没有找到对应的msgId
HasReadParameterError(1106,"HasRead参数错误,没有找到对应的msgId"),
/**
* 身份认证错误
*/
//无权限
UnAuthed(1021, "未认证的用户"),
/**
* 业务错误
*/
//认证失败
AuthFailed(1301,"认证失败"),
//空闲断开连接(连续Ns没有收到数据)
ChannelIdle(1302,"连接断开:连续N秒没有从收到客户端收到任何数据"),
//认证超时断开连接
ChannelAuthTimeOut(1303,"连接断开:认证超时"),
//不可预期错误
UnExpectedError(1304,"不可预期异常");
public int code;
public String text;
public String extra;
Error(int code,String text) {
this.code = code;
this.text = text;
}
Error(int code,String text,String extra) {
this.code = code;
this.text = text;
this.extra = extra;
}
public Error joinExtra(String extra){
this.extra = extra;
return this;
}
}
/**
* (UserQueueRestServer)
*/
public enum DomainType{
//Netty Client
User(1),
//Queue Client
Queue(2),
//Rest Client
Rest(3),
//系统
Server(4);
public int value;
DomainType(int value){
this.value = value;
}
public static DomainType valueOf(int value) {
for(DomainType domainType : values()){
if(domainType.value == value){
return domainType;
}
}
return null;
}
}
public enum Status{
//未决状态(未完成)
Pending(0),
//发送成功(投递成功)
Succeed(1),
//发送失败(投递失败)
Failed(2),
//消息过期
Expired(3),
//消息被撤回
Reverted(4),
//消息被删除
Deleted(5),
//消息达到重试次数上限
SendTimesUpLimit(6),
//临时完成状态,当ackIsSuccess==0时,一旦ack设置消息为此状态
TempSucceed(10);
public int value;
Status(int value){
this.value = value;
}
public static Status valueOf(int value){
for(Status status : values()){
if(status.value == value){
return status;
}
}
return null;
}
}
}

200
game/src/main/java/com/ccsens/game/netty/WrapperedChannel.java

@ -0,0 +1,200 @@
package com.ccsens.game.netty;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import io.netty.channel.Channel;
import lombok.Getter;
import lombok.Setter;
import java.net.InetSocketAddress;
/**
* @author wei
*/
@Getter
@Setter
public class WrapperedChannel {
@Getter
@Setter
private static class ClientVersion{
int major;
int minor;
public ClientVersion(int major,int minor){
this.major = major;
this.minor = minor;
}
}
/**
* Netty's Channel
*/
private Channel channel;
/**
* userId
*/
private String userId;
/**
* 客户端版本号
*/
private ClientVersion version;
/**
* 客户端类型(哪种服务器)
*/
private String type;
/**
* 是否认证
*/
private boolean authed;
/**
* 连接建立时间
*/
private Long createdAtInSeconds;
/**
* 认证时间(s)
*/
private Long authedAtInSeconds;
/**
* 最后一次接收有效数据时间(包括心跳包)
*/
private Long lastDataReceivedInSeconds;
/**
* 最后一次发送有效数据时间(包括心跳包)
*/
private Long lastDataSendInSeconds;
/**
* 接收到数据条数(每接收到一条协议加1包括心跳)
*/
private long dataReceivedCount;
/**
* 发送数据条数(每发送到一条协议加1包括心跳)
*/
private long dataSendCount;
public WrapperedChannel(Channel channel){
this.channel = channel;
this.createdAtInSeconds = DateUtil.currentSeconds();
}
public WrapperedChannel(Channel channel,String type){
this(channel);
this.type = type;
}
public WrapperedChannel(Channel channel,String type,int major,int minor){
this(channel,type);
this.version = new ClientVersion(major,minor);
}
public String getVersion(){
if(ObjectUtil.isNotNull(version)){
return "v" + version.getMajor() + "." + version.getMinor();
}
return null;
}
public void setVersion(int major,int minor){
if (ObjectUtil.isNull(version)) {
version = new ClientVersion(major, minor);
} else {
version.setMajor(major);
version.setMinor(minor);
}
}
public String getRemoteAddr(){
if(ObjectUtil.isNotNull(channel)){
InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
if(ObjectUtil.isNotNull(insocket)) {
return insocket.getAddress().getHostAddress();
}
}
return null;
}
public Integer getRemotePort(){
if(ObjectUtil.isNotNull(channel)){
InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
if(ObjectUtil.isNotNull(insocket)) {
return insocket.getPort();
}
}
return null;
}
public String getId(){
if(ObjectUtil.isNotNull(channel)){
return channel.id().asLongText();
}
return null;
}
public void whenReceivedData(){
lastDataReceivedInSeconds = DateUtil.currentSeconds();
dataReceivedCount++;
}
public void whenSendData(){
lastDataSendInSeconds = DateUtil.currentSeconds();
dataSendCount++;
}
public void whenAuthed(){
authed = true;
authedAtInSeconds = DateUtil.currentSeconds();
}
public void whenAuthed(String userId,int major,int minor){
whenAuthed();
setVersion(major,minor);
this.userId = userId;
}
public void writeAndFlush(Object message){
if(channel != null && channel.isActive()){
channel.writeAndFlush(message);
whenSendData();
}
}
public Long getConnectedSeconds(){
return createdAtInSeconds == null ? null : DateUtil.currentSeconds() - createdAtInSeconds;
}
public Long getOnlineSeconds(){
return authedAtInSeconds == null ? null : DateUtil.currentSeconds() - authedAtInSeconds ;
}
@Override
public boolean equals(Object obj) {
if(ObjectUtil.isNull(obj)) {
return false;
}
if(this == obj) {
return true;
}
if(ObjectUtil.isNull(channel)) {
return false;
}
if(obj.getClass() == this.getClass()){
WrapperedChannel other = (WrapperedChannel)obj;
return channel.equals(other.channel);
}else if(obj.getClass() == channel.getClass()){
Channel other = (Channel)obj;
return channel.equals(other);
}
return false;
}
@Override
public int hashCode() {
if(ObjectUtil.isNotNull(channel)){
return channel.hashCode();
}
return 0;
}
@Override
public String toString() {
return String.format("id: %s, type: %s, authed: %b, userId: %s, version: %s",getId(),type,authed,userId,getVersion());
}
}

70
game/src/main/java/com/ccsens/game/netty/wsserver/NettyWsServer.java

@ -0,0 +1,70 @@
package com.ccsens.game.netty.wsserver;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author wei
*/
@Component
public class NettyWsServer {
private static final String URI = "/game/v3.0/ws";
private static final short PORT = 7070;
@Autowired
private WebSocketHandler webSocketHandler;
@Async
public void start() {
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new IdleStateHandler(40,
0, 0, TimeUnit.SECONDS));
p.addLast(new HttpServerCodec());
p.addLast(new HttpObjectAggregator(64 * 1024));
p.addLast(new ChunkedWriteHandler());
p.addLast(new WebSocketServerProtocolHandler(URI));
p.addLast(new WebSocketDecoder());
p.addLast(new WebSocketEncoder());
p.addLast(webSocketHandler);
}
});
// Start the server.
ChannelFuture f = b.bind(PORT).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} catch(Exception e){
e.printStackTrace();
}finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}

33
game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketDecoder.java

@ -0,0 +1,33 @@
package com.ccsens.game.netty.wsserver;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.util.JacksonUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.List;
/**
* @author wei
*/
public class WebSocketDecoder extends MessageToMessageDecoder<TextWebSocketFrame> {
private static Logger logger = LoggerFactory.getLogger(WebSocketDecoder.class);
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame msg, List<Object> out) throws Exception {
String text = msg.text();
logger.info("Websocket received: {}",text);
try {
out.add(JacksonUtil.jsonToBean(text, BaseMessageDto.class));
}catch(IOException e){
e.printStackTrace();
logger.error("Websocket Read Error: {}",text);
throw e;
}
}
}

25
game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketEncoder.java

@ -0,0 +1,25 @@
package com.ccsens.game.netty.wsserver;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.util.JacksonUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author wei
*/
public class WebSocketEncoder extends MessageToByteEncoder<BaseMessageDto> {
private static Logger logger = LoggerFactory.getLogger(WebSocketEncoder.class);
@Override
protected void encode(ChannelHandlerContext ctx, BaseMessageDto outMessageSet, ByteBuf out) throws Exception {
String msg = JacksonUtil.beanToJson(outMessageSet);
ctx.writeAndFlush(new TextWebSocketFrame(msg));
logger.info("Websocket send: {}",msg);
}
}

135
game/src/main/java/com/ccsens/game/netty/wsserver/WebSocketHandler.java

@ -0,0 +1,135 @@
package com.ccsens.game.netty.wsserver;
import com.ccsens.game.bean.dto.message.AckMessageDto;
import com.ccsens.game.bean.dto.message.AuthMessageDto;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.game.bean.dto.message.HeartMessageDto;
import com.ccsens.game.netty.ChannelManager;
import com.ccsens.game.service.IClientService;
import com.ccsens.game.service.IMessageService;
import com.ccsens.util.WebConstant;
import com.ccsens.util.bean.message.common.MessageConstant;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author wei
*/
@ChannelHandler.Sharable
@Component
public class WebSocketHandler extends SimpleChannelInboundHandler<BaseMessageDto> {
private static final String TYPE = "netty_ws";
private static Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);
@Autowired
private IClientService clientService;
@Autowired
private IMessageService messageService;
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ChannelManager.addChannel(ctx.channel(), TYPE);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ChannelManager.removeChannel(ctx.channel());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
logger.error("Channel closed. Ws get a exception: {}", cause.getMessage());
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
if (idleStateEvent.state() == IdleState.READER_IDLE) {
ctx.channel().close();
logger.error("Ws channel idle,closed.");
}
} else {
super.userEventTriggered(ctx, evt);
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, BaseMessageDto baseMessage) throws Exception {
MessageConstant.GameClientMessageType gameClientMessageType = MessageConstant.GameClientMessageType.valueOf(baseMessage.getType());
System.out.println(baseMessage);
try {
switch (gameClientMessageType) {
case Heart: {
HeartMessageDto message = (HeartMessageDto) baseMessage;
message.setTime(System.currentTimeMillis());
if (message.getData() != null) {
ChannelManager.versionChannel(
ctx.channel(), message.getData().getMajor(), message.getData().getMinor());
}
ChannelManager.sendTo(ctx.channel(), message);
break;
}
case Ack: {
AckMessageDto message = (AckMessageDto) baseMessage;
String userId = ChannelManager.getUserIdByChannel(ctx.channel());
messageService.doAckMessageWithAck(userId, message);
break;
}
case Auth:
AuthMessageDto theMessage = (AuthMessageDto) baseMessage;
theMessage.getData().setChannelId(ctx.channel().id().asLongText());
doAuthMessage(ctx, theMessage);
break;
case Count:
String userId = ChannelManager.getUserIdByChannel(ctx.channel());
clientService.clientAddTimes(userId);
break;
case ChangeStatus:
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
logger.error("Websocket Process Message Failed: {},{}", e.getMessage(), baseMessage);
throw e;
} finally {
ChannelManager.removeCurrentChannel();
}
}
private void doAuthMessage(ChannelHandlerContext ctx, AuthMessageDto message) throws Exception {
WebConstant.Message_Auth_Event event = WebConstant.Message_Auth_Event.phaseOf(message.getEvent());
switch (event) {
case Auth:
messageService.doAuthMessageWithAuth(ctx, message);
break;
default:
break;
}
}
}

4
game/src/main/java/com/ccsens/game/persist/dao/GameUserJoinDao.java

@ -5,6 +5,8 @@ import com.ccsens.game.persist.mapper.GameUserJoinMapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List;
@Repository @Repository
public interface GameUserJoinDao extends GameUserJoinMapper { public interface GameUserJoinDao extends GameUserJoinMapper {
@ -16,6 +18,6 @@ public interface GameUserJoinDao extends GameUserJoinMapper {
*/ */
int getRanking(@Param("userId") Long userId, @Param("recordId") Long recordId); int getRanking(@Param("userId") Long userId, @Param("recordId") Long recordId);
ClientVo.MemberInfo selectByRecordId(@Param("recordId") Long recordId); List<ClientVo.MemberInfo> selectByRecordId(@Param("recordId") Long recordId);
} }

35
game/src/main/java/com/ccsens/game/service/ClientService.java

@ -2,10 +2,12 @@ package com.ccsens.game.service;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake; import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.ccsens.cloudutil.bean.tall.vo.MemberVo; import com.ccsens.cloudutil.bean.tall.vo.MemberVo;
import com.ccsens.cloudutil.feign.TallFeignClient; import com.ccsens.cloudutil.feign.TallFeignClient;
import com.ccsens.game.bean.dto.ClientDto; import com.ccsens.game.bean.dto.ClientDto;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.game.bean.po.GameRecord; import com.ccsens.game.bean.po.GameRecord;
import com.ccsens.game.bean.po.GameUserJoin; import com.ccsens.game.bean.po.GameUserJoin;
import com.ccsens.game.bean.po.GameUserJoinExample; import com.ccsens.game.bean.po.GameUserJoinExample;
@ -171,20 +173,45 @@ public class ClientService implements IClientService {
joinVo.setCountMembers(count); joinVo.setCountMembers(count);
return joinVo; return joinVo;
} }
/**
* 查询总排名表
* @param params
* @return
*/
@Override @Override
public ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params) { public ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params) {
ClientDto.GatRanking gatRanking = params.getParam(); ClientDto.GatRanking gatRanking = params.getParam();
ClientVo.RankingAll rankingAll = new ClientVo.RankingAll();
GameUserJoinExample userJoinExample = new GameUserJoinExample(); GameUserJoinExample userJoinExample = new GameUserJoinExample();
userJoinExample.createCriteria().andRecordIdEqualTo(gatRanking.getRecordId()); userJoinExample.createCriteria().andRecordIdEqualTo(gatRanking.getRecordId());
List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(userJoinExample); List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(userJoinExample);
if(CollectionUtil.isNotEmpty(userJoinList)){
rankingAll.setTotalMembers(userJoinList.size());
}else {
rankingAll.setTotalMembers(0);
}
PageHelper.startPage(gatRanking.getPageNum(), gatRanking.getPageSize()); PageHelper.startPage(gatRanking.getPageNum(), gatRanking.getPageSize());
ClientVo.MemberInfo memberInfo = gameUserJoinDao.selectByRecordId(gatRanking.getRecordId()); List<ClientVo.MemberInfo> memberInfo = gameUserJoinDao.selectByRecordId(gatRanking.getRecordId());
log.info("查询成员信息"); log.info("查询成员信息");
PageInfo pageInfo =new PageInfo<>(); PageInfo pageInfo =new PageInfo<>(memberInfo);
rankingAll.setMemberInfoList(memberInfo);
rankingAll.setFirstPage(pageInfo.isIsFirstPage());
rankingAll.setLastPage(pageInfo.isIsLastPage());
return null; return rankingAll;
}
@Override
public void clientAddTimes(String userId) {
if(ObjectUtil.isNotNull(userId)){
GameUserJoinExample gameUserJoinExample = new GameUserJoinExample();
gameUserJoinExample.createCriteria().andUserIdEqualTo(Long.valueOf(userId));
List<GameUserJoin> userJoinList = gameUserJoinDao.selectByExample(gameUserJoinExample);
}
} }
} }

6
game/src/main/java/com/ccsens/game/service/IClientService.java

@ -1,6 +1,7 @@
package com.ccsens.game.service; package com.ccsens.game.service;
import com.ccsens.game.bean.dto.ClientDto; import com.ccsens.game.bean.dto.ClientDto;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.game.bean.vo.ClientVo; import com.ccsens.game.bean.vo.ClientVo;
import com.ccsens.util.bean.dto.QueryDto; import com.ccsens.util.bean.dto.QueryDto;
@ -20,4 +21,9 @@ public interface IClientService {
ClientVo.Join join(ClientDto.Join join, Long userId); ClientVo.Join join(ClientDto.Join join, Long userId);
ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params); ClientVo.RankingAll getRankingAll(QueryDto<ClientDto.GatRanking> params);
/**
* 滑动时增加次数
*/
void clientAddTimes(String userId);
} }

18
game/src/main/java/com/ccsens/game/service/IMessageService.java

@ -0,0 +1,18 @@
package com.ccsens.game.service;
import com.ccsens.game.bean.dto.message.AckMessageDto;
import com.ccsens.game.bean.dto.message.AuthMessageDto;
import com.ccsens.game.bean.dto.message.ChromeMessageDto;
import com.ccsens.game.bean.dto.message.GameMessageWithGetUrlDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.netty.channel.ChannelHandlerContext;
public interface IMessageService {
//获取路径后给每个人发送游戏路径消息
void sendGameMessageWithGetUrl(ChromeMessageDto message) throws Exception;
void doAckMessageWithAck(String userId, AckMessageDto message);
void doAuthMessageWithAuth(ChannelHandlerContext ctx, AuthMessageDto message);
}

2
game/src/main/java/com/ccsens/game/service/IScreenService.java

@ -5,7 +5,7 @@ import com.ccsens.game.bean.vo.ScreenVo;
import com.ccsens.util.bean.dto.QueryDto; import com.ccsens.util.bean.dto.QueryDto;
public interface IScreenService { public interface IScreenService {
ScreenVo.UrlVo getScreenUrl(QueryDto<ScreenDto.MemberGame> params); ScreenVo.UrlVo getScreenUrl(QueryDto<ScreenDto.MemberGame> params) throws Exception;
ScreenVo.GameInfoVo getGameInformation(QueryDto<ScreenDto.MemberRecord> params); ScreenVo.GameInfoVo getGameInformation(QueryDto<ScreenDto.MemberRecord> params);

67
game/src/main/java/com/ccsens/game/service/MessageService.java

@ -0,0 +1,67 @@
package com.ccsens.game.service;
import com.ccsens.cloudutil.feign.TallFeignClient;
import com.ccsens.game.bean.dto.message.AckMessageDto;
import com.ccsens.game.bean.dto.message.AuthMessageDto;
import com.ccsens.game.bean.dto.message.ChromeMessageDto;
import com.ccsens.game.netty.ChannelManager;
import com.ccsens.util.JacksonUtil;
import com.ccsens.util.config.RabbitMQConfig;
import io.netty.channel.ChannelHandlerContext;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageService implements IMessageService{
@Autowired
private AmqpTemplate rabbitTemplate;
@Autowired
private TallFeignClient tallFeignClient;
@Override
public void sendGameMessageWithGetUrl(ChromeMessageDto message) throws Exception {
System.out.println(JacksonUtil.beanToJson(message));
rabbitTemplate.convertAndSend(RabbitMQConfig.RabbitMQ_QUEUE_NAME,
JacksonUtil.beanToJson(message));
}
@Override
public void doAckMessageWithAck(String userId, AckMessageDto message) {
// System.out.println(message);
// //1.存储到MongoDB(ack消息不需要存储,修改响应消息的发送成功标志即可)
//// Long userId = message.getSender().getUserId();
// Long msgId = message.getData().getMsgId();
// messageLogDao.updateMessageLogSendSuccess(userId,msgId,1);
}
@Override
public void doAuthMessageWithAuth(ChannelHandlerContext ctx, AuthMessageDto message) {
System.out.println(message);
//ws连接认证
String userId = message.getData().getUserId();
if(userId == null){
String token = message.getData().getToken();
userId = tallFeignClient.getUserId(token);
}
ChannelManager.authChannel(ctx.channel(),userId,1,1);
// if(userId == null){
//// logger.warn(String.format("Auth failed: %s",userId,message.getData().getToken()));
//// ChannelManager.removeChannel(ctx.channel());
// AuthMessageWithAnswerDto messageWithAnswerDto = new AuthMessageWithAnswerDto(false,"未找到对应的用户信息");
// sendTo(ctx.channel(),messageWithAnswerDto);
// ctx.channel().close();
// return;
// }
// String channelId = message.getData().getChannelId();
// if(ChannelManager.authChannel(ctx.channel(),userId)){ //认证成功
//查找所有该用户相关未收到的消息和未读消息依次发送给该用户
// sendAllUnSendSuccessedMessagesByUserId(userId,0L);
// AuthMessageWithAnswerDto messageWithAnswerDto = new AuthMessageWithAnswerDto(true,"ok");
// sendTo(ctx.channel(),messageWithAnswerDto);
// }else {
//// AuthMessageWithAnswerDto messageWithAnswerDto = new AuthMessageWithAnswerDto(false,"认证失败");
//// sendTo(ctx.channel(),messageWithAnswerDto);
// }
}
}

65
game/src/main/java/com/ccsens/game/service/ScreenService.java

@ -1,10 +1,13 @@
package com.ccsens.game.service; package com.ccsens.game.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Snowflake; import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import com.ccsens.cloudutil.feign.TallFeignClient;
import com.ccsens.game.bean.dto.ScreenDto; import com.ccsens.game.bean.dto.ScreenDto;
import com.ccsens.game.bean.dto.message.BaseMessageDto;
import com.ccsens.game.bean.dto.message.ChromeMessageDto;
import com.ccsens.game.bean.dto.message.GameMessageWithGetUrlDto;
import com.ccsens.game.bean.po.*; import com.ccsens.game.bean.po.*;
import com.ccsens.game.bean.vo.ScreenVo; import com.ccsens.game.bean.vo.ScreenVo;
import com.ccsens.game.persist.dao.*; import com.ccsens.game.persist.dao.*;
@ -12,7 +15,6 @@ import com.ccsens.util.CodeEnum;
import com.ccsens.util.WebConstant; import com.ccsens.util.WebConstant;
import com.ccsens.util.bean.dto.QueryDto; import com.ccsens.util.bean.dto.QueryDto;
import com.ccsens.util.exception.BaseException; import com.ccsens.util.exception.BaseException;
import feign.Param;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -41,7 +43,10 @@ public class ScreenService implements IScreenService{
private GamePrizeInstructionsDao prizeInstructionsDao; private GamePrizeInstructionsDao prizeInstructionsDao;
@Autowired @Autowired
private GameUserJoinDao gameMemberJoinDao; private GameUserJoinDao gameMemberJoinDao;
@Autowired
private TallFeignClient tallFeignClient;
@Autowired
private IMessageService messageService;
@Autowired @Autowired
private Snowflake snowflake; private Snowflake snowflake;
@ -50,7 +55,7 @@ public class ScreenService implements IScreenService{
* @return * @return
*/ */
@Override @Override
public ScreenVo.UrlVo getScreenUrl(QueryDto<ScreenDto.MemberGame> params) { public ScreenVo.UrlVo getScreenUrl(QueryDto<ScreenDto.MemberGame> params) throws Exception {
ScreenDto.MemberGame memberGame = params.getParam(); ScreenDto.MemberGame memberGame = params.getParam();
//查找游戏 //查找游戏
GameType gameType = null; GameType gameType = null;
@ -86,15 +91,33 @@ public class ScreenService implements IScreenService{
GameRecord gameRecord = new GameRecord(); GameRecord gameRecord = new GameRecord();
gameRecord.setId(snowflake.nextId()); gameRecord.setId(snowflake.nextId());
gameRecord.setUserPayId(gameUserPay.getId()); gameRecord.setUserPayId(gameUserPay.getId());
gameRecord.setUrl(WebConstant.TEST_URL_GAME + gameRecord.getId() + File.separator + gameType.getScreenUrl()); gameRecord.setUrl(WebConstant.TEST_URL_GAME + gameType.getScreenUrl() + "?id="+gameRecord.getId());
gameRecord.setQrCodeUrl(WebConstant.TEST_URL_GAME + gameRecord.getId() + File.separator + gameType.getClientUrl()); gameRecord.setQrCodeUrl(WebConstant.TEST_URL_GAME + gameRecord.getId() + File.separator + gameType.getClientUrl());
gameRecordDao.insertSelective(gameRecord); gameRecordDao.insertSelective(gameRecord);
//5、查询该游戏的规则 //5、查询该游戏的规则
List<String> ruleList = getGameActivityRule(gameType.getId()); List<String> ruleList = getGameActivityRule(gameType.getId());
//6、返回 //6、返回
ScreenVo.UrlVo urlVo = new ScreenVo.UrlVo(); ScreenVo.UrlVo urlVo = new ScreenVo.UrlVo();
urlVo.setId(gameRecord.getId());
urlVo.setUrl(gameRecord.getUrl()); urlVo.setUrl(gameRecord.getUrl());
urlVo.setRuleList(ruleList); urlVo.setRuleList(ruleList);
//给所有人发送消息发送消息
ChromeMessageDto chromeMessageDto = new ChromeMessageDto(gameRecord.getUrl());
BaseMessageDto.MessageUser messageUser = null;
List<BaseMessageDto.MessageUser> messageUserList = new ArrayList<>();
//获取项目下所有成员
List<Long> memberIdList = tallFeignClient.getMemberIdListByProject(memberGame.getProjectId());
if(CollectionUtil.isNotEmpty(memberIdList)){
for(Long memberId:memberIdList){
messageUser = new BaseMessageDto.MessageUser();
messageUser.setUserId(memberId);
messageUserList.add(messageUser);
}
}
chromeMessageDto.setReceivers(messageUserList);
messageService.sendGameMessageWithGetUrl(chromeMessageDto);
return urlVo; return urlVo;
} }
@ -243,6 +266,7 @@ public class ScreenService implements IScreenService{
@Override @Override
public String startAgain(QueryDto<ScreenDto.MemberRecord> params) { public String startAgain(QueryDto<ScreenDto.MemberRecord> params) {
ScreenDto.MemberRecord memberRecord = params.getParam(); ScreenDto.MemberRecord memberRecord = params.getParam();
GameRecord gameRecordNew = null;
GameRecord gameRecord = gameRecordDao.selectByPrimaryKey(memberRecord.getMemberRecord()); GameRecord gameRecord = gameRecordDao.selectByPrimaryKey(memberRecord.getMemberRecord());
if(ObjectUtil.isNull(gameRecord)){ if(ObjectUtil.isNull(gameRecord)){
throw new BaseException(CodeEnum.NOT_GAME_RECORD); throw new BaseException(CodeEnum.NOT_GAME_RECORD);
@ -251,21 +275,28 @@ public class ScreenService implements IScreenService{
if(ObjectUtil.isNull(gameUserPay)){ if(ObjectUtil.isNull(gameUserPay)){
throw new BaseException(CodeEnum.NOT_GAME_TYPE); throw new BaseException(CodeEnum.NOT_GAME_TYPE);
} }
GameType gameType = gameTypeDao.selectByPrimaryKey(gameUserPay.getId()); GameType gameType = gameTypeDao.selectByPrimaryKey(gameUserPay.getGameTypeId());
if(ObjectUtil.isNull(gameType)){ if(ObjectUtil.isNull(gameType)){
throw new BaseException(CodeEnum.NOT_GAME_TYPE); throw new BaseException(CodeEnum.NOT_GAME_TYPE);
} }
//添加一场新的游戏记录
GameRecord gameRecordNew = new GameRecord();
gameRecordNew.setId(snowflake.nextId());
gameRecordNew.setUserPayId(gameUserPay.getId());
gameRecordNew.setUrl(WebConstant.TEST_URL_GAME + gameRecordNew.getId() + File.separator + gameType.getScreenUrl());
gameRecordNew.setQrCodeUrl(WebConstant.TEST_URL_GAME + gameRecordNew.getId() + File.separator + gameType.getClientUrl());
gameRecordDao.insertSelective(gameRecordNew);
//修改购买的游戏的使用次数
gameUserPay.setUsedCount(gameUserPay.getUsedCount() + 1);
typeMemberDao.updateByPrimaryKeySelective(gameUserPay);
if(gameUserPay.getUsedCount() >= gameUserPay.getTotalCount()){
throw new BaseException(CodeEnum. GAME_NOT_TIMES);
}
if(gameRecord.getGameStatus() == 3){
//添加一场新的游戏记录
gameRecordNew = new GameRecord();
gameRecordNew.setId(snowflake.nextId());
gameRecordNew.setUserPayId(gameUserPay.getId());
gameRecordNew.setUrl(WebConstant.TEST_URL_GAME + gameType.getScreenUrl() + "?id="+gameRecord.getId());
gameRecordNew.setQrCodeUrl(WebConstant.TEST_URL_GAME + gameRecordNew.getId() + File.separator + gameType.getClientUrl());
gameRecordDao.insertSelective(gameRecordNew);
//修改购买的游戏的使用次数
gameUserPay.setUsedCount(gameUserPay.getUsedCount() + 1);
typeMemberDao.updateByPrimaryKeySelective(gameUserPay);
}else {
throw new BaseException(CodeEnum.GAME_NO_END);
}
return gameRecordNew.getUrl(); return gameRecordNew.getUrl();
} }
@ -343,4 +374,6 @@ public class ScreenService implements IScreenService{
completedData.setOver(over); completedData.setOver(over);
return completedData; return completedData;
} }
} }

2
mt/src/main/resources/application-test.yml

@ -28,4 +28,4 @@ swagger:
enable: true enable: true
eureka: eureka:
instance: instance:
ip-address: 49.233.89.188 ip-address: 119.28.76.62

4
mt/src/main/resources/application.yml

@ -1,4 +1,4 @@
spring: spring:
profiles: profiles:
active: dev active: test
include: common, util-dev include: common, util-test

4
mt/src/main/resources/druid-test.yml

@ -15,7 +15,7 @@ spring:
maxWait: 60000 maxWait: 60000
minEvictableIdleTimeMillis: 300000 minEvictableIdleTimeMillis: 300000
minIdle: 5 minIdle: 5
password: password: 37080c1f223685592316b02dad8816c019290a476e54ebb638f9aa3ba8b6bdb9
poolPreparedStatements: true poolPreparedStatements: true
servletLogSlowSql: true servletLogSlowSql: true
servletLoginPassword: 111111 servletLoginPassword: 111111
@ -27,7 +27,7 @@ spring:
testOnReturn: false testOnReturn: false
testWhileIdle: true testWhileIdle: true
timeBetweenEvictionRunsMillis: 60000 timeBetweenEvictionRunsMillis: 60000
url: jdbc:mysql://127.0.0.1/mt?useUnicode=true&characterEncoding=UTF-8 url: jdbc:mysql://49.233.89.188/mt?useUnicode=true&characterEncoding=UTF-8
username: root username: root
validationQuery: SELECT 1 FROM DUAL validationQuery: SELECT 1 FROM DUAL
env: CCSENS_GAME env: CCSENS_GAME

7
pom.xml

@ -32,6 +32,13 @@
</properties> </properties>
<dependencies> <dependencies>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.32.Final</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>

32
tall/src/main/java/com/ccsens/tall/bean/dto/message/ChromeMessageDto.java

@ -0,0 +1,32 @@
package com.ccsens.tall.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* @author __zHangSan
*/
@Data
public class ChromeMessageDto extends BaseMessageDto{
@Setter
@Getter
public static class Data{
private String url;
}
private Data data;
public ChromeMessageDto(){
setType(WebConstant.Message_Type.Chrome.phase);
setTime(System.currentTimeMillis());
}
public ChromeMessageDto(String url){
this();
if(data == null){
data = new Data();
}
data.setUrl(url);
}
}

35
tall/src/main/java/com/ccsens/tall/bean/dto/message/PPTCtlMessageDto.java

@ -0,0 +1,35 @@
package com.ccsens.tall.bean.dto.message;
import com.ccsens.util.WebConstant;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
/**
* @author __zHangSan
*/
@Data
public class PPTCtlMessageDto extends BaseMessageDto{
@Setter
@Getter
public static class Data{
/**
* Supported Operation: up,down,begin,end
*/
private String oper;
}
private Data data;
public PPTCtlMessageDto(){
setType(WebConstant.Message_Type.PPTCtl.phase);
setTime(System.currentTimeMillis());
}
public PPTCtlMessageDto(String oper){
this();
if(data == null){
data = new Data();
}
data.setOper(oper);
}
}

4
tall/src/main/java/com/ccsens/tall/bean/dto/message/SyncMessageWithStartDto.java

@ -17,6 +17,7 @@ public class SyncMessageWithStartDto extends BaseMessageDto {
Long endTaskId; Long endTaskId;
Long time; Long time;
Long duration; //获取当前节点时长,为倒计时做准备 Long duration; //获取当前节点时长,为倒计时做准备
String player; //参赛选手名字
} }
private Data data; private Data data;
@ -28,7 +29,7 @@ public class SyncMessageWithStartDto extends BaseMessageDto {
} }
public SyncMessageWithStartDto(Long projectId, MessageUser sender, List<MessageUser> receivers, Long roleId, Long beginTaskId, public SyncMessageWithStartDto(Long projectId, MessageUser sender, List<MessageUser> receivers, Long roleId, Long beginTaskId,
Long endTaskId, Long time, Long duration){ Long endTaskId, Long time, Long duration,String player){
this(); this();
setProjectId(projectId); setProjectId(projectId);
setSender(sender); setSender(sender);
@ -40,6 +41,7 @@ public class SyncMessageWithStartDto extends BaseMessageDto {
d.setEndTaskId(endTaskId); d.setEndTaskId(endTaskId);
d.setTime(time); d.setTime(time);
d.setDuration(duration); d.setDuration(duration);
d.setPlayer(player);
setData(d); setData(d);
} }
} }

1
tall/src/main/java/com/ccsens/tall/config/SpringConfig.java

@ -135,6 +135,7 @@ public class SpringConfig implements WebMvcConfigurer {
.excludePathPatterns("/users/token") .excludePathPatterns("/users/token")
.excludePathPatterns("/users/claims") .excludePathPatterns("/users/claims")
.excludePathPatterns("/users/member") .excludePathPatterns("/users/member")
.excludePathPatterns("/users/allMemberAll")
.addPathPatterns("/plugins/**") .addPathPatterns("/plugins/**")
.addPathPatterns("/delivers/**") .addPathPatterns("/delivers/**")
.addPathPatterns("/tasks/**") .addPathPatterns("/tasks/**")

8
tall/src/main/java/com/ccsens/tall/persist/dao/ProTaskMemberDao.java

@ -0,0 +1,8 @@
package com.ccsens.tall.persist.dao;
import com.ccsens.tall.persist.mapper.ProTaskMemberMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface ProTaskMemberDao extends ProTaskMemberMapper{
}

2
tall/src/main/java/com/ccsens/tall/service/IMessageService.java

@ -8,7 +8,7 @@ import com.ccsens.util.bean.message.common.InMessage;
public interface IMessageService { public interface IMessageService {
void sendDeliverMessageWithUpload(InMessage inMessage) throws Exception; void sendDeliverMessageWithUpload(InMessage inMessage) throws Exception;
//同步消息——Start //同步消息——Start
void sendSyncMessageWithStart(Long currentUserId, Long projectId, Long roleId, Long taskId, Long time, Long duration) throws Exception; void sendSyncMessageWithStart(Long currentUserId, Long projectId, Long roleId, Long taskId, Long time, Long duration,String player) throws Exception;
void sendDeliverMessageWithChecker(InMessage inMessage)throws Exception; void sendDeliverMessageWithChecker(InMessage inMessage)throws Exception;

2
tall/src/main/java/com/ccsens/tall/service/IProMemberService.java

@ -25,4 +25,6 @@ public interface IProMemberService {
List<ProMember> selectByRole(Long roleId)throws Exception; List<ProMember> selectByRole(Long roleId)throws Exception;
MemberVo.MemberInfo getMemberByUserIdAndProjectId(Long userId, Long projectId); MemberVo.MemberInfo getMemberByUserIdAndProjectId(Long userId, Long projectId);
List<Long> getMemberIdByProjectId(Long projectId);
} }

3
tall/src/main/java/com/ccsens/tall/service/ITaskMemberService.java

@ -1,7 +1,10 @@
package com.ccsens.tall.service; package com.ccsens.tall.service;
import com.ccsens.tall.bean.po.ProTaskMember; import com.ccsens.tall.bean.po.ProTaskMember;
import org.springframework.beans.factory.annotation.Autowired;
public interface ITaskMemberService { public interface ITaskMemberService {
void saveTaskMember(ProTaskMember proTaskMember); void saveTaskMember(ProTaskMember proTaskMember);
} }

4
tall/src/main/java/com/ccsens/tall/service/MessageService.java

@ -47,7 +47,7 @@ public class MessageService implements IMessageService{
return messageUsers; return messageUsers;
} }
@Override @Override
public void sendSyncMessageWithStart(Long currentUserId, Long projectId, Long roleId, Long taskId,Long time, Long duration) throws Exception { public void sendSyncMessageWithStart(Long currentUserId, Long projectId, Long roleId, Long taskId,Long time, Long duration,String player) throws Exception {
MemberVo.MemberInfo currentMemberVo = memberService.getProMemberByProjectIdAndUserId(projectId,currentUserId); MemberVo.MemberInfo currentMemberVo = memberService.getProMemberByProjectIdAndUserId(projectId,currentUserId);
if(ObjectUtil.isNotNull(currentMemberVo)) { if(ObjectUtil.isNotNull(currentMemberVo)) {
//生成userMessage //生成userMessage
@ -58,7 +58,7 @@ public class MessageService implements IMessageService{
List<MemberVo.MemberInfo> memberList = memberService.getAuthedMemberByProjectId(projectId); List<MemberVo.MemberInfo> memberList = memberService.getAuthedMemberByProjectId(projectId);
receivers = constructMessageUsers(memberList); receivers = constructMessageUsers(memberList);
SyncMessageWithStartDto message = new SyncMessageWithStartDto(projectId, sender, receivers, roleId, taskId, null, time, duration); SyncMessageWithStartDto message = new SyncMessageWithStartDto(projectId, sender, receivers, roleId, taskId, null, time, duration,player);
//FixMe 发送到消息队列 //FixMe 发送到消息队列
System.out.println(message); System.out.println(message);
rabbitTemplate.convertAndSend(RabbitMQConfig.RabbitMQ_QUEUE_NAME, rabbitTemplate.convertAndSend(RabbitMQConfig.RabbitMQ_QUEUE_NAME,

17
tall/src/main/java/com/ccsens/tall/service/ProMemberService.java

@ -208,4 +208,21 @@ public class ProMemberService implements IProMemberService {
} }
return memberInfo; return memberInfo;
} }
@Override
public List<Long> getMemberIdByProjectId(Long projectId) {
List<Long> memberIdList = null;
ProMemberExample memberExample = new ProMemberExample();
memberExample.createCriteria().andProjectIdEqualTo(projectId);
List<ProMember> proMemberList = proMemberDao.selectByExample(memberExample);
if(CollectionUtil.isNotEmpty(proMemberList)){
memberIdList = new ArrayList<>();
for(ProMember member : proMemberList){
if(ObjectUtil.isNotNull(member.getUserId())){
memberIdList.add(member.getUserId());
}
}
}
return memberIdList;
}
} }

21
tall/src/main/java/com/ccsens/tall/service/TaskSubTimeService.java

@ -39,12 +39,16 @@ public class TaskSubTimeService implements ITaskSubTimeService {
@Autowired @Autowired
private ProSubTimeMemberDao proSubTimeMemberDao; private ProSubTimeMemberDao proSubTimeMemberDao;
@Autowired @Autowired
private TaskMemberDao taskMemberDao;
@Autowired
private ProTaskDeliverPostLogDao proTaskDeliverPostLogDao; private ProTaskDeliverPostLogDao proTaskDeliverPostLogDao;
@Autowired @Autowired
private TaskDetailDao taskDetailDao; private TaskDetailDao taskDetailDao;
@Autowired @Autowired
private ProRoleDao proRoleDao; private ProRoleDao proRoleDao;
@Autowired @Autowired
private ProMemberDao proMemberDao;
@Autowired
private IProMemberService proMemberService; private IProMemberService proMemberService;
@Autowired @Autowired
private IProTaskDetailService taskDetailService; private IProTaskDetailService taskDetailService;
@ -185,12 +189,27 @@ public class TaskSubTimeService implements ITaskSubTimeService {
taskSubTime.setComplatedStatus(1); taskSubTime.setComplatedStatus(1);
taskSubTimeDao.updateByPrimaryKeySelective(taskSubTime); taskSubTimeDao.updateByPrimaryKeySelective(taskSubTime);
//查找任务的负责人名
String player = null;
ProTaskDetail taskDetail = taskDetailDao.selectByPrimaryKey(taskSubTime.getTaskDetailId());
if(ObjectUtil.isNotNull(taskDetail)){
if(taskDetail.getAllMember() == 0){
ProTaskMemberExample taskMemberExample = new ProTaskMemberExample();
taskMemberExample.createCriteria().andTaskDetailIdEqualTo(taskDetail.getId());
List<ProTaskMember> taskMemberList = taskMemberDao.selectByExample(taskMemberExample);
if(CollectionUtil.isNotEmpty(taskMemberList)){
ProMember member = proMemberDao.selectByPrimaryKey(taskMemberList.get(0).getMemberId());
player = member.getNickname();
}
}
}
//发送同步消息 //发送同步消息
SysProject project = sysProjectDao.selectByPrimaryKey(startTaskDto.getProjectId()); SysProject project = sysProjectDao.selectByPrimaryKey(startTaskDto.getProjectId());
//已发布的项目才同步 //已发布的项目才同步
if (ObjectUtil.isNotNull(project.getPublished()) && project.getPublished() == 1) { if (ObjectUtil.isNotNull(project.getPublished()) && project.getPublished() == 1) {
messageService.sendSyncMessageWithStart(currentUserId, startTaskDto.getProjectId(), startTaskDto.getRoleId(), taskSubTime.getTaskDetailId(), now, messageService.sendSyncMessageWithStart(currentUserId, startTaskDto.getProjectId(), startTaskDto.getRoleId(), taskSubTime.getTaskDetailId(), now,
taskSubTime.getEndTime() - taskSubTime.getBeginTime()); taskSubTime.getEndTime() - taskSubTime.getBeginTime(),player);
} }
//3.添加记录 //3.添加记录
proLogService.addNewProLog(now, taskSubTime.getId(), proLogService.addNewProLog(now, taskSubTime.getId(),

10
tall/src/main/java/com/ccsens/tall/web/UserController.java

@ -272,6 +272,16 @@ public class UserController {
MemberVo.MemberInfo memberInfo = proMemberService.getMemberByUserIdAndProjectId(userId,projectId); MemberVo.MemberInfo memberInfo = proMemberService.getMemberByUserIdAndProjectId(userId,projectId);
return JsonResponse.newInstance().ok(memberInfo); return JsonResponse.newInstance().ok(memberInfo);
} }
/**
* 获取项目下的所有成员ID
*/
@RequestMapping(value = "allMemberAll", method = RequestMethod.GET, produces = {"application/json;charset=UTF-8"})
public List<Long> getMemberIdByProjectId(Long projectId) throws Exception {
List<Long> memberIdInfo = proMemberService.getMemberIdByProjectId(projectId);
return memberIdInfo;
}
} }

4
util/src/main/java/com/ccsens/util/CodeEnum.java

@ -76,7 +76,9 @@ public enum CodeEnum {
SCORE_REPEAT(60,"您已经评分,请勿重复提交",true), SCORE_REPEAT(60,"您已经评分,请勿重复提交",true),
NOT_MEMBER(61,"对不起,找不到对应的成员信息",true), NOT_MEMBER(61,"对不起,找不到对应的成员信息",true),
NOT_GAME_RECORD(62,"对不起,找不到对应的游戏场次",true), NOT_GAME_RECORD(62,"对不起,找不到对应的游戏场次",true),
NOT_JOIN_GAME(63,"您还未加入游戏,请参加游戏后再试",true) NOT_JOIN_GAME(63,"您还未加入游戏,请参加游戏后再试",true),
GAME_NO_END(64,"您的上一场游戏尚未结束,请勿重复开启",true),
GAME_NOT_TIMES(65,"游戏可玩次数不足,请充值后重试",true)
; ;
public CodeEnum addMsg(String msg){ public CodeEnum addMsg(String msg){

34
util/src/main/java/com/ccsens/util/WebConstant.java

@ -72,7 +72,7 @@ public class WebConstant {
public static final String UPLOAD_PROJECT_WBS = UPLOAD_PATH_BASE + File.separator + "project"; public static final String UPLOAD_PROJECT_WBS = UPLOAD_PATH_BASE + File.separator + "project";
public static final String URL_BASE = "https://api.ccsens.com/ptpro/uploads/"; public static final String URL_BASE = "https://api.ccsens.com/ptpro/uploads/";
public static final String TEST_URL = "https://test.tall.wiki/"; public static final String TEST_URL = "https://test.tall.wiki/";
public static final String TEST_URL_GAME = TEST_URL + "game/"; public static final String TEST_URL_GAME = TEST_URL + "game-dev/";
public static final String TEST_URL_BASE = TEST_URL + "gateway/tall/v1.0/uploads/"; public static final String TEST_URL_BASE = TEST_URL + "gateway/tall/v1.0/uploads/";
public static final Integer Expired_Verify_Code_In_Seconds = 120; public static final Integer Expired_Verify_Code_In_Seconds = 120;
@ -358,7 +358,10 @@ public class WebConstant {
,BatchSetting(0x11,"BatchSetting") ,BatchSetting(0x11,"BatchSetting")
,Admin(0x12,"Admin") ,Admin(0x12,"Admin")
,Ring(0x13,"Ring") ,Ring(0x13,"Ring")
,Deliver(0x14,"Deliver"); ,Deliver(0x14,"Deliver")
,Game(0x15,"Game")
,Chrome(0x15,"Chrome")
,PPTCtl(0x15,"PPTCtl");
public int value; public int value;
public String phase; public String phase;
Message_Type(int value,String thePhase){ Message_Type(int value,String thePhase){
@ -380,6 +383,7 @@ public class WebConstant {
case 0x12: return Admin; case 0x12: return Admin;
case 0x13: return Ring; case 0x13: return Ring;
case 0x14: return Deliver; case 0x14: return Deliver;
case 0x15: return Game;
default: return null; default: return null;
} }
} }
@ -423,7 +427,10 @@ public class WebConstant {
} }
if(phase.equalsIgnoreCase("Deliver")) { if(phase.equalsIgnoreCase("Deliver")) {
return Deliver; return Deliver;
} else { }
if(phase.equalsIgnoreCase("Game")) {
return Game;
}else {
return null; return null;
} }
} }
@ -797,6 +804,27 @@ public class WebConstant {
} }
} }
public enum Message_Url_Event{
Url(0,"Url");
public int value;
public String phase;
Message_Url_Event(int value,String thePhase){
this.value = value;
this.phase = thePhase;
}
public static Message_Url_Event valueOf(int value) { // 手写的从int到enum的转换函数
switch (value) {
case 0: return Url;
default: return null;
}
}
public static Message_Url_Event phaseOf(String phase) { // 手写的从String到enum的转换函数
if(phase.equalsIgnoreCase("Url")) {
return Url;
}
return null;
}
}
//wbs表时间类型==================================================================/ //wbs表时间类型==================================================================/
} }

34
util/src/main/java/com/ccsens/util/bean/message/common/MessageConstant.java

@ -214,4 +214,38 @@ public class MessageConstant {
return null; return null;
} }
} }
public enum GameClientMessageType{
//客户端心跳
Heart(0x00),
//客户端认证
Auth(0x01),
//客户端收到消息ACK
Ack(0x02),
//滑动
Count(0x03),
//状态改变
ChangeStatus(0x04)
;
public int value;
GameClientMessageType(int value){
this.value = value;
}
/**
* 从int到enum的转换函数
* @param value 枚举int值
* @return 对应的枚举找不到则返回null
*/
public static GameClientMessageType valueOf(int value) {
for(GameClientMessageType type : values()){
if(type.value == value){
return type;
}
}
return null;
}
}
} }

Loading…
Cancel
Save