新增观战功能

nc~
This commit is contained in:
Nico
2020-09-27 20:30:53 +08:00
committed by GitHub
16 changed files with 425 additions and 15 deletions
@@ -0,0 +1,29 @@
package org.nico.ratel.landlords.client.entity;
public class User {
public static final User INSTANCE = new User();
/** 是否游戏中 */
private boolean isPlaying = false;
/** 是否观战中 */
private boolean isWatching = false;
private User() {}
public boolean isPlaying() {
return isPlaying;
}
public void setPlaying(boolean playing) {
isPlaying = playing;
}
public boolean isWatching() {
return isWatching;
}
public void setWatching(boolean watching) {
isWatching = watching;
}
}
@@ -0,0 +1,148 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.noson.Noson;
import org.nico.noson.entity.NoType;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
public class ClientEventListener_CODE_GAME_WATCH extends ClientEventListener {
@Override
public void call(Channel channel, String wrapData) {
Map<String, Object> wrapMap = MapHelper.parser(wrapData);
ClientEventCode rawCode = ClientEventCode.valueOf(wrapMap.get("code").toString());
Object rawData = wrapMap.get("data");
switch (rawCode) {
case CODE_ROOM_JOIN_SUCCESS:
printJoinPlayerInfo(rawData);
break;
// 游戏开始
case CODE_GAME_STARTING:
printGameStartInfo(rawData);
break;
// 抢地主
case CODE_GAME_LANDLORD_ELECT:
printRobLandlord(rawData);
break;
// 地主确认
case CODE_GAME_LANDLORD_CONFIRM:
printConfirmLandlord(rawData);
break;
// 出牌
case CODE_SHOW_POKERS:
printPlayPokers(rawData);
break;
// 不出(过)
case CODE_GAME_POKER_PLAY_PASS:
printPlayPass(rawData);
break;
// 玩家退出(此时可以退出观战,修改User.isWatching状态)
case CODE_CLIENT_EXIT:
printPlayerExit(rawData, channel);
break;
// 玩家被提出房间
case CODE_CLIENT_KICK:
printKickInfo(rawData);
break;
// 游戏结束(此时可以退出观战,修改User.isWatching状态)
case CODE_GAME_OVER:
printGameResult(rawData, channel);
break;
// 其他事件忽略
default:
break;
}
}
private void printJoinPlayerInfo(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] join room");
}
private void printGameStartInfo(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Game start");
printNoticeWithTime("Player1 : " + map.get("player1"));
printNoticeWithTime("Player2 : " + map.get("player2"));
printNoticeWithTime("Player3 : " + map.get("player3"));
}
private void printRobLandlord(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] don't rob the landlord");
}
private void printConfirmLandlord(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("landlord") + "] grabbed the landlord and got extra three poker shots:");
SimplePrinter.printPokers(Noson.convert(map.get("additionalPokers"), new NoType<List<Poker>>() {}));
}
private void printPlayPokers(Object rawData) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("clientNickname") + "] play pokers:");
SimplePrinter.printPokers(Noson.convert(map.get("pokers"), new NoType<List<Poker>>() {}));
}
private void printPlayPass(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] : pass");
}
private void printPlayerExit(Object rawData, Channel channel) {
printNoticeWithTime("Player [" + rawData + "] exit room");
quitWatch(channel);
}
private void quitWatch(Channel channel) {
printNoticeWithTime("This room will be close!");
printNoticeWithTime("Quit watch, bye.");
SimplePrinter.printNotice("");
SimplePrinter.printNotice("");
// 修改玩家是否观战状态
User.INSTANCE.setWatching(false);
// 退出watch展示
get(ClientEventCode.CODE_SHOW_OPTIONS).call(channel, "");
}
private void printGameResult(Object rawData, Channel channel) {
Map<String, Object> map = MapHelper.parser(rawData.toString());
printNoticeWithTime("Player [" + map.get("winnerNickname") + "](" + map.get("winnerType") + ") won the game");
quitWatch(channel);
}
private void printKickInfo(Object rawData) {
printNoticeWithTime("Player [" + rawData + "] play time out, kick out of room.");
}
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private void printNoticeWithTime(String notice) {
String msg = FORMATTER.format(LocalDateTime.now()) + " " + notice;
SimplePrinter.printNotice(msg);
}
}
@@ -0,0 +1,28 @@
package org.nico.ratel.landlords.client.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.print.SimplePrinter;
import java.util.Map;
public class ClientEventListener_CODE_GAME_WATCH_SUCCESSFUL extends ClientEventListener {
private static final String WATCH_SUCCESSFUL_TIPS = " \n" +
"+------------------------------------------------\n" +
"|You are already watch the game. \n" +
"|Room owner: %s. Room current status: %s.\n" +
"+------------------------------------------------\n" +
" ";
@Override
public void call(Channel channel, String data) {
// 修改User.isWatching状态
User.INSTANCE.setWatching(true);
// 进入观战提示
Map<String, Object> map = MapHelper.parser(data);
SimplePrinter.printNotice(String.format(WATCH_SUCCESSFUL_TIPS, map.get("owner"), map.get("status")));
}
}
@@ -16,6 +16,7 @@ public class ClientEventListener_CODE_SHOW_OPTIONS_PVP extends ClientEventListen
SimplePrinter.printNotice("1. Create Room");
SimplePrinter.printNotice("2. Room List");
SimplePrinter.printNotice("3. Join Room");
SimplePrinter.printNotice("4. Watch Game");
SimplePrinter.printNotice("Please enter the number of options (enter [BACK] return options list)");
String line = SimpleWriter.write("pvp");
@@ -43,7 +44,22 @@ public class ClientEventListener_CODE_SHOW_OPTIONS_PVP extends ClientEventListen
pushToServer(channel, ServerEventCode.CODE_ROOM_JOIN, String.valueOf(option));
}
}
}else {
} else if (choose == 4) {
SimplePrinter.printNotice("Please enter the room id you want to watch (enter [BACK] return options list)");
line = SimpleWriter.write("roomid");
if(line.equalsIgnoreCase("BACK")) {
call(channel, data);
}else {
int option = OptionsUtils.getOptions(line);
if(line == null || option < 1) {
SimplePrinter.printNotice("Invalid options, please choose again");
call(channel, data);
}else{
pushToServer(channel, ServerEventCode.CODE_GAME_WATCH, String.valueOf(option));
}
}
} else {
SimplePrinter.printNotice("Invalid option, please choose again");
call(channel, data);
}
@@ -1,6 +1,8 @@
package org.nico.ratel.landlords.client.handler;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.client.entity.User;
import org.nico.ratel.landlords.client.event.ClientEventListener;
import org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc;
import org.nico.ratel.landlords.enums.ClientEventCode;
@@ -12,6 +14,9 @@ import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.HashMap;
import java.util.Map;
public class TransferHandler extends ChannelInboundHandlerAdapter{
@Override
@@ -24,7 +29,15 @@ public class TransferHandler extends ChannelInboundHandlerAdapter{
}
ClientEventCode code = ClientEventCode.valueOf(clientTransferData.getCode());
if(code != null) {
ClientEventListener.get(code).call(ctx.channel(), clientTransferData.getData());
if (User.INSTANCE.isWatching()) {
Map<String, Object> wrapMap = new HashMap<>(3);
wrapMap.put("code", code);
wrapMap.put("data", clientTransferData.getData());
ClientEventListener.get(ClientEventCode.CODE_GAME_WATCH).call(ctx.channel(), Noson.reversal(wrapMap));
} else {
ClientEventListener.get(code).call(ctx.channel(), clientTransferData.getData());
}
}
}
}
@@ -1,5 +1,6 @@
package org.nico.ratel.landlords.entity;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -39,6 +40,9 @@ public class Room{
private long createTime;
private int firstSellClient;
/** 观战者列表 */
private List<ClientSide> watcherList = new ArrayList<>(5);
public Room() {
}
@@ -169,4 +173,8 @@ public class Room{
public void setFirstSellClient(int firstSellClient) {
this.firstSellClient = firstSellClient;
}
public List<ClientSide> getWatcherList() {
return watcherList;
}
}
@@ -61,7 +61,10 @@ public enum ClientEventCode implements Serializable{
CODE_GAME_OVER("游戏结束"),
CODE_PVE_DIFFICULTY_NOT_SUPPORT("人机难度不支持"),
;
CODE_GAME_WATCH("观战"),
CODE_GAME_WATCH_SUCCESSFUL("观战成功");
private String msg;
@@ -29,8 +29,8 @@ public enum ServerEventCode implements Serializable{
CODE_GAME_POKER_PLAY_REDIRECT("出牌重定向"),
CODE_GAME_POKER_PLAY_PASS("不出"),
;
CODE_GAME_WATCH("观战");
private String msg;
@@ -27,8 +27,22 @@ public class ServerEventListener_CODE_CLIENT_EXIT implements ServerEventListener
client.init();
}
}
notifyWatcherClientExit(room, clientSide);
ServerContains.removeRoom(room.getId());
}
}
/**
* 通知所有观战者玩家退出游戏
*
* @param room 房间
* @param player 退出游戏玩家
*/
private void notifyWatcherClientExit(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_EXIT, player.getNickname());
}
}
}
@@ -13,6 +13,8 @@ import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.server.ServerContains;
import org.nico.ratel.landlords.server.robot.RobotEventListener;
import java.util.Map;
public class ServerEventListener_CODE_GAME_LANDLORD_ELECT implements ServerEventListener{
@Override
@@ -50,6 +52,8 @@ public class ServerEventListener_CODE_GAME_LANDLORD_ELECT implements ServerEvent
}
}
}
notifyWatcherConfirmLandlord(room, clientSide);
}else{
if(clientSide.getNext().getId() == room.getFirstSellClient()){
for(ClientSide client: room.getClientSideList()){
@@ -57,6 +61,7 @@ public class ServerEventListener_CODE_GAME_LANDLORD_ELECT implements ServerEvent
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_CYCLE, null);
}
}
ServerEventListener.get(ServerEventCode.CODE_GAME_STARTING).call(clientSide, null);
}else{
ClientSide turnClientSide = clientSide.getNext();
@@ -79,10 +84,40 @@ public class ServerEventListener_CODE_GAME_LANDLORD_ELECT implements ServerEvent
}
}
}
notifyWatcherRobLandlord(room, clientSide);
}
}
}else {
// ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_PLAY_FAIL_BY_INEXIST, null);
}
}
/**
* 通知房间内的观战人员谁是地主
*
* @param room 房间
* @param landlord 地主
*/
private void notifyWatcherConfirmLandlord(Room room, ClientSide landlord) {
String json = MapHelper.newInstance()
.put("landlord", landlord.getNickname())
.put("additionalPokers", room.getLandlordPokers())
.json();
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_CONFIRM, json);
}
}
/**
* 通知房间内的观战人员抢地主情况
*
* @param room 房间
*/
private void notifyWatcherRobLandlord(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_LANDLORD_ELECT, player.getNickname());
}
}
}
@@ -83,6 +83,8 @@ public class ServerEventListener_CODE_GAME_POKER_PLAY implements ServerEventList
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_SHOW_POKERS, result);
}
}
notifyWatcherPlayPoker(room, result);
if(clientSide.getPokers().isEmpty()) {
result = MapHelper.newInstance()
@@ -95,6 +97,9 @@ public class ServerEventListener_CODE_GAME_POKER_PLAY implements ServerEventList
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_GAME_OVER, result);
}
}
notifyWatcherGameOver(room, result);
ServerEventListener.get(ServerEventCode.CODE_CLIENT_EXIT).call(clientSide, data);
}else {
if(next.getRole() == ClientRole.PLAYER) {
@@ -115,4 +120,27 @@ public class ServerEventListener_CODE_GAME_POKER_PLAY implements ServerEventList
}
}
/**
* 通知观战者出牌信息
*
* @param room 房间
* @param result 出牌信息
*/
private void notifyWatcherPlayPoker(Room room, String result) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_SHOW_POKERS, result);
}
}
/**
* 通知观战者游戏结束
*
* @param room 房间
* @param result 出牌信息
*/
private void notifyWatcherGameOver(Room room, String result) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_OVER, result);
}
}
}
@@ -37,6 +37,8 @@ public class ServerEventListener_CODE_GAME_POKER_PLAY_PASS implements ServerEven
}
}
}
notifyWatcherPlayPass(room, clientSide);
}else {
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_CANT_PASS, null);
}
@@ -48,4 +50,15 @@ public class ServerEventListener_CODE_GAME_POKER_PLAY_PASS implements ServerEven
}
}
/**
* 通知观战者玩家不出牌
*
* @param room 房间
* @param player 不出牌的玩家
*/
private void notifyWatcherPlayPass(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_GAME_POKER_PLAY_PASS, player.getNickname());
}
}
}
@@ -7,10 +7,7 @@ import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ClientRole;
import org.nico.ratel.landlords.enums.ClientType;
import org.nico.ratel.landlords.enums.RoomStatus;
import org.nico.ratel.landlords.enums.*;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.helper.PokerHelper;
import org.nico.ratel.landlords.server.ServerContains;
@@ -68,7 +65,28 @@ public class ServerEventListener_CODE_GAME_STARTING implements ServerEventListen
}
notifyWatcherGameStart(room);
}
/**
* 通知房间内的观战人员游戏开始
*
* @param room 房间
*/
private void notifyWatcherGameStart(Room room) {
for (ClientSide clientSide : room.getWatcherList()) {
String result = MapHelper.newInstance()
.put("player1", room.getClientSideList().getFirst().getNickname())
.put("pokers1", room.getClientSideList().getFirst().getPokers())
.put("player2", room.getClientSideList().getFirst().getNext().getNickname())
.put("pokers2", room.getClientSideList().getFirst().getNext().getPokers())
.put("player3", room.getClientSideList().getLast().getNickname())
.put("pokers3", room.getClientSideList().getLast().getPokers())
.json();
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_STARTING, result);
}
}
}
@@ -0,0 +1,37 @@
package org.nico.ratel.landlords.server.event;
import org.nico.noson.Noson;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Room;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.helper.MapHelper;
import org.nico.ratel.landlords.server.ServerContains;
import java.util.HashMap;
import java.util.Map;
public class ServerEventListener_CODE_GAME_WATCH implements ServerEventListener {
@Override
public void call(ClientSide clientSide, String data) {
Room room = ServerContains.getRoom(Integer.valueOf(data));
if (room == null) {
String result = MapHelper.newInstance()
.put("roomId", data)
.json();
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_INEXIST, result);
} else {
// 将用户加入到房间中的观战者列表中
clientSide.setRoomId(room.getId());
room.getWatcherList().add(clientSide);
Map<String, String> map = new HashMap<>(16);
map.put("owner", room.getRoomOwner());
map.put("status", room.getStatus().toString());
ChannelUtils.pushToClient(clientSide.getChannel(), ClientEventCode.CODE_GAME_WATCH_SUCCESSFUL, Noson.reversal(map));
}
}
}
@@ -64,15 +64,22 @@ public class ServerEventListener_CODE_ROOM_JOIN implements ServerEventListener{
for(ClientSide client: roomClientMap.values()) {
ChannelUtils.pushToClient(client.getChannel(), ClientEventCode.CODE_ROOM_JOIN_SUCCESS, result);
}
notifyWatcherJoinRoom(room, clientSide);
}
}
}
}
/**
* 通知观战者玩家加入房间
*
* @param room 房间
* @param clientSide 玩家
*/
private void notifyWatcherJoinRoom(Room room, ClientSide clientSide) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_ROOM_JOIN_SUCCESS, clientSide.getNickname());
}
}
}
@@ -87,6 +87,8 @@ public class RoomClearTask extends TimerTask{
//kick this client
ChannelUtils.pushToClient(currentPlayer.getChannel(), ClientEventCode.CODE_CLIENT_KICK, null);
notifyWatcherClientKick(room, currentPlayer);
//client current player
room.getClientSideMap().remove(currentPlayer.getId());
room.getClientSideList().remove(currentPlayer);
@@ -136,4 +138,15 @@ public class RoomClearTask extends TimerTask{
}
}
/**
* 通知观战者玩家被提出房间
*
* @param room 房间
* @param player 被提出的玩家
*/
private void notifyWatcherClientKick(Room room, ClientSide player) {
for (ClientSide watcher : room.getWatcherList()) {
ChannelUtils.pushToClient(watcher.getChannel(), ClientEventCode.CODE_CLIENT_KICK, player.getNickname());
}
}
}