移除landlords-client-javafx子项目

This commit is contained in:
zxw
2020-08-17 23:46:47 +08:00
parent aa9d9b2677
commit 4e76362684
105 changed files with 0 additions and 4506 deletions
-59
View File
@@ -1,59 +0,0 @@
## 介绍
本项目是一个使用 `javafx` + `netty` 技术构建的一个桌面应用,
是对`ratel`应用命令行客户端的扩展,为`ratel`应用提供可视化界面操作方式。
### 系统架构
* 使用`netty`构建和**ratel**服务端的通讯
* 使用`javafx`构建`GUI`界面
## 快速启动
### 依赖
* `jdk`
本项目是一个`java`应用,所以运行需要`java`环境,前往[oracle](https://www.oracle.com/java/technologies/java-downloads.html)下载最新版本jdk进行安装
* `maven`
本项目由maven构建,构建本应用需要先安装maven,前往[apache maven](https://maven.apache.org)下载最新版本maven进行安装
### 安装
```powershell
git clone https://github.com/ainilili/ratel.git
cd ratel
mvn install package
```
#### 启动服务器
```shell
java -jar landlords-server/target/landlords-server-#{version}.jar -p 1024
```
#### 启动`javafx`客户端
```shell
java -jar landlords-client-javafx/target/landlords-client-javafx-#{version}.jar
```
## 使用
1. 选择服务器地址连接
![连接服务器](images/connect.png)
2. 输入昵称
![输入昵称](images/input-nickname.png)
3. 选择模式
![选择模式](images/select-modal.png)
4. 选择房间
![选择房间](images/choose-room.png)
5. 开始游戏
![开始游戏](images/play.png)
## TODO List
- [X] PVE模式
- [ ] PVP模式
- [ ] 优化界面
- [ ] 页面切换
- [ ] 挂机检测
## 反馈
如果你发现此客户端的bug或有任何疑问,欢迎提[issue](https://github.com/ainilili/ratel/issues)
或者你也可以直接联系我([zhangxunweia@gmail.com](zhangxunweia@gmail.com)
## 参考
* [NaiveChat](https://github.com/fuzhengwei/NaiveChat)
* [ratel部分协议](https://github.com/ainilili/ratel/blob/master/PROTOCO_CN.md)
* [javafx和netty之间的通信](./javafx-netty-communication.md)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

@@ -1,178 +0,0 @@
## 页面如何将用户信息传递给服务端
### UI组件的介绍
* `UIObject`:继承于`Stage`的一个抽象类,用于用户视图扩展
* `Controller`:基础于`UIObject`,代表一个自定义视图
* `Method`:定义视图上可以进行的操作
* `EventRegister`:用于视图上元素的事件注册
* `IEvent`:定义事件可以进行的操作
### ui类结构
![ui类结构UML图](images/ui-class-struct.png)
1. `Controller`通过`EventRegister`进行页面元素的事件注册
2. `EventRegister``IEvent`注册为页面元素上的事件回调函数
3. `IEvent`的实现类`DemoEvent`可以操纵`channel``netty`服务端进行通信
以上组件的简单流程图如下:
```
// 注册元素事件
controller -> init -> EventRegister.registerEvent -> element.setOnAction
// 元素事件响应
elemnt -> onAction -> event -> channel -> netty server
```
### 示例
场景:编写一个页面,点击页面上的退出按钮向`netty`服务端发送退出房间信号
1. 编写一个`demo.fxml`视图文件
```fxml
<AnchorPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button fx:id="quitButton">退出房间</Button>
</children>
</AnchorPane>
```
2. 编写一个`Controller`用于视图展示
```java
public class Controller extends UIObject implements Method {
private IEvent event;
private EventRegister demoEventRegister;
public Controller(IEvent event) throws IOException {
super();
// 加载fxml视图文件
root = FXMLLoader.load(getClass().getClassLoader().getResource("demo.fxml"));
setScene(new Scene(root));
this.roomEvent = roomEvent;
// 注册元素事件
registerEvent();
}
@Override
public void registerEvent() {
demoEventRegister = new DemoEventRegister(this, event);
}
}
```
3. 编写一个`Event`用于事件处理
```java
public interface Event {
void quit();
}
public class DemoEvent implements Event {
@Override
public void quit() {
// 获取channel,通过工具类向netty服务端发送退出房间信号
Channel channel = BeanUtil.getBean("channel");
ChannelUtil.pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT, null);
}
}
```
4. 编写一个`EventDefiner`用于页面元素事件注册
```java
public class DemoEventRegister implements EventRegister {
private UIObject uiObject;
private IEvent event;
public DemoEventRegister(UIObject uiObject, IEvent event) {
this.uiObject = uiObject;
this.event = event;
registerEvent();
}
@Override
public void registerEvent() {
quitRoom();
}
private void quitRoom() {
// 为退出按钮设置点击事件回调函数
uiObject.$("#quitButton", Button.clas).setOnAction(e -> event.quit());
}
}
```
## 服务端如何将信息传递给页面
如果您还不清楚`netty`服务端和`netty`客户端之间的事件通信,请先阅读[ratel部分协议](https://github.com/ainilili/ratel/blob/master/PROTOCO_CN.md)。
### 编写客户端事件监听器
编写自己的事件监听器,设置感兴趣的服务端事件编码,当对应事件出现时,会执行事件监听器中的代码。实现`ClientListener`或者继承`AbstractClientListener`编写自己的客户端事件监听器:
```java
public class ClientExitListener extends AbstractClientListener {
public ClientExitListener() {
// 设置感兴趣的服务端事件编码(CODE_CLIENT_EXIT 客户端退出事件编码)
super(ClientEventCode.CODE_CLIENT_EXIT);
}
/**
* 事件处理业务
* @param channel 客户端通信channel
* @param json 事件数据
*/
@Override
public void handle(Channel channel, String json) {
// do something ...
}
}
```
### 在客户端事件监听器中改变页面
每一个客户端事件监听器中都有`uiService`属性,通过`uiService`可以获取各个`Method`对页面进行操作:
```java
@Override
public void handler(Channel channel, String json) {
Method method = uiService.getMethod(Controller.METHOD_NAME);
// 一定要在javafx线程中进行视图的更改
Platform.runLater(() -> method.updateView(json));
}
```
### 示例
场景:客户端退出后服务端向客户端发送退出成功事件响应,客户端接收事件后弹出弹框提示退出成功。
1. 编写一个`Method`定义视图的弹出弹框行为
```java
public interface Method {
void alert(String message);
}
public class Controller extends UIObject implements Method {
private static final String METHOD_NAME = "method";
@Override
public void alert(String message) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setContentText(message);
alert.showAndWait();
}
}
```
2. 编写一个客户端事件监听器
```java
public class ClientExitListener extends AbstractClientListener {
public ClientExitListener() {
// 设置感兴趣的服务端事件编码(CODE_CLIENT_EXIT 客户端退出事件编码)
super(ClientEventCode.CODE_CLIENT_EXIT);
}
/**
* 事件处理业务
* @param channel 客户端通信channel
* @param json 事件数据
*/
@Override
public void handle(Channel channel, String json) {
Method method = uiService.getMethod(Controller.METHOD_NAME);
Platform.runLater(() -> method.alert(json));
}
}
```
-78
View File
@@ -1,78 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>landlords</artifactId>
<groupId>com.smallnico.ratel</groupId>
<version>1.2.2</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>landlords-client-javafx</artifactId>
<properties>
<start-class>priv.zxw.ratel.landlords.client.javafx.SimpleClient</start-class>
</properties>
<dependencies>
<dependency>
<groupId>com.smallnico.ratel</groupId>
<artifactId>landlords-common</artifactId>
<version>1.2.2</version>
</dependency>
<!-- logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!-- 实现lsf4j接口并整合 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,116 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.nico.noson.util.string.StringUtils;
import priv.zxw.ratel.landlords.client.javafx.listener.ClientListenerUtils;
import priv.zxw.ratel.landlords.client.javafx.handler.DefaultChannelInitializer;
import priv.zxw.ratel.landlords.client.javafx.ui.UIService;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import java.io.IOException;
import java.util.concurrent.*;
public class NettyClient {
private String host;
private int port;
private ExecutorService executorService;
private Channel channel;
private EventLoopGroup workerGroup;
private int id = -1;
private String username;
public NettyClient(UIService uiService) {
executorService = Executors.newSingleThreadExecutor();
ClientListenerUtils.setUIService(uiService);
}
public void start(String host, int port) throws Exception {
if (StringUtils.isBlank(host)) {
throw new IllegalArgumentException("不合法的host" + host);
}
if (port < 0) {
throw new IllegalArgumentException("不合法的端口:" + port);
}
this.host = host;
this.port = port;
try {
// 直接启动netty会别javafx阻塞消息接受
// 使用线程池启动则可以正常运行,why !!!!
Future<Channel> channelFuture = executorService.submit(new ClientThread());
Channel channel = channelFuture.get();
if (!channel.isActive()) {
Exception gotoCatch = new Exception();
throw gotoCatch;
}
} catch (Exception e) {
// 清理资源
if (channel != null) {
channel.close().syncUninterruptibly();
}
workerGroup.shutdownGracefully().syncUninterruptibly();
throw new IOException(String.format("连接netty服务端(%s:%d)失败", host, port), e);
}
BeanUtil.addBean("channel", channel);
}
private class ClientThread implements Callable<Channel> {
@Override
public Channel call() throws Exception {
workerGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap()
.group(workerGroup)
.channel(NioSocketChannel.class)
.handler(new DefaultChannelInitializer());
channel = bootstrap.connect(host, port).syncUninterruptibly().channel();
return channel;
}
}
public void destroy() {
if (channel == null) {
return;
}
channel.close().syncUninterruptibly();
workerGroup.shutdownGracefully().syncUninterruptibly();
executorService.shutdown();
try {
executorService.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
@@ -1,60 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx;
import com.alibaba.fastjson.JSONArray;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import org.nico.ratel.landlords.utils.StreamUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.event.IndexEvent;
import priv.zxw.ratel.landlords.client.javafx.event.LobbyEvent;
import priv.zxw.ratel.landlords.client.javafx.event.LoginEvent;
import priv.zxw.ratel.landlords.client.javafx.event.RoomEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.UIService;
import priv.zxw.ratel.landlords.client.javafx.ui.view.index.IndexController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.index.IndexMethod;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.login.LoginController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import java.io.IOException;
import java.net.URL;
import java.util.List;
public class SimpleClient extends Application {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleClient.class);
@Override
public void start(Stage primaryStage) throws Exception {
UIService uiService = new UIService();
IndexMethod indexMethod = new IndexController(new IndexEvent());
uiService.addMethods(indexMethod, new LoginController(new LoginEvent()),
new LobbyController(new LobbyEvent()), new RoomController(new RoomEvent()));
uiService.getMethod(IndexController.METHOD_NAME).doShow();
NettyClient nettyClient = new NettyClient(uiService);
BeanUtil.addBean("nettyClient", nettyClient);
try {
List<String> remoteServerAddressList = fetchRemoteServerAddresses();
Platform.runLater(() -> indexMethod.generateRemoteServerAddressOptions(remoteServerAddressList));
} catch (IOException e) {
LOGGER.error("获取远程服务器列表失败", e);
Platform.runLater(() -> indexMethod.setFetchRemoteServerAddressErrorTips());
}
}
private List<String> fetchRemoteServerAddresses() throws IOException {
String serverInfo = StreamUtils.convertToString(
new URL("https://raw.githubusercontent.com/ainilili/ratel/master/serverlist.json"));
return JSONArray.parseArray(serverInfo, String.class);
}
public static void main(String[] args) {
launch(args);
}
}
@@ -1,125 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.entity;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientType;
import java.util.ArrayList;
import java.util.List;
public class CurrentRoomInfo {
private int roomId;
private String roomOwner;
private User player;
private String prevPlayerName;
private ClientType prevPlayerRole;
private int prevPlayerSurplusPokerCount;
private String nextPlayerName;
private ClientType nextPlayerRole;
private int nextPlayerSurplusPokerCount;
private String recentPlayerName;
private List<Poker> recentPokers;
private List<Poker> checkedPokers;
public CurrentRoomInfo(int roomId, String roomOwner) {
this.roomId = roomId;
this.roomOwner = roomOwner;
this.checkedPokers = new ArrayList<>();
}
public void setLandlord(String landlordName) {
if (landlordName.equals(player.getNickname())) {
player.setRole(ClientType.LANDLORD);
prevPlayerRole = nextPlayerRole = ClientType.PEASANT;
} else if (landlordName.equals(prevPlayerName)) {
prevPlayerRole = ClientType.LANDLORD;
nextPlayerRole = ClientType.PEASANT;
player.setRole(ClientType.PEASANT);
} else {
nextPlayerRole = ClientType.LANDLORD;
prevPlayerRole = ClientType.PEASANT;
player.setRole(ClientType.PEASANT);
}
}
public String getRecentPlayerName() {
return recentPlayerName;
}
public void setRecentPlayerName(String recentPlayerName) {
this.recentPlayerName = recentPlayerName;
}
public List<Poker> getRecentPokers() {
return recentPokers;
}
public void setRecentPokers(List<Poker> recentPokers) {
this.recentPokers = recentPokers;
}
public void setPlayer(User player) {
this.player = player;
}
public User getPlayer() {
return player;
}
public void setPrevPlayerName(String prevPlayerName) {
this.prevPlayerName = prevPlayerName;
}
public void setNextPlayerName(String nextPlayerName) {
this.nextPlayerName = nextPlayerName;
}
public String getPrevPlayerName() {
return prevPlayerName;
}
public String getNextPlayerName() {
return nextPlayerName;
}
public ClientType getPrevPlayerRole() {
return prevPlayerRole;
}
public ClientType getNextPlayerRole() {
return nextPlayerRole;
}
public void addCheckedPoker(Poker poker) {
checkedPokers.add(poker);
}
public void removeUncheckedPoker(Poker poker) {
checkedPokers.remove(poker);
}
public List<Poker> pollCheckedPokers() {
List<Poker> pokers = new ArrayList<>(checkedPokers);
checkedPokers.clear();
return pokers;
}
public int getPrevPlayerSurplusPokerCount() {
return prevPlayerSurplusPokerCount;
}
public void setPrevPlayerSurplusPokerCount(int prevPlayerSurplusPokerCount) {
this.prevPlayerSurplusPokerCount = prevPlayerSurplusPokerCount;
}
public int getNextPlayerSurplusPokerCount() {
return nextPlayerSurplusPokerCount;
}
public void setNextPlayerSurplusPokerCount(int nextPlayerSurplusPokerCount) {
this.nextPlayerSurplusPokerCount = nextPlayerSurplusPokerCount;
}
}
@@ -1,41 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.entity;
public class RoomInfo {
private Integer roomId;
private String roomOwner;
private Integer roomClientCount;
private String roomType;
public Integer getRoomId() {
return roomId;
}
public void setRoomId(Integer roomId) {
this.roomId = roomId;
}
public String getRoomOwner() {
return roomOwner;
}
public void setRoomOwner(String roomOwner) {
this.roomOwner = roomOwner;
}
public Integer getRoomClientCount() {
return roomClientCount;
}
public void setRoomClientCount(Integer roomClientCount) {
this.roomClientCount = roomClientCount;
}
public String getRoomType() {
return roomType;
}
public void setRoomType(String roomType) {
this.roomType = roomType;
}
}
@@ -1,73 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.entity;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientType;
import java.util.List;
import java.util.stream.Collectors;
public class User {
private String nickname;
private boolean playing = false;
private int currentRoomId = -1;
private List<Poker> pokers;
// null, ClientType.LANDLORD, ClientType.PEASANT
private ClientType role;
public User(String nickname) {
this.nickname = nickname;
}
public void joinRoom(int roomId) {
currentRoomId = roomId;
playing = true;
}
public void exitRoom() {
currentRoomId = -1;
playing = false;
role = null;
pokers.clear();
pokers = null;
}
public void addPokers(List<Poker> pokers) {
if (this.pokers != null) {
this.pokers.addAll(pokers);
} else {
this.pokers = pokers;
}
this.pokers = this.pokers.stream()
.sorted((a, b) -> Integer.compare(b.getLevel().getLevel(), a.getLevel().getLevel()))
.collect(Collectors.toList());
}
public void removePokers(List<Poker> sellPokerList) {
for (Poker sellPoker : sellPokerList) {
pokers.remove(sellPoker);
}
}
public List<Poker> getPokers() {
return pokers;
}
public ClientType getRole() {
return role;
}
public boolean isPlaying() {
return playing;
}
public void setRole(ClientType role) {
this.role = role;
}
public String getNickname() {
return nickname;
}
}
@@ -1,15 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.event;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IIndexEvent;
public class IndexEvent implements IIndexEvent {
@Override
public void connect(String host, int port) throws Exception {
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
nettyClient.start(host, port);
}
}
@@ -1,57 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.listener.ClientListener;
import priv.zxw.ratel.landlords.client.javafx.listener.ClientListenerUtils;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILobbyEvent;
public class LobbyEvent implements ILobbyEvent {
@Override
public void selectPVPModal() {
ClientListener listener = ClientListenerUtils.getListener(ClientEventCode.CODE_SHOW_OPTIONS_PVP);
listener.handle(BeanUtil.getBean("channel"), ".");
}
@Override
public void selectPVEModal() {
ClientListener listener = ClientListenerUtils.getListener(ClientEventCode.CODE_SHOW_OPTIONS_PVE);
listener.handle(BeanUtil.getBean("channel"), ".");
}
@Override
public void createPVPRoom() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_ROOM_CREATE, null);
}
@Override
public void createPVERoom(int modal) {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_ROOM_CREATE_PVE, String.valueOf(modal));
}
@Override
public void showRooms() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GET_ROOMS, null);
}
@Override
public void joinRoom(int roomId) {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_ROOM_JOIN, String.valueOf(roomId));
}
}
@@ -1,26 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.event;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILoginEvent;
public class LoginEvent implements ILoginEvent {
@Override
public void setNickname(String nickname) {
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
nettyClient.setUsername(nickname);
User user = new User(nickname);
BeanUtil.addBean("user", user);
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_CLIENT_NICKNAME_SET, nickname);
}
}
@@ -1,61 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.event;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IRoomEvent;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class RoomEvent implements IRoomEvent {
@Override
public void robLandlord() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_LANDLORD_ELECT, "TRUE");
}
@Override
public void notRobLandlord() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_LANDLORD_ELECT, "FALSE");
}
@Override
public void submitPokers(List<Poker> pokerList) {
Channel channel = BeanUtil.getBean("channel");
String[] chars = pokerList.stream()
.sorted(Comparator.comparingInt(poker -> poker.getLevel().getLevel()))
.map(p -> {
String name = p.getLevel().getName();
// 10 实际出牌值为 0
return name.length() > 1 ? name.substring(1, 2) : name;
})
.collect(Collectors.toList())
.toArray(new String[] {});
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY, JSONObject.toJSONString(chars));
}
@Override
public void passRound() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_PASS, null);
}
@Override
public void exit() {
Channel channel = BeanUtil.getBean("channel");
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_CLIENT_EXIT, null);
}
}
@@ -1,35 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.handler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.timeout.IdleStateHandler;
import org.nico.ratel.landlords.entity.ClientTransferData;
import java.util.concurrent.TimeUnit;
/**
* @ClassName DefaultChannelInitializer
* @Desc TODO
* @Author zxw
* @Date 2020/8/5 13:25
* @Version 1.0
*/
public class DefaultChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline()
.addLast(new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS))
.addLast(new ProtobufVarint32FrameDecoder())
.addLast(new ProtobufDecoder(ClientTransferData.ClientTransferDataProtoc.getDefaultInstance()))
.addLast(new ProtobufVarint32LengthFieldPrepender())
.addLast(new ProtobufEncoder())
.addLast(new SecondProtobufCodec())
.addLast(new TransferHandler());
}
}
@@ -1,29 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.handler;
import com.google.protobuf.MessageLite;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import org.nico.ratel.landlords.entity.ClientTransferData;
import java.util.List;
/**
* @ClassName SecondProtobufCodec
* @Desc TODO
* @Author zxw
* @Date 2020/8/5 13:26
* @Version 1.0
*/
public class SecondProtobufCodec extends MessageToMessageCodec<ClientTransferData.ClientTransferDataProtoc, MessageLite> {
@Override
protected void encode(ChannelHandlerContext ctx, MessageLite msg, List<Object> out) throws Exception {
out.add(msg);
}
@Override
protected void decode(ChannelHandlerContext ctx, ClientTransferData.ClientTransferDataProtoc msg, List<Object> out) throws Exception {
out.add(msg);
}
}
@@ -1,64 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.ClientTransferData.ClientTransferDataProtoc;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import org.nico.ratel.landlords.print.SimplePrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.listener.ClientListener;
import priv.zxw.ratel.landlords.client.javafx.listener.ClientListenerUtils;
public class TransferHandler extends ChannelInboundHandlerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(TransferHandler.class);
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
ClientTransferDataProtoc clientTransferData = (ClientTransferDataProtoc) msg;
if (clientTransferData.getInfo() != null && !clientTransferData.getInfo().isEmpty()) {
SimplePrinter.printNotice(clientTransferData.getInfo());
}
ClientEventCode code = ClientEventCode.valueOf(clientTransferData.getCode());
LOGGER.info("接受服务端信息, 编码:{},数据:{}.", code, clientTransferData.getData());
if (code != null) {
ClientListener listener = ClientListenerUtils.getListener(code);
if (listener != null) {
listener.handle(ctx.channel(), clientTransferData.getData());
} else {
LOGGER.warn("未知的消息编码 {},忽略该条消息: {}", code, clientTransferData.getData());
}
}
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.WRITER_IDLE) {
ChannelUtils.pushToServer(ctx.channel(), ServerEventCode.CODE_CLIENT_HEAD_BEAT, "heartbeat");
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) {
cause.printStackTrace();
context.close();
}
}
@@ -1,28 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.UIService;
import java.util.Objects;
public abstract class AbstractClientListener implements ClientListener {
protected ClientEventCode code;
protected UIService uiService;
public AbstractClientListener(ClientEventCode code) {
Objects.requireNonNull(code, "子事件监听器需要自定义专属的事件编码");
this.code = code;
}
@Override
public ClientEventCode getCode() {
return code;
}
@Override
public void setUIService(UIService uiService) {
this.uiService = uiService;
}
}
@@ -1,32 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
public class ClientCantPassListener extends AbstractClientListener {
public ClientCantPassListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_CANT_PASS);
}
@Override
public void handle(Channel channel, String json) {
// 不允许跳过,即简单的不响应用户操作即可
RoomController roomController = (RoomController) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
Label tips = ((Label) roomController.$("playerPane", Pane.class).lookup(".error-tips"));
tips.setVisible(true);
tips.setText("此回合不能不出牌");
roomController.delayHidden(tips, 2);
});
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
@@ -1,52 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
import java.util.List;
public class ClientConfirmLandlordListener extends AbstractClientListener {
public ClientConfirmLandlordListener() {
super(ClientEventCode.CODE_GAME_LANDLORD_CONFIRM);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
String landlordName = jsonObject.getString("landlordNickname");
List<Poker> surplusPokerList = jsonObject.getJSONArray("additionalPokers").toJavaList(Poker.class);
// 给地主发底牌
User user = BeanUtil.getBean("user");
if (landlordName.equals(user.getNickname())) {
user.addPokers(surplusPokerList);
}
// 设置玩家的角色
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
currentRoomInfo.setLandlord(landlordName);
// 视图更新
RoomMethod method = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
method.showSurplusPokers(surplusPokerList);
method.hideRobButtons();
method.setLandLord(landlordName);
});
// 重定向玩家
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
@@ -1,25 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
public class ClientConnectListener extends AbstractClientListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientConnectListener.class);
public ClientConnectListener() {
super(ClientEventCode.CODE_CLIENT_CONNECT);
}
@Override
public void handle(Channel channel, String json) {
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
nettyClient.setId(Integer.parseInt(json));
LOGGER.info("当前客户端被分配的id为 {}", nettyClient.getId());
}
}
@@ -1,27 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientExitListener extends AbstractClientListener {
public ClientExitListener() {
super(ClientEventCode.CODE_CLIENT_EXIT);
}
@Override
public void handle(Channel channel, String json) {
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
LobbyMethod lobbyMethod = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(() -> {
roomMethod.doClose();
lobbyMethod.doShow();
});
}
}
@@ -1,27 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ClientType;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientGameOverListener extends AbstractClientListener {
public ClientGameOverListener() {
super(ClientEventCode.CODE_GAME_OVER);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
String winnerName = jsonObject.getString("winnerNickname");
ClientType clientType = jsonObject.getObject("winnerType", ClientType.class);
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> roomMethod.gameOver(winnerName, clientType));
}
}
@@ -1,28 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientJoinRoomSuccessfulListener extends AbstractClientListener {
public ClientJoinRoomSuccessfulListener() {
super(ClientEventCode.CODE_ROOM_JOIN_SUCCESS);
}
@Override
public void handle(Channel channel, String json) {
Method lobbyMethod = uiService.getMethod(LobbyController.METHOD_NAME);
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
lobbyMethod.doClose();
roomMethod.joinRoom();
});
}
}
@@ -1,33 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.AlertUtils;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientKickListener extends AbstractClientListener {
public ClientKickListener() {
super(ClientEventCode.CODE_CLIENT_KICK);
}
@Override
public void handle(Channel channel, String json) {
Method lobbyMethod = uiService.getMethod(LobbyController.METHOD_NAME);
RoomMethod roomMethod = (RoomController) uiService.getMethod(RoomController.METHOD_NAME);
// 防止出现多次触发 CODE_CLIENT_KICK 事件后导致页面显示错误的情况
if (roomMethod.isShow()) {
Platform.runLater(() -> {
AlertUtils.warn("您已经退出房间", "您因长时间未操作,请出已被房间");
roomMethod.doClose();
lobbyMethod.doShow();
});
}
}
}
@@ -1,14 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.UIService;
public interface ClientListener {
void handle(Channel channel, String json);
ClientEventCode getCode();
void setUIService(UIService uiService);
}
@@ -1,100 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.ui.UIService;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ClientListenerUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientListenerUtils.class);
/** code - listener 映射 */
private static final Map<ClientEventCode, ClientListener> LISTENER_MAP = new HashMap<>(16);
/**
* 获取code对应的事件监听器
*
* @param code 事件编码
* @return code对应的事件监听器,如果不存在对应的事件监听器则返回null
*/
public static ClientListener getListener(ClientEventCode code) {
ClientListener clientListener = LISTENER_MAP.get(code);
return clientListener;
}
public static ClientEventCode[] supportCodes() {
return LISTENER_MAP.keySet().toArray(new ClientEventCode[] {});
}
public static void setUIService(UIService uiService) {
for (ClientListener listener : LISTENER_MAP.values()) {
listener.setUIService(uiService);
}
}
static {
List<Class<ClientListener>> listenerClassList = findListener();
for (Class<ClientListener> clazz : listenerClassList) {
try {
ClientListener listener = clazz.newInstance();
LISTENER_MAP.put(listener.getCode(), listener);
LOGGER.info("添加 {} -> {} 事件监听器映射", listener.getCode(), listener.getClass().getName());
} catch (InstantiationException e) {
LOGGER.warn(clazz.getName() + " 不能被实例化");
} catch (IllegalAccessException e) {
LOGGER.warn(clazz.getName() + " 没有默认构造函数或默认构造函数不可访问", e);
}
}
}
private static List<Class<ClientListener>> findListener() {
ClassLoader defaultClassLoader = ClientListenerUtils.class.getClassLoader();
URL classWorkPath = ClientListenerUtils.class.getResource("");
File classWorkDir = new File(classWorkPath.getPath());
return loadClasses(defaultClassLoader, classWorkDir.listFiles(ClientListenerUtils::isNormalClass))
.stream()
.filter(clazz -> clazz.getSuperclass() == AbstractClientListener.class)
.map(clazz -> (Class<ClientListener>) clazz)
.collect(Collectors.toList());
}
private static boolean isNormalClass(File file) {
String fileName = file.getName();
boolean isClassFile = fileName.endsWith(".class");
boolean isNotInnerClassFile = !fileName.matches("[A-Z]\\w+\\$\\w+.class");
return isClassFile && isNotInnerClassFile;
}
private static List<Class<?>> loadClasses(ClassLoader classLoader, File[] classFiles) {
String classpath = classLoader.getResource("").getPath();
List<Class<?>> classList = new ArrayList<>(classFiles.length);
for (File classFile : classFiles) {
String absolutePath = classFile.getAbsolutePath();
String classFullName = absolutePath.substring(classpath.length() - 1, absolutePath.lastIndexOf("."))
.replace(File.separator, ".");
try {
classList.add(classLoader.loadClass(classFullName));
} catch (ClassNotFoundException e) {
LOGGER.warn("默认类加载器在 {} 路径下没有找到 {} 类", classpath, classFullName);
}
}
return classList;
}
}
@@ -1,51 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
import java.util.Collections;
public class ClientPassListener extends AbstractClientListener {
public ClientPassListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_PASS);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
RoomMethod method = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
// 更新当前玩家和出牌信息
String clientNickname = jsonObject.getString("clientNickname");
currentRoomInfo.setRecentPlayerName(clientNickname);
currentRoomInfo.setRecentPokers(Collections.emptyList());
// 视图更新
String nextClientNickname = jsonObject.getString("nextClientNickname");
Platform.runLater(() -> {
method.play(nextClientNickname);
method.showMessage(clientNickname, "不出");
});
// 如果下一个出牌的是本玩家进行出牌重定向
int turnClientId = jsonObject.getIntValue("nextClientId");
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
if (turnClientId == nettyClient.getId()) {
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
}
@@ -1,33 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
public class ClientPokerInvalidListener extends AbstractClientListener {
public ClientPokerInvalidListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_INVALID);
}
@Override
public void handle(Channel channel, String json) {
// 牌无效,不允许出牌,即简单的不响应用户操作即可
RoomController roomController = (RoomController) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
Label tips = ((Label) roomController.$("playerPane", Pane.class).lookup(".error-tips"));
tips.setVisible(true);
tips.setText("您的出牌不符合规则");
roomController.delayHidden(tips, 2);
});
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
@@ -1,32 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
public class ClientPokerLessListener extends AbstractClientListener {
public ClientPokerLessListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_LESS);
}
@Override
public void handle(Channel channel, String json) {
// 出牌太少,不允许出牌,即简单的不响应用户操作即可
RoomController roomController = (RoomController) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
Label tips = ((Label) roomController.$("playerPane", Pane.class).lookup(".error-tips"));
tips.setVisible(true);
tips.setText("您的出牌应该大于上家的牌");
roomController.delayHidden(tips, 2);
});
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
@@ -1,34 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
public class ClientPokerMismatchListener extends AbstractClientListener {
public ClientPokerMismatchListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_MISMATCH);
}
@Override
public void handle(Channel channel, String json) {
// 出牌不匹配,不允许出牌,即简单的不响应用户操作即可
JSONObject jsonObject = JSONObject.parseObject(json);
RoomController roomController = (RoomController) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
Label tips = ((Label) roomController.$("playerPane", Pane.class).lookup(".error-tips"));
tips.setVisible(true);
tips.setText("您需要出" + jsonObject.getIntValue("preCount") + "张牌");
roomController.delayHidden(tips, 2);
});
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GAME_POKER_PLAY_REDIRECT, null);
}
}
@@ -1,26 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientPokerPlayListener extends AbstractClientListener {
public ClientPokerPlayListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY);
}
@Override
public void handle(Channel channel, String json) {
User user = BeanUtil.getBean("user");
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> roomMethod.play(user.getNickname()));
}
}
@@ -1,34 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
public class ClientPokerPlayRedirectListener extends AbstractClientListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientPokerPlayRedirectListener.class);
public ClientPokerPlayRedirectListener() {
super(ClientEventCode.CODE_GAME_POKER_PLAY_REDIRECT);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
int sellClientId = jsonObject.getIntValue("sellClientId");
// 通知下一个玩家出牌
if (sellClientId == nettyClient.getId()) {
ClientListenerUtils.getListener(ClientEventCode.CODE_GAME_POKER_PLAY).handle(channel, json);
}
}
}
@@ -1,16 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import org.nico.ratel.landlords.enums.ClientEventCode;
public class ClientRestartGameListener extends AbstractClientListener {
public ClientRestartGameListener() {
super(ClientEventCode.CODE_GAME_LANDLORD_CYCLE);
}
@Override
public void handle(Channel channel, String json) {
System.out.println("无人抢地主,重新发牌");
}
}
@@ -1,28 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientRoomCreateSuccessfulListener extends AbstractClientListener {
public ClientRoomCreateSuccessfulListener() {
super(ClientEventCode.CODE_ROOM_CREATE_SUCCESS);
}
@Override
public void handle(Channel channel, String json) {
Method lobbyMethod = uiService.getMethod(LobbyController.METHOD_NAME);
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
lobbyMethod.doClose();
roomMethod.joinRoom();
});
}
}
@@ -1,23 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
public class ClientRoomFullJoinFailListener extends AbstractClientListener {
public ClientRoomFullJoinFailListener() {
super(ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_FULL);
}
@Override
public void handle(Channel channel, String json) {
LobbyMethod lobbyMethod = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(() -> {
lobbyMethod.joinRoomFail("房间已经满人", "该房间人数已满,开始游戏,请挑选其它未满房间进行游戏。");
});
}
}
@@ -1,23 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
public class ClientRoomNotExistsJoinFailListener extends AbstractClientListener {
public ClientRoomNotExistsJoinFailListener() {
super(ClientEventCode.CODE_ROOM_JOIN_FAIL_BY_INEXIST);
}
@Override
public void handle(Channel channel, String json) {
LobbyMethod lobbyMethod = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(() -> {
lobbyMethod.joinRoomFail("房间已经不存在", "该房间已经不存在,可能房主已经解散该房间了,请挑选其它房间进行游戏。");
});
}
}
@@ -1,38 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
public class ClientSelectLandlordListener extends AbstractClientListener {
private static final Logger LOGGER = LoggerFactory.getLogger(ClientSelectLandlordListener.class);
public ClientSelectLandlordListener() {
super(ClientEventCode.CODE_GAME_LANDLORD_ELECT);
}
@Override
public void handle(Channel channel, String json) {
// 计算出玩家的顺序
JSONObject jsonObject = JSONObject.parseObject(json);
String nextClientNickname = jsonObject.getString("nextClientNickname");
// 决定接下来谁抢地主
int turnClientId = jsonObject.getIntValue("nextClientId");
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
if (turnClientId == nettyClient.getId()) {
RoomMethod method = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> method.showRobButtons());
}
LOGGER.info("接下来由 {} 抢地主", nextClientNickname);
}
}
@@ -1,26 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.index.IndexController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.login.LoginController;
public class ClientSetNicknameListener extends AbstractClientListener {
public ClientSetNicknameListener() {
super(ClientEventCode.CODE_CLIENT_NICKNAME_SET);
}
@Override
public void handle(Channel channel, String json) {
Method indexMethod = uiService.getMethod(IndexController.METHOD_NAME);
Method loginMethod = uiService.getMethod(LoginController.METHOD_NAME);
Platform.runLater(() -> {
indexMethod.doClose();
loginMethod.doShow();
});
}
}
@@ -1,27 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.login.LoginController;
public class ClientShowOptionsListener extends AbstractClientListener {
public ClientShowOptionsListener() {
super(ClientEventCode.CODE_SHOW_OPTIONS);
}
@Override
public void handle(Channel channel, String json) {
Method loginMethod = uiService.getMethod(LoginController.METHOD_NAME);
Method lobbyMethod = uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(() -> {
loginMethod.doClose();
lobbyMethod.doShow();
});
}
}
@@ -1,22 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
public class ClientShowOptionsPVEListener extends AbstractClientListener {
public ClientShowOptionsPVEListener() {
super(ClientEventCode.CODE_SHOW_OPTIONS_PVE);
}
@Override
public void handle(Channel channel, String json) {
LobbyMethod lobbyMethod = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(lobbyMethod::toggleToPVEMenu);
}
}
@@ -1,25 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.channel.ChannelUtils;
import org.nico.ratel.landlords.enums.ClientEventCode;
import org.nico.ratel.landlords.enums.ServerEventCode;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
public class ClientShowOptionsPVPListener extends AbstractClientListener {
public ClientShowOptionsPVPListener() {
super(ClientEventCode.CODE_SHOW_OPTIONS_PVP);
}
@Override
public void handle(Channel channel, String json) {
LobbyMethod lobbyMethod = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(lobbyMethod::toggleToPVPMenu);
ChannelUtils.pushToServer(channel, ServerEventCode.CODE_GET_ROOMS, null);
}
}
@@ -1,55 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import javafx.scene.control.Label;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
import java.util.List;
public class ClientShowPokersListener extends AbstractClientListener {
public ClientShowPokersListener() {
super(ClientEventCode.CODE_SHOW_POKERS);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
String clientNickname = jsonObject.getString("clientNickname");
List<Poker> sellPokerList = jsonObject.getJSONArray("pokers").toJavaList(Poker.class);
// 更新当前玩家和出牌信息
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
User user = currentRoomInfo.getPlayer();
if (user.getNickname().equals(clientNickname)) {
user.removePokers(sellPokerList);
} else if (currentRoomInfo.getPrevPlayerName().equals(clientNickname)) {
currentRoomInfo.setPrevPlayerSurplusPokerCount(currentRoomInfo.getPrevPlayerSurplusPokerCount() - sellPokerList.size());
} else if (currentRoomInfo.getNextPlayerName().equals(clientNickname)) {
currentRoomInfo.setNextPlayerSurplusPokerCount(currentRoomInfo.getNextPlayerSurplusPokerCount() - sellPokerList.size());
}
currentRoomInfo.setRecentPlayerName(clientNickname);
currentRoomInfo.setRecentPokers(sellPokerList);
// 视图更新
String nextPlayerName = jsonObject.getString("sellClinetNickname");
RoomMethod method = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
method.showPokers(clientNickname, sellPokerList);
if (nextPlayerName != null) {
method.play(nextPlayerName);
}
});
}
}
@@ -1,27 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONArray;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.entity.RoomInfo;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyMethod;
import java.util.List;
public class ClientShowRoomsListner extends AbstractClientListener {
public ClientShowRoomsListner() {
super(ClientEventCode.CODE_SHOW_ROOMS);
}
@Override
public void handle(Channel channel, String json) {
List<RoomInfo> rooms = JSONArray.parseArray(json, RoomInfo.class);
LobbyMethod method = (LobbyMethod) uiService.getMethod(LobbyController.METHOD_NAME);
Platform.runLater(() -> method.showRoomList(rooms));
}
}
@@ -1,65 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.listener;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import javafx.application.Platform;
import org.nico.ratel.landlords.entity.ClientSide;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientEventCode;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.lobby.LobbyController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomController;
import priv.zxw.ratel.landlords.client.javafx.ui.view.room.RoomMethod;
import java.util.List;
public class ClientStartGameListener extends AbstractClientListener {
public ClientStartGameListener() {
super(ClientEventCode.CODE_GAME_STARTING);
}
@Override
public void handle(Channel channel, String json) {
JSONObject jsonObject = JSONObject.parseObject(json);
// 设置用户信息和当前对局房间信息
User user = BeanUtil.getBean("user");
user.addPokers(jsonObject.getJSONArray("pokers").toJavaList(Poker.class));
user.joinRoom(jsonObject.getIntValue("roomId"));
CurrentRoomInfo currentRoomInfo = new CurrentRoomInfo(jsonObject.getIntValue("roomId"),
jsonObject.getString("roomOwner"));
currentRoomInfo.setPlayer(user);
currentRoomInfo.setPrevPlayerSurplusPokerCount(17);
currentRoomInfo.setNextPlayerSurplusPokerCount(17);
BeanUtil.addBean("currentRoomInfo", currentRoomInfo);
// 计算出玩家的顺序
List<ClientSide> clientOrderList = jsonObject.getJSONArray("clientOrderList").toJavaList(ClientSide.class);
ClientSide clientSide = clientOrderList.stream().filter(c -> user.getNickname().equals(c.getNickname())).findFirst().get();
currentRoomInfo.setPrevPlayerName(clientSide.getPre().getNickname());
currentRoomInfo.setNextPlayerName(clientSide.getNext().getNickname());
// 更新试图
Method lobbyMethod = uiService.getMethod(LobbyController.METHOD_NAME);
RoomMethod roomMethod = (RoomMethod) uiService.getMethod(RoomController.METHOD_NAME);
Platform.runLater(() -> {
// 客户端加入房间时,可能没有触发 joinRoomSuccessful 的事件
// 导致视图未正常切换,判断视图是否切换,否则进行试图切换
if (!roomMethod.isShow()) {
lobbyMethod.doClose();
roomMethod.joinRoom();
}
roomMethod.startGame(user.getPokers());
});
// 触发抢地主(CODE_GAME_LANDLORD_ELECT)事件
ClientListenerUtils.getListener(ClientEventCode.CODE_GAME_LANDLORD_ELECT).handle(channel, json);
}
}
@@ -1,21 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import java.util.HashMap;
import java.util.Map;
public class UIService {
private Map<String, Method> methodMap = new HashMap<>(16);
public void addMethods(Method... methods) {
for (Method method : methods) {
methodMap.put(method.getName(), method);
}
}
public Method getMethod(String name) {
return methodMap.get(name);
}
}
@@ -1,7 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.event;
public interface IIndexEvent {
void connect(String host, int port) throws Exception;
}
@@ -1,17 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.event;
public interface ILobbyEvent {
void selectPVPModal();
void selectPVEModal();
void createPVPRoom();
void createPVERoom(int modal);
void showRooms();
void joinRoom(int roomId);
}
@@ -1,7 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.event;
public interface ILoginEvent {
void setNickname(String nickname);
}
@@ -1,17 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.event;
import org.nico.ratel.landlords.entity.Poker;
import java.util.List;
public interface IRoomEvent {
void robLandlord();
void notRobLandlord();
void submitPokers(List<Poker> pokerList);
void passRound();
void exit();
}
@@ -1,29 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view;
import javafx.scene.control.Alert;
public class AlertUtils {
public static void info(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.INFORMATION, headerText, contentText);
}
private static void createAndShowAlert(Alert.AlertType alertType,
String headerText, String contentText) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(Alert.AlertType.INFORMATION.equals(alertType) ? "信息" :
Alert.AlertType.WARNING.equals(alertType) ? "警告" : "错误");
alert.setHeaderText(headerText);
alert.setContentText(contentText);
alert.showAndWait();
}
public static void warn(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.WARNING, headerText, contentText);
}
public static void error(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.ERROR, headerText, contentText);
}
}
@@ -1,93 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view;
import javafx.scene.Node;
import java.util.Objects;
import java.util.function.Consumer;
public class CountDownTask {
public static final int DEFAULT_TIME_OUT = 30;
private Consumer<Node> finallyExecuteConsumer;
private Consumer<Integer> preSecondExecuteConsumer;
private Node targetElement;
private int duration;
public CountDownTask(Node targetElement,
Consumer<Node> finallyExecuteConsumer, Consumer<Integer> preSecondExecuteConsumer) {
this.finallyExecuteConsumer = finallyExecuteConsumer;
this.preSecondExecuteConsumer = preSecondExecuteConsumer;
this.targetElement = targetElement;
}
public CountDownTask(Node targetElement, int duration,
Consumer<Node> finallyExecuteConsumer, Consumer<Integer> preSecondExecuteConsumer) {
Objects.requireNonNull(finallyExecuteConsumer);
this.finallyExecuteConsumer = finallyExecuteConsumer;
this.preSecondExecuteConsumer = preSecondExecuteConsumer;
this.duration = duration < 0 ? DEFAULT_TIME_OUT : duration;
this.targetElement = targetElement;
}
public CountDownFuture start() {
targetElement.setVisible(true);
CountDownFuture future = new CountDownFuture();
future.start();
return future;
}
public class CountDownFuture extends Thread {
private volatile boolean done = false;
private CountDownFuture() {
setDaemon(true);
}
@Override
public void run() {
long startTimeMillis = System.currentTimeMillis();
long interval;
try {
while (true) {
long currentTimeMillis = System.currentTimeMillis();
interval = (currentTimeMillis - startTimeMillis) / 1000;
if (interval > duration) {
break;
}
preSecondExecuteConsumer.accept((int) (duration - interval));
sleep(1000L);
}
finallyExecuteConsumer.accept(targetElement);
} catch (InterruptedException cancelFlag) {
// exit
return;
} finally {
done = true;
targetElement.setVisible(false);
}
}
public void cancel() {
if (done) {
return;
}
done = true;
interrupt();
}
public boolean isDone() {
return done;
}
}
}
@@ -1,7 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view;
public interface EventRegister {
void registerEvent();
}
@@ -1,10 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view;
public interface Method {
String getName();
void doShow();
void doClose();
}
@@ -1,101 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view;
import javafx.animation.FadeTransition;
import javafx.application.Platform;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.stage.Stage;
import javafx.util.Duration;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.NettyClient;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
public abstract class UIObject extends Stage {
protected Parent root;
private ExecutorService animationExecutorService = Executors.newFixedThreadPool(2);
public UIObject() {
setTitle("ratel javafx客户端");
// 退出程序
setOnCloseRequest(e -> closeApplication());
}
private void closeApplication() {
// 关闭视图
close();
Platform.exit();
// 关闭用于动画执行的线程池
animationExecutorService.shutdownNow();
// 关闭netty
NettyClient nettyClient = BeanUtil.getBean("nettyClient");
if (nettyClient != null) {
nettyClient.destroy();
}
}
public <T> T $(String id, Class<T> clazz) {
return (T) root.lookup("#" + id);
}
public void delayShow(Node node, int secondDelay) {
animationExecutorService.execute(new DelayRunnable(node, n -> n.setVisible(true), secondDelay));
}
public void delayHidden(Node node, int secondDelay) {
animationExecutorService.execute(new DelayRunnable(node, n -> {
// 动画过程中的元素是无效的,不能被操作的
n.setDisable(true);
useTransition(n);
n.setDisable(false);
n.setVisible(false);
}, secondDelay));
}
private class DelayRunnable implements Runnable {
private Object monitor = new Object();
private Node node;
private Consumer<Node> operate;
private int delayTimes;
DelayRunnable(Node node, Consumer<Node> operate, int delayTimes) {
this.node = node;
this.operate = operate;
this.delayTimes = delayTimes;
}
@Override
public void run() {
try {
synchronized (monitor) {
monitor.wait(delayTimes * 1000L);
}
} catch (InterruptedException e) {
Thread.currentThread().isInterrupted();
}
operate.accept(node);
}
}
private void useTransition(Node node) {
FadeTransition fade = new FadeTransition();
fade.setDuration(Duration.millis(1000));
fade.setFromValue(1);
fade.setToValue(0.1);
fade.setCycleCount(1000);
fade.setAutoReverse(true);
fade.setNode(node);
fade.play();
}
public abstract void registerEvent();
}
@@ -1,83 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.index;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IIndexEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
import java.io.IOException;
import java.util.List;
public class IndexController extends UIObject implements IndexMethod {
public static final String METHOD_NAME = "index";
private static final String RESOURCE_NAME = "view/index.fxml";
private IIndexEvent indexEvent;
private IndexEventRegister eventRegister;
public IndexController(IIndexEvent indexEvent) throws IOException {
super();
this.indexEvent = indexEvent;
root = FXMLLoader.load(getClass().getClassLoader().getResource(RESOURCE_NAME));
setScene(new Scene(root));
registerEvent();
}
@Override
public void generateRemoteServerAddressOptions(List<String> remoteServerAddressList) {
Pane remoteServerListPane = $("remoteServerListPane", Pane.class);
for (int i = 0, size = remoteServerAddressList.size(); i < size; i++) {
Label serverAddressLabel = new ServerAddressLabel(remoteServerAddressList.get(i), i).getLabel();
serverAddressLabel.setOnMouseClicked(e -> {
Label label = (Label) e.getSource();
String remoteServerAddress = label.getText().trim();
String[] strs = remoteServerAddress.split(":");
$("host", TextField.class).setText(strs[0]);
$("port", TextField.class).setText(strs[1]);
});
remoteServerListPane.getChildren().add(serverAddressLabel);
}
}
@Override
public void setFetchRemoteServerAddressErrorTips() {
$("fetchServerAddressErrorTips", TextArea.class).setVisible(true);
}
@Override
public void setConnectServerErrorTips() {
$("connectServerErrorTips", Label.class).setVisible(true);
}
@Override
public String getName() {
return METHOD_NAME;
}
@Override
public void doShow() {
super.show();
}
@Override
public void doClose() {
super.close();
}
@Override
public void registerEvent() {
eventRegister = new IndexEventRegister(this, indexEvent);
}
}
@@ -1,44 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.index;
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IIndexEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.EventRegister;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
public class IndexEventRegister implements EventRegister {
private static final Logger LOGGER = LoggerFactory.getLogger(IndexEventRegister.class);
private UIObject uiObject;
private IIndexEvent indexEvent;
public IndexEventRegister(UIObject uiObject, IIndexEvent indexEvent) {
this.uiObject = uiObject;
this.indexEvent = indexEvent;
registerEvent();
}
@Override
public void registerEvent() {
connectServer();
}
private void connectServer() {
uiObject.$("connectButton", Button.class).setOnAction(e -> {
String host = uiObject.$("host", TextField.class).getText().trim();
int port = Integer.parseInt(uiObject.$("port", TextField.class).getText().trim());
try {
indexEvent.connect(host, port);
} catch (Exception ex) {
LOGGER.error(String.format("连接netty服务端(%s:%d)失败", host, port), ex);
Platform.runLater(() -> ((IndexMethod) uiObject).setConnectServerErrorTips());
}
});
}
}
@@ -1,13 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.index;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import java.util.List;
public interface IndexMethod extends Method {
void generateRemoteServerAddressOptions(List<String> remoteServerAddressList);
void setFetchRemoteServerAddressErrorTips();
void setConnectServerErrorTips();
}
@@ -1,19 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.index;
import javafx.scene.control.Label;
public class ServerAddressLabel {
private Label label;
public ServerAddressLabel(String serverAddress, int index) {
label = new Label();
label.setText(serverAddress);
label.setLayoutY(index * 30);
label.getStyleClass().add("remoteServerOption");
}
public Label getLabel() {
return label;
}
}
@@ -1,91 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.lobby;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import priv.zxw.ratel.landlords.client.javafx.entity.RoomInfo;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILobbyEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.AlertUtils;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
import java.io.IOException;
import java.util.List;
public class LobbyController extends UIObject implements LobbyMethod {
public static final String METHOD_NAME = "lobby";
private static final String RESOURCE_NAME = "view/lobby.fxml";
private ILobbyEvent lobbyEvent;
private LobbyEventRegister lobbyEventRegister;
public LobbyController(ILobbyEvent lobbyEvent) throws IOException {
super();
root = FXMLLoader.load(getClass().getClassLoader().getResource(RESOURCE_NAME));
setScene(new Scene(root));
this.lobbyEvent = lobbyEvent;
registerEvent();
}
@Override
public void registerEvent() {
lobbyEventRegister = new LobbyEventRegister(this, lobbyEvent);
}
@Override
public void toggleToPVPMenu() {
Pane modalPane = $("modalPane", Pane.class);
modalPane.setVisible(false);
Pane pvpMenuPane = $("pvpMenuPane", Pane.class);
pvpMenuPane.setVisible(true);
}
@Override
public void toggleToPVEMenu() {
Pane modalPane = $("modalPane", Pane.class);
modalPane.setVisible(false);
Pane pveMenuPane = $("pveMenuPane", Pane.class);
pveMenuPane.setVisible(true);
}
@Override
public void showRoomList(List<RoomInfo> roomInfoList) {
Pane roomsPane = $("roomsPane", Pane.class);
for (int i = 0, size = roomInfoList.size(); i < size; i++) {
RoomInfo roomInfo = roomInfoList.get(i);
Pane roomPane = new RoomPane(roomInfo, i).getPane();
roomPane.setOnMouseClicked(e -> lobbyEvent.joinRoom(roomInfo.getRoomId()));
roomsPane.getChildren().add(roomPane);
}
}
@Override
public void joinRoomFail(String message, String commentMessage) {
AlertUtils.warn(message, commentMessage);
}
@Override
public String getName() {
return METHOD_NAME;
}
@Override
public void doShow() {
super.show();
}
@Override
public void doClose() {
super.close();
}
}
@@ -1,50 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.lobby;
import javafx.scene.control.Button;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILobbyEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.EventRegister;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
public class LobbyEventRegister implements EventRegister {
private UIObject uiObject;
private ILobbyEvent lobbyEvent;
public LobbyEventRegister(UIObject uiObject, ILobbyEvent lobbyEvent) {
this.uiObject = uiObject;
this.lobbyEvent = lobbyEvent;
registerEvent();
}
@Override
public void registerEvent() {
selectPVPModal();
selectPVEModal();
createPVPRoom();
createPVERoom();
}
private void selectPVPModal() {
uiObject.$("pvpModalButton", Button.class).setOnAction(e -> lobbyEvent.selectPVPModal());
}
private void selectPVEModal() {
uiObject.$("pveModalButton", Button.class).setOnAction(e -> lobbyEvent.selectPVEModal());
}
private void createPVPRoom() {
uiObject.$("createRoomButton", Button.class).setOnAction(e -> lobbyEvent.createPVPRoom());
}
private static final int SIMPLE_MODAL = 1;
private static final int NORMAL_MODAL = 2;
private static final int DIFFICULT_MODAL = 3;
private void createPVERoom() {
uiObject.$("simpleModalButton", Button.class).setOnAction(e -> lobbyEvent.createPVERoom(SIMPLE_MODAL));
uiObject.$("normalModalButton", Button.class).setOnAction(e -> lobbyEvent.createPVERoom(NORMAL_MODAL));
uiObject.$("difficultModalButton", Button.class).setOnAction(e -> lobbyEvent.createPVERoom(DIFFICULT_MODAL));
}
}
@@ -1,18 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.lobby;
import priv.zxw.ratel.landlords.client.javafx.entity.RoomInfo;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import java.util.List;
public interface LobbyMethod extends Method {
void toggleToPVPMenu();
void toggleToPVEMenu();
void showRoomList(List<RoomInfo> roomInfoList);
void joinRoomFail(String message, String commentMessage);
}
@@ -1,61 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.lobby;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import priv.zxw.ratel.landlords.client.javafx.entity.RoomInfo;
public class RoomPane {
private static final int MARGIN_TOP = 25;
private static final int MARGIN_LEFT = 40;
private Pane pane;
public RoomPane(RoomInfo roomInfo, int index) {
pane = new Pane();
pane.getStyleClass().add("roomPane");
pane.setLayoutX(35 + (index % 3) * (150 + MARGIN_LEFT));
pane.setLayoutY(65 + ((index / 3) * (120 + MARGIN_TOP)));
Label idLabel = new Label();
idLabel.setLayoutX(6);
idLabel.setLayoutY(3);
idLabel.getStyleClass().add("idLabel");
idLabel.setText(roomInfo.getRoomId().toString());
Label roomOwnerLabel = new Label();
roomOwnerLabel.setLayoutX(0);
roomOwnerLabel.setLayoutY(22);
roomOwnerLabel.getStyleClass().add("roomOwnerLabel");
Label roomOwnerNameLabel = new Label();
roomOwnerNameLabel.setLayoutX(34);
roomOwnerNameLabel.setLayoutY(32);
roomOwnerNameLabel.setText(roomInfo.getRoomOwner());
Label modalLabel = new Label();
modalLabel.setLayoutX(54);
modalLabel.setLayoutY(60);
modalLabel.getStyleClass().add("modalLabel");
modalLabel.setText(roomInfo.getRoomType());
Label playerCountLabel = new Label();
playerCountLabel.setLayoutX(60);
playerCountLabel.setLayoutY(100);
playerCountLabel.getStyleClass().add("playerCountLabel");
playerCountLabel.setText("当前人数:" + roomInfo.getRoomClientCount() + "/3");
ObservableList<Node> children = pane.getChildren();
children.add(idLabel);
children.add(roomOwnerLabel);
children.add(roomOwnerNameLabel);
children.add(modalLabel);
children.add(playerCountLabel);
}
public Pane getPane() {
return pane;
}
}
@@ -1,49 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.login;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILoginEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
import java.io.IOException;
public class LoginController extends UIObject implements Method {
public static final String METHOD_NAME = "login";
private static final String RESOURCE_NAME = "view/login.fxml";
private ILoginEvent loginEvent;
private LoginEventRegister loginEventRegister;
public LoginController(ILoginEvent loginEvent) throws IOException {
super();
root = FXMLLoader.load(getClass().getClassLoader().getResource(RESOURCE_NAME));
setScene(new Scene(root));
this.loginEvent = loginEvent;
registerEvent();
}
@Override
public void registerEvent() {
this.loginEventRegister = new LoginEventRegister(this, loginEvent);
}
@Override
public String getName() {
return METHOD_NAME;
}
@Override
public void doShow() {
super.show();
}
@Override
public void doClose() {
super.close();
}
}
@@ -1,39 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.login;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import priv.zxw.ratel.landlords.client.javafx.ui.event.ILoginEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.EventRegister;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
public class LoginEventRegister implements EventRegister {
private UIObject uiObject;
private ILoginEvent loginEvent;
public LoginEventRegister(UIObject uiObject, ILoginEvent loginEvent) {
this.uiObject = uiObject;
this.loginEvent = loginEvent;
registerEvent();
}
@Override
public void registerEvent() {
submitNickname();
}
private void submitNickname() {
TextField field = uiObject.$("nicknameInput", TextField.class);
uiObject.$("submitButton", Button.class).setOnAction(e -> {
String nickname = field.getText().trim();
loginEvent.setNickname(nickname);
});
}
private void verifyNickname() {
uiObject.$("input", TextField.class).setOnAction(e -> {});
}
}
@@ -1,162 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
public class PokerPane {
public static final int MARGIN_LEFT = 40;
private Poker poker;
// start at 0
private int index;
private int offsetX;
private Pane pane;
public PokerPane(int index, int offsetX, Poker poker) {
this.poker = poker;
this.index = index;
this.offsetX = offsetX;
if (PokerLevel.LEVEL_SMALL_KING.equals(poker.getLevel()) ||
PokerLevel.LEVEL_BIG_KING.equals(poker.getLevel())) {
createJokerPokerPane();
} else {
createNormalPokerPane();
}
pane.setOnMouseClicked(e -> {
double y = pane.getLayoutY();
boolean alreadyChecked = y == 0;
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
// 取消选中
if (alreadyChecked) {
pane.setLayoutY(y + 20);
currentRoomInfo.removeUncheckedPoker(poker);
}
// 选中
else {
pane.setLayoutY(y - 20);
currentRoomInfo.addCheckedPoker(poker);
}
});
}
private void createNormalPokerPane() {
pane = new Pane();
pane.getStyleClass().add("horizontal-poker");
pane.setLayoutX(index * MARGIN_LEFT + offsetX);
pane.setLayoutY(20);
Text level = new Text();
level.getStyleClass().add("level");
level.setLayoutX(8);
level.setLayoutY(34);
level.setText(poker.getLevel().getName());
Text typeSmall = new Text();
typeSmall.getStyleClass().add("type-small");
typeSmall.setLayoutX(8);
typeSmall.setLayoutY(60);
typeSmall.setText(poker.getType().getName());
Text typeBig = new Text();
typeBig.getStyleClass().add("type-big");
typeBig.setLayoutX(50);
typeBig.setLayoutY(120);
typeBig.setText(poker.getType().getName());
if (PokerType.CLUB.equals(poker.getType()) || PokerType.SPADE.equals(poker.getType())) {
level.setFill(Paint.valueOf("black"));
typeSmall.setFill(Paint.valueOf("black"));
typeBig.setFill(Paint.valueOf("black"));
} else if (PokerType.DIAMOND.equals(poker.getType()) || PokerType.HEART.equals(poker.getType())) {
level.setFill(Paint.valueOf("#9c2023"));
typeSmall.setFill(Paint.valueOf("#9c2023"));
typeBig.setFill(Paint.valueOf("#9c2023"));
}
ObservableList<Node> children = pane.getChildren();
children.add(level);
children.add(typeSmall);
children.add(typeBig);
}
private void createJokerPokerPane() {
pane = new Pane();
pane.getStyleClass().add("horizontal-poker");
pane.setLayoutX(index * MARGIN_LEFT + offsetX);
pane.setLayoutY(20);
Text text1 = new Text();
text1.getStyleClass().add("joker-level");
text1.setLayoutX(13);
text1.setLayoutY(26);
text1.setText("J");
Text text2 = new Text();
text2.getStyleClass().add("joker-level");
text2.setLayoutX(8);
text2.setLayoutY(44);
text2.setText("O");
Text text3 = new Text();
text3.getStyleClass().add("joker-level");
text3.setLayoutX(10);
text3.setLayoutY(62);
text3.setText("K");
Text text4 = new Text();
text4.getStyleClass().add("joker-level");
text4.setLayoutX(10);
text4.setLayoutY(80);
text4.setText("E");
Text text5 = new Text();
text5.getStyleClass().add("joker-level");
text5.setLayoutX(10);
text5.setLayoutY(98);
text5.setText("R");
Text logo = new Text();
logo.setLayoutX(40);
logo.setLayoutY(126);
logo.setStyle("-fx-font-size: 28");
logo.setStyle("-fx-text-fill: silver");
logo.setText("ratel");
if (PokerLevel.LEVEL_SMALL_KING.equals(poker.getLevel())) {
text1.setFill(Paint.valueOf("black"));
text2.setFill(Paint.valueOf("black"));
text3.setFill(Paint.valueOf("black"));
text4.setFill(Paint.valueOf("black"));
text5.setFill(Paint.valueOf("black"));
} else if (PokerLevel.LEVEL_BIG_KING.equals(poker.getLevel())) {
text1.setFill(Paint.valueOf("#9c2023"));
text2.setFill(Paint.valueOf("#9c2023"));
text3.setFill(Paint.valueOf("#9c2023"));
text4.setFill(Paint.valueOf("#9c2023"));
text5.setFill(Paint.valueOf("#9c2023"));
}
ObservableList<Node> children = pane.getChildren();
children.add(text1);
children.add(text2);
children.add(text3);
children.add(text4);
children.add(text5);
}
public Pane getPane() {
return pane;
}
}
@@ -1,452 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientType;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IRoomEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class RoomController extends UIObject implements RoomMethod {
public static final String METHOD_NAME = "room";
private static final String RESOURCE_NAME = "view/room.fxml";
private IRoomEvent roomEvent;
private RoomEventRegister roomEventDefine;
private PlayerPaneOperator prevPlayerPaneOperator;
private PlayerPaneOperator nextPlayerPaneOperator;
private PlayerPaneOperator playerPaneOperator;
public RoomController(IRoomEvent roomEvent) throws IOException {
super();
root = FXMLLoader.load(getClass().getClassLoader().getResource(RESOURCE_NAME));
setScene(new Scene(root));
this.roomEvent = roomEvent;
registerEvent();
prevPlayerPaneOperator = new PrevPlayerPaneOperator();
nextPlayerPaneOperator = new NextPlayerPaneOperator();
playerPaneOperator = new CurrentPlayerPaneOperator();
}
@Override
public void startGame(List<Poker> pokers) {
// 1,组件状态改变(遮蔽罩隐藏,游戏面板可用状态改变)
// 2,组件内容填充
// 3,元素隐藏
// 4,牌初始化(己方和对方)
$("waitingPane", Pane.class).setVisible(false);
$("playingPane", Pane.class).setDisable(false);
Button robButton = $("robButton", Button.class);
robButton.setText("抢地主");
robButton.setVisible(false);
Button notRobButton = $("notRobButton", Button.class);
notRobButton.setText("不抢");
notRobButton.setVisible(false);
$("prevPlayerPane", Pane.class).lookup(".tips").setVisible(false);
$("nextPlayerPane", Pane.class).lookup(".tips").setVisible(false);
$("quitButton", Button.class).setText("退出");
initPokers(pokers);
}
private static final int PER_PLAYER_DEFAULT_POKER_COUNT = 17;
private static final int SURPLUS_POKER_COUNT = 3;
private void initPokers(List<Poker> pokers) {
// 己方牌pane
refreshPlayPokers(pokers);
// 上下游牌pane
$("prevPlayerPokersPane", Pane.class).setVisible(true);
$("nextPlayerPokersPane", Pane.class).setVisible(true);
refreshPrevPlayerPokers(PER_PLAYER_DEFAULT_POKER_COUNT);
refreshNextPlayerPokers(PER_PLAYER_DEFAULT_POKER_COUNT);
// 底牌
Pane surplusPokersPane = $("surplusPokersPane", Pane.class);
surplusPokersPane.getChildren().clear();
for (int n = 0; n < SURPLUS_POKER_COUNT; n++) {
surplusPokersPane.getChildren().add(new SurplusPokerPane(n).getPane());
}
}
@Override
public void gameOver(String winnerName, ClientType winnerType) {
$("playingPane", Pane.class).setDisable(true);
Pane gameOverPane = $("gameOverPane", Pane.class);
gameOverPane.setVisible(true);
Text text = (Text) gameOverPane.lookup("#winnerInfo");
text.setText(String.format("游戏结束,%s胜利", ClientType.LANDLORD.equals(winnerType) ? "地主" : "农民"));
}
@Override
public void showPokers(String playerName, List<Poker> pokers) {
getPlayerPaneOperatorByPlayerName(playerName).showPokers(pokers);
}
private PlayerPaneOperator getPlayerPaneOperatorByPlayerName(String playerName) {
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
if (playerName.equals(currentRoomInfo.getPrevPlayerName())) {
return prevPlayerPaneOperator;
} else if (playerName.equals(currentRoomInfo.getNextPlayerName())) {
return nextPlayerPaneOperator;
} else if (playerName.equals(currentRoomInfo.getPlayer().getNickname())) {
return playerPaneOperator;
}
throw new IllegalStateException("当前房间没有 " + playerName + " 用户");
}
@Override
public void showMessage(String playerName, String message) {
getPlayerPaneOperatorByPlayerName(playerName).showMessage(message);
}
@Override
public void play(String playerName) {
getPlayerPaneOperatorByPlayerName(playerName).play();
}
@Override
public void refreshPlayPokers(List<Poker> pokers) {
final int pokersPaneWidth = 870;
final int pokerPaneWidth = 110;
int size = pokers.size();
// 第一张牌的x轴偏移量
int firstPokerPaneOffsetX = ((pokersPaneWidth - pokerPaneWidth) - PokerPane.MARGIN_LEFT * (size -1)) / 2;
Pane pokersPane = $("pokersPane", Pane.class);
// 可能之前有牌,先清理再填充
pokersPane.getChildren().clear();
for (int i = 0; i < size; i++) {
pokersPane.getChildren().add(new PokerPane(i, firstPokerPaneOffsetX, pokers.get(i)).getPane());
}
}
@Override
public void refreshPrevPlayerPokers(int pokerCount) {
Pane prevPlayerPokersPane = $("prevPlayerPokersPane", Pane.class);
((Label) prevPlayerPokersPane.lookup(".pokerCount")).setText(String.valueOf(pokerCount));
}
@Override
public void refreshNextPlayerPokers(int pokerCount) {
Pane nextPlayerPokersPane = $("nextPlayerPokersPane", Pane.class);
((Label) nextPlayerPokersPane.lookup(".pokerCount")).setText(String.valueOf(pokerCount));
}
@Override
public void showRobButtons() {
$("robButton", Button.class).setVisible(true);
$("notRobButton", Button.class).setVisible(true);
}
@Override
public void hideRobButtons() {
$("robButton", Button.class).setVisible(false);
$("notRobButton", Button.class).setVisible(false);
}
@Override
public void showSurplusPokers(List<Poker> surplusPokers) {
Pane surplusPokersPane = $("surplusPokersPane", Pane.class);
surplusPokersPane.getChildren().clear();
for (int n = 0, size = surplusPokers.size(); n < size; n++) {
Pane surplusPokerPane = new PokerPane(n, 0, surplusPokers.get(n)).getPane();
surplusPokerPane.setLayoutX(45 + n * (SurplusPokerPane.MARGIN_LEFT + 110));
surplusPokerPane.setLayoutY(0);
surplusPokersPane.getChildren().add(surplusPokerPane);
}
}
@Override
public void setLandLord(String landlordName) {
// 1,为地主加底牌(重新洗牌)
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
if (ClientType.LANDLORD.equals(currentRoomInfo.getPrevPlayerRole())) {
currentRoomInfo.setPrevPlayerSurplusPokerCount(PER_PLAYER_DEFAULT_POKER_COUNT + SURPLUS_POKER_COUNT);
currentRoomInfo.setNextPlayerSurplusPokerCount(PER_PLAYER_DEFAULT_POKER_COUNT);
refreshPrevPlayerPokers(PER_PLAYER_DEFAULT_POKER_COUNT + SURPLUS_POKER_COUNT);
} else if (ClientType.LANDLORD.equals(currentRoomInfo.getNextPlayerRole())) {
currentRoomInfo.setNextPlayerSurplusPokerCount(PER_PLAYER_DEFAULT_POKER_COUNT + SURPLUS_POKER_COUNT);
currentRoomInfo.setPrevPlayerSurplusPokerCount(PER_PLAYER_DEFAULT_POKER_COUNT);
refreshNextPlayerPokers(PER_PLAYER_DEFAULT_POKER_COUNT + SURPLUS_POKER_COUNT);
} else {
User user = BeanUtil.getBean("user");
refreshPlayPokers(user.getPokers());
}
// 2,显示每个人的角色(地主|农民)和姓名
$("prevPlayerRole", Label.class).setText(ClientType.LANDLORD.equals(currentRoomInfo.getPrevPlayerRole()) ? "地主" : "农民");
$("nextPlayerRole", Label.class).setText(ClientType.LANDLORD.equals(currentRoomInfo.getNextPlayerRole()) ? "地主" : "农民");
$("playerRole", Label.class).setText(ClientType.LANDLORD.equals(currentRoomInfo.getPlayer().getRole()) ? "地主" : "农民");
$("prevPlayerNickname", Label.class).setText(currentRoomInfo.getPrevPlayerName());
$("nextPlayerNickname", Label.class).setText(currentRoomInfo.getNextPlayerName());
$("playerNickname", Label.class).setText(currentRoomInfo.getPlayer().getNickname());
}
@Override
public void showPokerPlayButtons() {
$("submitButton", Button.class).setVisible(true);
$("passButton", Button.class).setVisible(true);
}
@Override
public void hidePokerPlayButtons() {
$("submitButton", Button.class).setVisible(false);
$("passButton", Button.class).setVisible(false);
}
@Override
public boolean isShow() {
return super.isShowing();
}
@Override
public void joinRoom() {
super.show();
}
@Override
public void doShow() {
super.show();
}
@Override
public void doClose() {
super.close();
}
@Override
public void registerEvent() {
roomEventDefine = new RoomEventRegister(this, roomEvent);
}
@Override
public String getName() {
return METHOD_NAME;
}
interface PlayerPaneOperator {
void showPokers(List<Poker> pokers);
void showMessage(String message);
void play();
}
private abstract class AbstractPlayerPaneOperator implements PlayerPaneOperator {
protected Pane playerShowPane;
protected Label timer;
protected Label tips;
protected Pane playerShowPokersPane;
protected Pane playerPokersPane;
protected CountDownTask.CountDownFuture future;
AbstractPlayerPaneOperator(String parentPaneId) {
this.playerShowPane = $(parentPaneId, Pane.class);
this.timer = (Label) playerShowPane.lookup(".timer");
}
@Override
public synchronized void showMessage(String message) {
if (future != null && !future.isDone()) {
future.cancel();
}
playerShowPokersPane.getChildren().clear();
tips.setText(message);
tips.setVisible(true);
}
@Override
public synchronized void play() {
playerShowPokersPane.getChildren().clear();
tips.setVisible(false);
if (future == null || future.isDone()) {
CountDownTask task = new CountDownTask(timer, 30,
node -> Platform.runLater(() -> hidePokerPlayButtons()),
surplusTime -> Platform.runLater(() -> timer.setText(surplusTime.toString())));
future = task.start();
}
}
@Override
public synchronized void showPokers(List<Poker> pokers) {
if (future != null && !future.isDone()) {
future.cancel();
}
tips.setVisible(false);
renderPokers(pokers);
refreshPlayerPokers(pokers);
}
protected abstract void renderPokers(List<Poker> pokers);
protected abstract void refreshPlayerPokers(List<Poker> pokers);
}
private class PrevPlayerPaneOperator extends AbstractPlayerPaneOperator {
PrevPlayerPaneOperator() {
super("prevPlayerShowPane");
this.tips = (Label) playerShowPane.lookup(".tips");
this.playerShowPokersPane = (Pane) playerShowPane.lookup("#prevPlayerShowPokersPane");
this.playerPokersPane = $("prevPlayerPokersPane", Pane.class);
}
@Override
public void renderPokers(List<Poker> pokers) {
final int maxPerRowPokerCount = 8;
for (int i = 0, size = pokers.size(); i < size; i++) {
ShowPokerPane pokerPane = new ShowPokerPane(pokers.get(i));
if (i < maxPerRowPokerCount) {
pokerPane.setLayout(i * ShowPokerPane.MARGIN_LEFT, 0);
} else {
pokerPane.setLayout((i % maxPerRowPokerCount) * ShowPokerPane.MARGIN_LEFT, ShowPokerPane.MARGIN_TOP);
}
playerShowPokersPane.getChildren().add(pokerPane.getPane());
}
}
@Override
protected void refreshPlayerPokers(List<Poker> pokers) {
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
refreshPrevPlayerPokers(currentRoomInfo.getPrevPlayerSurplusPokerCount());
}
}
private class NextPlayerPaneOperator extends AbstractPlayerPaneOperator {
NextPlayerPaneOperator() {
super("nextPlayerShowPane");
this.tips = (Label) playerShowPane.lookup(".tips");
this.playerShowPokersPane = (Pane) playerShowPane.lookup("#nextPlayerShowPokersPane");
this.playerPokersPane = $("nextPlayerPokersPane", Pane.class);
}
@Override
public void renderPokers(List<Poker> pokers) {
final int maxPerRowPokerCount = 8;
final int parentPaneWidth = 380;
final int showPokerPaneWidth = 40;
// 从右至左渲染牌
for (int i = pokers.size() - 1; i >= 0; i--) {
ShowPokerPane pokerPane = new ShowPokerPane(pokers.get(i));
int layoutX = parentPaneWidth - (showPokerPaneWidth + ShowPokerPane.MARGIN_LEFT * (i % maxPerRowPokerCount));
if (i < maxPerRowPokerCount) {
pokerPane.setLayout(layoutX, 0);
} else {
pokerPane.setLayout(layoutX, ShowPokerPane.MARGIN_TOP);
}
playerShowPokersPane.getChildren().add(pokerPane.getPane());
}
}
@Override
protected void refreshPlayerPokers(List<Poker> pokers) {
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
refreshNextPlayerPokers(currentRoomInfo.getNextPlayerSurplusPokerCount());
}
}
private class CurrentPlayerPaneOperator extends AbstractPlayerPaneOperator {
CurrentPlayerPaneOperator() {
super("playerShowPane");
this.tips = (Label) playerShowPane.lookup(".primary-tips");
this.playerShowPokersPane = (Pane) playerShowPane.lookup("#playerShowPokersPane");
this.playerPokersPane = $("pokersPane", Pane.class);
}
@Override
public void showMessage(String message) {
hidePokerPlayButtons();
super.showMessage(message);
}
@Override
public void showPokers(List<Poker> pokers) {
hidePokerPlayButtons();
super.showPokers(pokers);
}
@Override
public void play() {
super.play();
showPokerPlayButtons();
}
@Override
public void renderPokers(List<Poker> pokers) {
final int parentPaneWidth = 870;
final int showPokerPaneWidth = 40;
int size = pokers.size();
int offset = (parentPaneWidth - (showPokerPaneWidth + ShowPokerPane.MARGIN_LEFT * (size - 1))) / 2;
for (int i = 0; i < size; i++) {
ShowPokerPane pokerPane = new ShowPokerPane(pokers.get(i));
pokerPane.setLayout(offset + i * ShowPokerPane.MARGIN_LEFT, 0);
playerShowPokersPane.getChildren().add(pokerPane.getPane());
}
}
@Override
protected void refreshPlayerPokers(List<Poker> pokers) {
User user = BeanUtil.getBean("user");
refreshPlayPokers(user.getPokers());
}
}
}
@@ -1,79 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import javafx.scene.control.Button;
import org.nico.ratel.landlords.entity.Poker;
import priv.zxw.ratel.landlords.client.javafx.util.BeanUtil;
import priv.zxw.ratel.landlords.client.javafx.entity.CurrentRoomInfo;
import priv.zxw.ratel.landlords.client.javafx.entity.User;
import priv.zxw.ratel.landlords.client.javafx.ui.event.IRoomEvent;
import priv.zxw.ratel.landlords.client.javafx.ui.view.util.CountDownTask;
import priv.zxw.ratel.landlords.client.javafx.ui.view.EventRegister;
import priv.zxw.ratel.landlords.client.javafx.ui.view.UIObject;
import java.util.List;
public class RoomEventRegister implements EventRegister {
private UIObject uiObject;
private IRoomEvent roomEvent;
public RoomEventRegister(UIObject uiObject, IRoomEvent roomEvent) {
this.uiObject = uiObject;
this.roomEvent = roomEvent;
registerEvent();
}
@Override
public void registerEvent() {
robLandlord();
notRobLandlord();
submitPokers();
passRound();
back2Lobby();
}
private void robLandlord() {
uiObject.$("robButton", Button.class).setOnAction(e -> {
RoomController roomController = (RoomController) uiObject;
roomController.hideRobButtons();
roomEvent.robLandlord();
});
}
private void notRobLandlord() {
uiObject.$("notRobButton", Button.class).setOnAction(e -> {
RoomController roomController = (RoomController) uiObject;
roomController.hideRobButtons();
roomEvent.notRobLandlord();
});
}
private void submitPokers() {
uiObject.$("submitButton", Button.class).setOnAction(e -> {
CurrentRoomInfo currentRoomInfo = BeanUtil.getBean("currentRoomInfo");
List<Poker> checkedPokers = currentRoomInfo.pollCheckedPokers();
if (checkedPokers.isEmpty()) {
return;
}
// 执行对应的事件
roomEvent.submitPokers(checkedPokers);
});
}
private void passRound() {
uiObject.$("passButton", Button.class).setOnAction(e -> {
roomEvent.passRound();
});
}
private void back2Lobby() {
uiObject.$("quitButton", Button.class).setOnAction(e -> roomEvent.exit());
uiObject.$("backLobbyButton", Button.class).setOnAction(e -> roomEvent.exit());
}
}
@@ -1,42 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.ClientType;
import priv.zxw.ratel.landlords.client.javafx.ui.view.Method;
import java.util.List;
public interface RoomMethod extends Method {
boolean isShow();
void joinRoom();
void startGame(List<Poker> pokers);
void gameOver(String winnerName, ClientType winnerType);
void showPokers(String playerName, List<Poker> pokers);
void showMessage(String playerName, String message);
void play(String playerName);
void refreshPlayPokers(List<Poker> pokers);
void refreshPrevPlayerPokers(int pokerCount);
void refreshNextPlayerPokers(int pokerCount);
void showRobButtons();
void hideRobButtons();
void showSurplusPokers(List<Poker> surplusPokers);
void setLandLord(String landlordName);
void showPokerPlayButtons();
void hidePokerPlayButtons();
}
@@ -1,102 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Paint;
import org.nico.ratel.landlords.entity.Poker;
import org.nico.ratel.landlords.enums.PokerLevel;
import org.nico.ratel.landlords.enums.PokerType;
public class ShowPokerPane {
public static final int MARGIN_LEFT = 30;
public static final int MARGIN_TOP = 40;
private Poker poker;
private Pane pane;
public ShowPokerPane(Poker poker) {
this.poker = poker;
if (PokerLevel.LEVEL_SMALL_KING.equals(poker.getLevel()) ||
PokerLevel.LEVEL_BIG_KING.equals(poker.getLevel())) {
createJokerPokerPane();
} else {
createNormalPokerPane();
}
}
private void createNormalPokerPane() {
pane = new Pane();
pane.getStyleClass().add("showPoker");
Label level = new Label();
level.setLayoutX(2);
level.setLayoutY(-2);
level.setText(poker.getLevel().getName());
level.getStyleClass().add("level");
Label type = new Label();
type.setLayoutX(2);
type.setLayoutY(12);
type.setText(poker.getType().getName());
type.getStyleClass().add("type-small");
if (PokerType.CLUB.equals(poker.getType()) || PokerType.SPADE.equals(poker.getType())) {
level.setStyle("-fx-text-fill: black");
type.setStyle("-fx-text-fill: black");
} else if (PokerType.DIAMOND.equals(poker.getType()) || PokerType.HEART.equals(poker.getType())) {
level.setStyle("-fx-text-fill: #9c2023");
type.setStyle("-fx-text-fill: #9c2023");
}
pane.getChildren().add(level);
pane.getChildren().add(type);
}
private void createJokerPokerPane() {
pane = new Pane();
pane.getStyleClass().add("showPoker");
Label label1 = new Label();
label1.setLayoutX(6);
label1.setLayoutY(0);
label1.setText("J");
label1.getStyleClass().add("joker-level");
Label label2 = new Label();
label2.setLayoutX(4);
label2.setLayoutY(13);
label2.setText("O");
label2.getStyleClass().add("joker-level");
Label label3 = new Label();
label3.setLayoutX(5);
label3.setLayoutY(26);
label3.setText("K");
label3.getStyleClass().add("joker-level");
if (PokerLevel.LEVEL_SMALL_KING.equals(poker.getLevel())) {
label1.setStyle("-fx-text-fill: black");
label2.setStyle("-fx-text-fill: black");
label3.setStyle("-fx-text-fill: black");
} else if (PokerLevel.LEVEL_BIG_KING.equals(poker.getLevel())) {
label1.setStyle("-fx-text-fill: #9c2023");
label2.setStyle("-fx-text-fill: #9c2023");
label3.setStyle("-fx-text-fill: #9c2023");
}
pane.getChildren().add(label1);
pane.getChildren().add(label2);
pane.getChildren().add(label3);
}
public void setLayout(double x, double y) {
pane.setLayoutX(x);
pane.setLayoutY(y);
}
public Pane getPane() {
return pane;
}
}
@@ -1,23 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.room;
import javafx.scene.layout.Pane;
public class SurplusPokerPane {
public static final double MARGIN_LEFT = 40;
private int index;
private Pane pane;
public SurplusPokerPane(int index) {
this.index = index;
pane = new Pane();
pane.getStyleClass().add("surplus-poker");
pane.setLayoutX(45 + index * (MARGIN_LEFT + 110));
}
public Pane getPane() {
return pane;
}
}
@@ -1,29 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.util;
import javafx.scene.control.Alert;
public class AlertUtils {
public static void info(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.INFORMATION, headerText, contentText);
}
private static void createAndShowAlert(Alert.AlertType alertType,
String headerText, String contentText) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setTitle(Alert.AlertType.INFORMATION.equals(alertType) ? "信息" :
Alert.AlertType.WARNING.equals(alertType) ? "警告" : "错误");
alert.setHeaderText(headerText);
alert.setContentText(contentText);
alert.showAndWait();
}
public static void warn(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.WARNING, headerText, contentText);
}
public static void error(String headerText, String contentText) {
createAndShowAlert(Alert.AlertType.ERROR, headerText, contentText);
}
}
@@ -1,93 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.ui.view.util;
import javafx.scene.Node;
import java.util.Objects;
import java.util.function.Consumer;
public class CountDownTask {
public static final int DEFAULT_TIME_OUT = 30;
private Consumer<Node> finallyExecuteConsumer;
private Consumer<Integer> preSecondExecuteConsumer;
private Node targetElement;
private int duration;
public CountDownTask(Node targetElement,
Consumer<Node> finallyExecuteConsumer, Consumer<Integer> preSecondExecuteConsumer) {
this.finallyExecuteConsumer = finallyExecuteConsumer;
this.preSecondExecuteConsumer = preSecondExecuteConsumer;
this.targetElement = targetElement;
}
public CountDownTask(Node targetElement, int duration,
Consumer<Node> finallyExecuteConsumer, Consumer<Integer> preSecondExecuteConsumer) {
Objects.requireNonNull(finallyExecuteConsumer);
this.finallyExecuteConsumer = finallyExecuteConsumer;
this.preSecondExecuteConsumer = preSecondExecuteConsumer;
this.duration = duration < 0 ? DEFAULT_TIME_OUT : duration;
this.targetElement = targetElement;
}
public CountDownFuture start() {
targetElement.setVisible(true);
CountDownFuture future = new CountDownFuture();
future.start();
return future;
}
public class CountDownFuture extends Thread {
private volatile boolean done = false;
private CountDownFuture() {
setDaemon(true);
}
@Override
public void run() {
long startTimeMillis = System.currentTimeMillis();
long interval;
try {
while (true) {
long currentTimeMillis = System.currentTimeMillis();
interval = (currentTimeMillis - startTimeMillis) / 1000;
if (interval > duration) {
break;
}
preSecondExecuteConsumer.accept((int) (duration - interval));
sleep(1000L);
}
finallyExecuteConsumer.accept(targetElement);
} catch (InterruptedException cancelFlag) {
// exit
return;
} finally {
done = true;
targetElement.setVisible(false);
}
}
public void cancel() {
if (done) {
return;
}
done = true;
interrupt();
}
public boolean isDone() {
return done;
}
}
}
@@ -1,17 +0,0 @@
package priv.zxw.ratel.landlords.client.javafx.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class BeanUtil {
private static final Map<String, Object> CACHE_MAP = new ConcurrentHashMap<>();
public static void addBean(String name, Object object) {
CACHE_MAP.put(name, object);
}
public static <T> T getBean(String name) {
return (T) CACHE_MAP.get(name);
}
}
@@ -1,93 +0,0 @@
#appInfoPane {
-fx-pref-width: 280;
-fx-pref-height: 80;
}
#welcomeTips,
#version {
-fx-font-size: 16;
-fx-font-family: "微软雅黑";
}
#connectPane {
-fx-pref-width: 280;
-fx-pref-height: 240;
-fx-background-color: silver;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
#connectButton {
-fx-background-color: #40b1f5;
-fx-border-width: 1;
-fx-border-radius: 5;
-fx-background-radius: 5;
-fx-border-color: #40b1f5;
-fx-text-fill: #000000;
-fx-font-size: 16;
-fx-cursor: hand;
}
#remoteServerInfoPane {
-fx-pref-width: 280;
-fx-pref-height: 340;
-fx-background-color: silver;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
#remoteServerListPane {
-fx-pref-width: 280;
-fx-pref-height: 300;
-fx-background-color: white;
}
#fetchServerAddressErrorTips {
-fx-pref-width: 260;
-fx-pref-height: 100;
-fx-wrap-text: true;
-fx-text-fill: red;
}
.title {
-fx-font-size: 24;
-fx-alignment: center;
-fx-font-family: "微软雅黑";
}
.hostPortInput {
-fx-border-width: 0;
-fx-background-color: #dbd9d8;
-fx-background-radius: 8;
-fx-font-family: "微软雅黑";
-fx-text-fill: #000000;
-fx-font-size: 14;
}
.hostPortInput:focused {
-fx-border-width: 2;
-fx-border-color: #dbd9d8;
-fx-border-radius: 8;
-fx-background-color: #f6f6f5;
}
.forLabel {
-fx-text-alignment: center;
-fx-font-size: 20;
}
.remoteServerOption {
-fx-alignment: center;
-fx-pref-width: 260;
-fx-pref-height: 30;
-fx-background-color: silver;
-fx-border-color: #dbd9d8;
-fx-border-width: 1;
-fx-border-radius: 8;
-fx-background-radius: 8;
-fx-cursor: hand;
}
.remoteServerOption:hover {
-fx-background-color: #716f6d;
}
@@ -1,79 +0,0 @@
#pveMenuPane {
-fx-pref-width: 400;
-fx-pref-height: 600;
}
#pvpModalButton,
#pveModalButton {
-fx-pref-width: 200;
-fx-pref-height: 100;
}
#roomsPane {
-fx-pref-height: 400;
-fx-pref-width: 600;
}
#createRoomButton {
-fx-pref-width: 30;
-fx-pref-height: 30;
-fx-background-color: #dbd9d8;
-fx-border-width: 1;
-fx-border-radius: 5;
-fx-background-radius: 5;
-fx-border-color: #dbd9d8;
-fx-cursor: hand;
-fx-background-image: url("../image/add_0.png");
}
.title {
-fx-pref-width: 600;
-fx-pref-height: 40;
-fx-border-color: black;
-fx-border-width: 0 0 1 0;
}
.roomListTitle {
-fx-font-size: 20;
}
.roomPane {
-fx-pref-width: 150;
-fx-pref-height: 120;
-fx-border-color: #afadab;
-fx-background-color: #dddbd8;
-fx-background-radius: 10;
-fx-border-radius: 10;
-fx-cursor: hand;
}
.roomPane:hover {
-fx-border-color: #3f91af;
}
.roomPane > .idLabel {
-fx-font-size: 16;
-fx-border-color: black;
-fx-border-width: 0 0 1 0;
}
.roomPane > .roomOwnerLabel {
-fx-pref-width: 30;
-fx-pref-height: 30;
-fx-background-image: url("../image/face_0.png");
}
.roomPane > .modalLabel {
-fx-font-size: 30;
-fx-text-fill: silver;
-fx-opacity: 0.8;
}
.roomPane > .playerCountLabel {
}
.pveModalButton {
-fx-pref-width: 200;
-fx-pref-height: 40;
-fx-font-size: 20;
}
@@ -1,39 +0,0 @@
#nicknameInput {
-fx-pref-width: 260;
-fx-border-width: 0;
-fx-background-color: #dbd9d8;
-fx-background-radius: 8;
-fx-font-family: "微软雅黑";
-fx-text-fill: #000000;
-fx-font-size: 14;
}
#nicknameInput:focused {
-fx-border-width: 2;
-fx-border-color: #dbd9d8;
-fx-border-radius: 8;
-fx-background-color: #f6f6f5;
}
#submitButton {
-fx-background-color: #40b1f5;
-fx-border-width: 1;
-fx-border-radius: 5;
-fx-background-radius: 5;
-fx-border-color: #40b1f5;
-fx-text-fill: #000000;
-fx-font-size: 16;
-fx-cursor: hand;
}
.forLabel {
-fx-text-alignment: center;
-fx-font-size: 20;
}
.tips {
-fx-font-size: 17;
-fx-text-fill: brown;
-fx-border-width: 0 0 1 0;
-fx-border-color: black;
}
@@ -1,13 +0,0 @@
.horizontal-poker {
-fx-pref-width: 120;
-fx-pref-height: 140;
-fx-border-color: black;
/*-fx-background-color: #dddbd8;*/
-fx-background-color: red;
-fx-background-radius: 10;
-fx-border-radius: 10;
}
.vertical-poker {
}
@@ -1,250 +0,0 @@
#waitingPane,
#gameOverPane {
-fx-background-color: silver;
-fx-opacity: 0.8;
}
#waitingTips,
#winnerInfo {
-fx-font-size: 20;
}
#prevPlayerPane,
#nextPlayerPane {
-fx-pref-height: 140;
-fx-pref-width: 600;
}
#prevPlayerShowPane,
#nextPlayerShowPane {
-fx-pref-width: 380;
-fx-pref-height: 140;
}
#playerShowPane {
-fx-pref-width: 870;
-fx-pref-height: 130;
}
#surplusPokersPane {
-fx-pref-height: 140;
-fx-pref-width: 500;
-fx-background-color: silver;
-fx-background-radius: 0 0 10 10;
-fx-border-radius: 0 0 10 10;
}
#quitButton {
-fx-alignment: center;
-fx-pref-width: 80;
-fx-background-size: 43px 43px;
-fx-background-color: #40b1f5;
-fx-cursor: hand;
-fx-border-width: 1px;
-fx-text-fill: black;
-fx-font-size: 18px;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
#backLobbyButton {
-fx-alignment: center;
-fx-pref-width: 100;
-fx-background-size: 43px 43px;
-fx-background-color: #40b1f5;
-fx-cursor: hand;
-fx-border-width: 1px;
-fx-text-fill: black;
-fx-font-size: 18px;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
#robButton,
#notRobButton,
#submitButton,
#passButton {
-fx-alignment: center;
-fx-pref-width: 60;
-fx-pref-height: 30;
-fx-background-color: #40b1f5;
-fx-text-fill: black;
-fx-cursor: hand;
-fx-border-width: 1px;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
#prevPlayerRole,
#nextPlayerRole,
#playerRole {
-fx-alignment: center;
-fx-pref-width: 50;
-fx-pref-height: 25;
-fx-background-color: #a58a65;
-fx-text-fill: black;
-fx-border-color: #afadab;
-fx-background-radius: 6;
-fx-border-radius: 6;
}
#prevPlayerNickname,
#nextPlayerNickname,
#playerNickname {
-fx-alignment: center;
-fx-pref-width: 100;
-fx-pref-height: 25;
-fx-text-fill: black;
-fx-border-color: black;
-fx-border-width: 0 0 1 0;
}
.top {
-fx-pref-height: 150;
-fx-pref-width: 1200;
}
.middle {
-fx-pref-height: 140;
-fx-pref-width: 1200;
}
.bottom {
-fx-pref-height: 355;
-fx-pref-width: 1200;
}
.pokers {
-fx-alignment: center;
-fx-pref-width: 870;
-fx-pref-height: 180;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
.tips {
-fx-alignment: center;
-fx-pref-height: 30;
-fx-pref-width: 70;
-fx-font-size: 20;
-fx-text-fill: black;
-fx-background-color: silver;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
.primary-tips {
-fx-alignment: center;
-fx-pref-height: 30;
-fx-pref-width: 140;
-fx-background-color: silver;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
.error-tips {
-fx-alignment: center;
-fx-pref-height: 30;
-fx-pref-width: 200;
-fx-background-color: silver;
-fx-border-radius: 8;
-fx-background-radius: 8;
}
.horizontal-poker {
-fx-pref-width: 110;
-fx-pref-height: 140;
-fx-border-color: #afadab;
-fx-background-color: #dddbd8;
-fx-background-radius: 10;
-fx-border-radius: 10;
-fx-cursor: hand;
}
.horizontal-poker > .level {
-fx-font-size: 35;
-fx-text-fill: black;
}
.horizontal-poker > .joker-level {
-fx-font-size: 22;
}
.horizontal-poker > .type-small {
-fx-font-size: 35;
-fx-text-fill: black;
}
.horizontal-poker > .type-big {
-fx-font-size: 70;
-fx-text-fill: black;
}
.rearPoker {
-fx-pref-width: 55;
-fx-pref-height: 70;
-fx-border-color: #716f6d;
-fx-background-image: url("../image/rear.png");
-fx-background-color: transparent;
-fx-background-radius: 5;
-fx-border-radius: 5;
}
.rearPoker > .pokerCount {
-fx-font-size: 25;
-fx-text-fill: #000000;
}
.vertical-poker {
-fx-pref-width: 140;
-fx-pref-height: 90;
-fx-border-color: #716f6d;
-fx-background-image: url("../image/rear.png");
-fx-background-color: transparent;
}
.surplus-poker {
-fx-pref-width: 110;
-fx-pref-height: 140;
-fx-border-color: #716f6d;
-fx-background-image: url("../image/rear.png");
}
.timer {
-fx-alignment: center;
-fx-font-size: 20;
-fx-pref-width: 60;
-fx-pref-height: 50;
-fx-border-color: #afadab;
-fx-background-color: #dddbd8;
-fx-background-radius: 10;
-fx-border-radius: 10;
}
.showPoker {
-fx-pref-width: 40;
-fx-pref-height: 50;
-fx-border-color: #afadab;
-fx-background-color: #dddbd8;
-fx-background-radius: 6;
-fx-border-radius: 6;
}
.showPoker > .level {
-fx-font-size: 20;
-fx-text-fill: black;
}
.showPoker > .joker-level {
-fx-font-size: 15;
}
.showPoker > .type-small {
-fx-font-size: 20;
-fx-text-fill: black;
}
.showPoker > .type-big {
-fx-font-size: 40;
-fx-text-fill: black;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

@@ -1,41 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Text?>
<AnchorPane prefHeight="400.0" prefWidth="600.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" stylesheets="@assets/css/index.css">
<children>
<Pane fx:id="connectPane" layoutX="10" layoutY="20">
<Label layoutX="5" layoutY="5" styleClass="title">连接信息</Label>
<Label layoutX="5" layoutY="50" styleClass="forLabel">主机:</Label>
<TextField fx:id="host" layoutX="60" layoutY="50" styleClass="hostPortInput">127.0.0.1</TextField>
<Label layoutX="5" layoutY="90" styleClass="forLabel">端口:</Label>
<TextField fx:id="port" layoutX="60" layoutY="90" styleClass="hostPortInput">1024</TextField>
<Label fx:id="connectServerErrorTips" layoutX="5" layoutY="140" style="-fx-text-fill: red;" visible="false">连接失败,请确认上述地址是否正确</Label>
<Button fx:id="connectButton" layoutX="200" layoutY="160">连接</Button>
</Pane>
<Pane fx:id="appInfoPane" layoutX="10" layoutY="300">
<Text fx:id="welcomeTips" layoutX="5" layoutY="20">欢迎使用retel javafx客户端 : )</Text>
<Text fx:id="version" layoutX="5" layoutY="50">@versionv1.0.0</Text>
</Pane>
<Pane fx:id="remoteServerInfoPane" layoutX="310" layoutY="20">
<Label layoutX="68" layoutY="5" styleClass="forLabel">远程服务器信息</Label>
<Pane fx:id="remoteServerListPane" layoutY="40">
<ScrollBar orientation="VERTICAL" layoutX="260" max="5" min="0" value="0" prefHeight="300"></ScrollBar>
<TextArea fx:id="fetchServerAddressErrorTips" visible="false">
获取远程服务器地址失败(远程服务器地址清单链接为:https://raw.githubusercontent.com/ainilili/ratel/master/serverlist.json),请检查您的网络
</TextArea>
</Pane>
</Pane>
</children>
</AnchorPane>

Some files were not shown because too many files have changed in this diff Show More