diff --git a/src/Controller/Client.java b/src/Controller/Client.java index b4a77fe..7c8ad12 100644 --- a/src/Controller/Client.java +++ b/src/Controller/Client.java @@ -9,30 +9,21 @@ public class Client implements Runnable{ private Socket curSocket; - private ObjectOutputStream out; - private ObjectInputStream in; + private ObjectOutputStream objectOutputStream; + private ObjectInputStream objectInputStream; private SerializeObject obj = null; - private SerializeObject result = null; - private boolean flag = true; + private Object input = null; + private GameController gameController; - // 서버에 객체 전달 - public synchronized void returnObj (SerializeObject obj){ - this.obj = obj; - flag = false; - while(!flag){ - } - } - public SerializeObject getAnswer(){ - return result; + public Client(GameController gameController){ + this.gameController = gameController; } - - - public synchronized void setFlag() { - flag = true; - notify(); // 메인 스레드에 flag 변경 알림 + // 서버에 객체 전달 + public synchronized void returnObj (SerializeObject obj){ + this.obj = obj; } public void connect(String address, int port, String name) throws UnknownHostException, NotEmptySpaceException, OnProgressException{ @@ -40,10 +31,10 @@ public void connect(String address, int port, String name) throws UnknownHostExc System.out.println("연결을 시도합니다."); curSocket = new Socket(address, port); System.out.println(curSocket); - this.out = new ObjectOutputStream(curSocket.getOutputStream()); - this.in = new ObjectInputStream(curSocket.getInputStream()); + this.objectOutputStream = new ObjectOutputStream(curSocket.getOutputStream()); + this.objectInputStream = new ObjectInputStream(curSocket.getInputStream()); - SerializeObject answer = (SerializeObject)in.readObject(); + SerializeObject answer = (SerializeObject) objectInputStream.readObject(); String answerStr = (String)answer.getEventObject(); returnObj(new SerializeObject("received", "String")); if(answerStr.equals("방이 가득찼습니다.")) { @@ -55,7 +46,7 @@ else if(answerStr.equals("현재 게임이 진행중입니다.")){ System.out.println("서버에 연결되었습니다."); - out.writeObject(new SerializeObject(name, "String")); + objectOutputStream.writeObject(new SerializeObject(name, "String")); }catch (IOException e){ e.printStackTrace(); } catch (ClassNotFoundException e) { @@ -66,11 +57,15 @@ else if(answerStr.equals("현재 게임이 진행중입니다.")){ @Override public void run() { try { - while (obj != null) { - out.writeObject(obj); - result = (SerializeObject) in.readObject(); - obj = null; - setFlag(); + while (obj != null || (input = objectInputStream.readObject()) != null) { + // 입력 + if(obj != null) { + objectOutputStream.writeObject(obj); + obj = null; + } + else { + gameController.excuteQuery((SerializeObject) input, -1); + } } } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); diff --git a/src/Controller/ClientHandler.java b/src/Controller/ClientHandler.java new file mode 100644 index 0000000..33d649c --- /dev/null +++ b/src/Controller/ClientHandler.java @@ -0,0 +1,63 @@ +package Controller; + +import java.io.*; +import java.net.Socket; + +public class ClientHandler implements Runnable { + private Socket clientSocket; + private ObjectOutputStream objectOutputStream; + private ObjectInputStream objectInputStream; + private Object input = null; + + private Server server; + private int index; + private SerializeObject obj = null; + + + // 클라이언트에 객체 전달 + public void returnObj (SerializeObject obj){ + this.obj = obj; + } + + public void update(SerializeObject object){ + // 현재 오브젝트 파싱 및 처리 + server.notifiObservers(this, object); + } + + + public ClientHandler(Socket socket, Server server, int index) { + this.clientSocket = socket; + this.server = server; + this.index = index; + try { + objectOutputStream = new ObjectOutputStream(clientSocket.getOutputStream()); + objectInputStream = new ObjectInputStream(clientSocket.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void run() { + try { + while (obj != null || (input = objectInputStream.readObject()) != null) { + // 입력 + if(obj != null) { + objectOutputStream.writeObject(obj); + obj = null; + } + else { + update((SerializeObject) input); + } + } + } catch (IOException | ClassNotFoundException e) { + e.printStackTrace(); + } finally { + try { + clientSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff --git a/src/Controller/GameController.java b/src/Controller/GameController.java index 160e555..113e117 100644 --- a/src/Controller/GameController.java +++ b/src/Controller/GameController.java @@ -76,13 +76,15 @@ public void makeRoom() { public void connectRoom(String address) { - client = new Client(); + client = new Client(this); isServer = false; String name = view.getNameTF().getText(); + view.getLoginErrorLabel().setText("연결 중 입니다..."); try { + // TODO client.connect(address, PORT, name); + view.changePanel("RoomPanel"); - curPlayer = new Player(name); } catch (UnknownHostException e) { view.getLoginErrorLabel().setText("IP주소로 접속할 수 없습니다. IP주소를 다시 확인해주세요."); } catch (NotEmptySpaceException e){ @@ -91,6 +93,64 @@ public void connectRoom(String address) { view.getLoginErrorLabel().setText("현재 게임이 진행 중인 방입니다."); } } + + + // 플레이어 ready 상태 변경 함수 + public void changeReadyState(int index, Player.ReadyState readyState){ + // ready + if(readyState == Player.ReadyState.READY && players[index].getReadyState() == Player.ReadyState.NOT_READY){ + players[index].setReadyState(Player.ReadyState.READY); + } + // ready 해제 + else if(readyState == Player.ReadyState.NOT_READY && players[index].getReadyState() == Player.ReadyState.READY){ + players[index].setReadyState(Player.ReadyState.NOT_READY); + } + view.updateRoomReadyPanel(players[index].getReadyState(), index); + } + + // 플레이어 정보 변경 함수 + public void changePlayers(Player[] getPlayers){ + // Model 플레이어 변경 + players = getPlayers; + + // 플레이어 정보 UI 적용 + view.updatePlayers(players); + } + + + // 클라이언트로 넘어온 쿼리 실행 함수 + public void excuteQuery(SerializeObject object, int index){ + switch (object.getObjectType()){ + case "String" : + String content = (String)object.getEventObject(); + + break; + case "Player[]": + Player[] getPlayers = (Player[]) object.getEventObject(); + changePlayers(getPlayers); + break; + + case "Name": + if(isServer) { + String name = (String) object.getEventObject(); + players[index].setName(name); + server.notifiObservers(players[index].getClientHandler(), new SerializeObject(players, "Player[]")); + } + break; + + case "ReadyState" : + if(isServer) { + Player.ReadyState readyState = (Player.ReadyState) object.getEventObject(); + changeReadyState(index, readyState); + server.notifiObservers(players[index].getClientHandler(), new SerializeObject(players, "Player[]")); + break; + } + default: + break; + } + + } + } diff --git a/src/Controller/Server.java b/src/Controller/Server.java index e644da4..acab1d3 100644 --- a/src/Controller/Server.java +++ b/src/Controller/Server.java @@ -10,17 +10,36 @@ public class Server { static int clientCnt = 0; static int port; - static ClientHandler[] handlers = new ClientHandler[GameController.MAX_PLAYER_COUNT]; - + static Player[] players; static private GameController gameController; public Server(int port, GameController gameController) { this.port = port; this.gameController = gameController; + players = gameController.getPlayers(); openServer(); } - static void openServer() { + + public void notifiObservers(ClientHandler clientHandler, SerializeObject object){ + for(int i = 0 ; i < GameController.MAX_PLAYER_COUNT ; i ++){ + if(players[i] == null || players[i].getClientHandler() == clientHandler) continue; + ClientHandler curHandler = players[i].getClientHandler(); + curHandler.returnObj(object); + } + } + + private void addPlayer(Socket clientSocket){ + clientCnt++; + int idx = clientCnt - 1; + ClientHandler curHandler = new ClientHandler(clientSocket, this, idx); + Thread clientThread = new Thread(curHandler); + clientThread.start(); + curHandler.returnObj(new SerializeObject("connected", "String")); + players[idx] = new Player("", curHandler); + } + + private void openServer() { Thread serverWaitThread = new Thread(new Runnable() { @Override @@ -40,14 +59,7 @@ public void run() { if (clientCnt < 4 || GameController.gameState == GameController.GameState.FINISHED) { // 클라이언트와 통신하는 스레드 생성 - ClientHandler curHandler = new ClientHandler(clientSocket); - clientCnt++; - handlers[clientCnt - 1] = curHandler; - Thread clientThread = new Thread(curHandler); - clientThread.start(); - curHandler.returnObj(new SerializeObject("connected", "String")); - String name = (String)curHandler.getAnswer().getEventObject(); // 플레이어 객체 받기 - gameController.getPlayers()[clientCnt - 1] = new Player(name); + addPlayer(clientSocket); } else { PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true); if(clientCnt >= 4) { @@ -69,64 +81,3 @@ public void run() { serverWaitThread.start(); } } - -class ClientHandler implements Runnable { - private Socket clientSocket; - private PrintWriter out; - private BufferedReader in; - private ObjectOutputStream objectOutputStream; - private ObjectInputStream objectInputStream; - private SerializeObject result = null; - private boolean flag = true; - - private SerializeObject obj = null; - - - // 클라이언트에 객체 전달 - public synchronized void returnObj (SerializeObject obj){ - this.obj = obj; - flag = false; - while(!flag){ - } - } - - public SerializeObject getAnswer(){ - return result; - } - - public synchronized void setFlag() { - flag = true; - notify(); // 메인 스레드에 flag 변경 알림 - } - - - public ClientHandler(Socket socket) { - this.clientSocket = socket; - try { - objectOutputStream = new ObjectOutputStream(clientSocket.getOutputStream()); - objectInputStream = new ObjectInputStream(clientSocket.getInputStream()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - @Override - public void run() { - try { - while (obj != null) { - objectOutputStream.writeObject(obj); - result = (SerializeObject) objectInputStream.readObject(); - obj = null; - setFlag(); - } - } catch (IOException | ClassNotFoundException e) { - e.printStackTrace(); - } finally { - try { - clientSocket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } -} diff --git a/src/Model/Player.java b/src/Model/Player.java index a32a4cf..5209259 100644 --- a/src/Model/Player.java +++ b/src/Model/Player.java @@ -1,20 +1,27 @@ package Model; +import Controller.ClientHandler; + import java.util.ArrayList; import java.util.List; -// 루미큐브 플레이어 객체 +// 루미큐브 플레이어의 내용을 담근 객체 + public class Player { + + public enum ReadyState{ + READY, NOT_READY; + } private String name; // 유저의 이름 + private ClientHandler clientHandler; private List tiles; // 유저가 가지고 있는 타일들 - private int playerIdx = -1; // players 인덱스 번호 - - private int handlerIdx = -1; // clientHandler 인덱스 번호 + private ReadyState readyState = ReadyState.NOT_READY; // 유저 클래스의 생성자 - public Player(String name) { + public Player(String name, ClientHandler clientHandler) { this.name = name; + this.clientHandler = clientHandler; this.tiles = new ArrayList<>(); // 타일 리스트 초기화 } @@ -23,6 +30,10 @@ public String getName() { return name; } + public void setName(String name){ + this.name = name; + } + // 유저가 가진 타일 리스트를 반환하는 메서드 public List getTiles() { return tiles; @@ -38,21 +49,20 @@ public void removeTile(Tile tile) { tiles.remove(tile); } - public int getHandlerIdx() { - return handlerIdx; + public void setReadyState(ReadyState changeReadyState){ + this.readyState = changeReadyState; } - public void setHandlerIdx(int handlerIdx) { - this.handlerIdx = handlerIdx; + public ReadyState getReadyState(){ + return readyState; } - public int getPlayerIdx() { - return playerIdx; + public ClientHandler getClientHandler() { + return clientHandler; } - public void setPlayerIdx(int playerIdx) { - this.playerIdx = playerIdx; + @Override + public String toString() { + return "name : " + name + " ReadyState : " + this.readyState; } - - // 추가 유저 행동 메서드 } diff --git a/src/RummikubMainFrame.java b/src/RummikubMainFrame.java deleted file mode 100644 index 052068b..0000000 --- a/src/RummikubMainFrame.java +++ /dev/null @@ -1,2 +0,0 @@ -public class RummikubMainFrame { -} diff --git a/src/View/GameView.java b/src/View/GameView.java index ad26106..0dae505 100644 --- a/src/View/GameView.java +++ b/src/View/GameView.java @@ -1,6 +1,7 @@ package View; import Controller.GameController; +import Model.Player; import java.awt.*; @@ -30,8 +31,36 @@ public class GameView { private JPanel[] roomReadyPanel = new JPanel[MAX_PLAYER_COUNT]; private JLabel[] roomNameLabel = new JLabel[MAX_PLAYER_COUNT]; + private JPanel[] roomPlayerPanel = new JPanel[MAX_PLAYER_COUNT]; + private GameController gameController; + public void updateRoomReadyPanel(Player.ReadyState readyState, int index){ + if(readyState == Player.ReadyState.READY){ + roomReadyPanel[index].setBackground(Color.green); + } + else{ + roomReadyPanel[index].setBackground(Color.red); + } + } + + public void updateNameLabel(String name, int index){ + roomNameLabel[index].setText(name); + } + + public void updatePlayers(Player[] players){ + for(int i = 0 ; i < MAX_PLAYER_COUNT ; i ++){ + if(players[i] != null){ + updateRoomReadyPanel(players[i].getReadyState(), i); + updateNameLabel(players[i].getName(), i); + } + else{ + roomPlayerPanel[i].setVisible(false); + } + } + + } + public void setGameController(GameController gameController){ this.gameController = gameController; } @@ -519,6 +548,7 @@ else if(address.isEmpty() || address.isBlank() || !isValidIP(address)){ for(int j = 0 ; j < 2 ; j ++) { JPanel RoomPlayerPanel = new JPanel(); + roomPlayerPanel[i * 2 + j] = RoomPlayerPanel; // RoomPlayerPanel.setBackground(Color.cyan); RoomPlayerPanel.setPreferredSize(new Dimension(550, 310)); roomRowPanel.add(RoomPlayerPanel);