Search code examples
javasocketsclient-serverserversocket

Program stop when server try to receive client data


I'm trying to make a simple multiplayer game in Greenfoot for a school project.

If I remove updatePosition(); in the player script, the server can move and the client gets the data. However, when I try to get the data from the client and call updatePosition(); in the player script, it stops when the server tries to call receiveInt(). The terminal of the server side shows "Works Server" "2" "Works Server" "2" and then the program stops on the client and server.

"GameManager":

import greenfoot.*;
import java.io.*;
import java.net.*;

import javax.swing.JOptionPane;
import java.util.ArrayList;

public class MyWorld extends World
{
    public Server server;
    public Client client;
    public boolean Server = false;

    /**
     * Constructor for objects of class MyWorld.
     * 
     */
    public MyWorld()
    {    
        super(600, 400, 1);
        Player player = new Player(this);
        addObject(player, getWidth()/2, getHeight()/2);
    }

    public void act()
    {
        if(Greenfoot.isKeyDown("q"))
        {
            if(Server)
            {
                server.close();
            }else
            {
                client.close();
            }
        }
    }

    public void init()
    {
        Object[] options = {"Server","Client"};
        int i = JOptionPane.showOptionDialog(null, "Host as server or join as client?", "Selection", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
        if(i == 0)
        {
            server = new Server(this);
            Server = true;

            Player2 player2 = new Player2();
            addObject(player2, 0, 0);
        }else if(i == 1)
        {
            client = new Client(this);
            
            Player2 player2 = new Player2();
            addObject(player2, 0, 0);
        }
    }

    public class Server
    {
        MyWorld myWorld;
        public ServerSocket serverSocket;
        public Socket skt;
        private ObjectInputStream inServer;
        private ObjectOutputStream outServer;
        public Server(MyWorld myWorl)
        {
            this.myWorld = myWorl;
            try
            {
                serverSocket = new ServerSocket(8888);
                skt = serverSocket.accept();
                inServer = new ObjectInputStream(skt.getInputStream());
                outServer = new ObjectOutputStream(skt.getOutputStream());
            }catch(IOException e)
            {
                close();
            }
        }

        public void sendInts(int ...arr) {
            try {
                outServer.writeObject(arr);
                Greenfoot.delay(1);
                outServer.flush();
            }
            catch(NullPointerException ex) {
            }
            catch(IOException ex) {
            }
        }

        public int[] receiveInts() {
            int[] datServer = null;
            try {
                datServer = (int[])inServer.readObject();
            }
            catch(ClassNotFoundException ex) {
                ex.printStackTrace();
                close();
            }
            catch(NullPointerException ex) {
                close();
            }
            catch(IOException ex) {
                close();
            }
            return datServer;
        }

        public void close()
        {
            try {
                outServer.close();
                inServer.close();
                skt.close();
                serverSocket.close();
            }
            catch(IOException ex) {
                throw new RuntimeException("Error closing streams...");
            }
        }
    }

    public class Client
    {
        MyWorld myWorld;
        private ObjectOutputStream outClient;
        private ObjectInputStream inClient;
        public Socket clientSocket;
        public Client(MyWorld myWorl)
        {
            this.myWorld = myWorl;
            try
            {
                clientSocket = new Socket("localhost",8888);
                outClient = new ObjectOutputStream(clientSocket.getOutputStream());
                inClient = new ObjectInputStream(clientSocket.getInputStream());
            }catch(IOException e)
            {
                close();
            }   
        }

        public void sendInts(int ...arr) {
            try {
                outClient.writeObject(arr);
                Greenfoot.delay(1);
                outClient.flush();
            }
            catch(NullPointerException ex) {
            }
            catch(IOException ex) {
            }
        }

        public int[] receiveInts() {
            int[] datClient = null;
            try {
                datClient = (int[])inClient.readObject();
            }
            catch(ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            catch(NullPointerException ex) {
            }
            catch(IOException ex) {
                close();
            }
            return datClient;
        }

        public void close()
        {
            try {
                outClient.close();
                inClient.close();
                clientSocket.close();
            }
            catch(IOException ex) {
                throw new RuntimeException("Error closing streams...");
            }
        }
    }
}

Player:

import greenfoot.*;

public class Player extends Actor
{
    private MyWorld myWorld;
    private Player2 player2;

    public Player(MyWorld myWorl)
    {
        myWorld = myWorl;
    }

    private boolean startSelectionBool = false;

    public void act() 
    {
        if(!startSelectionBool)
        {
            if(Greenfoot.getMouseInfo() != null)
            {
                if(Greenfoot.mouseClicked(this))
                {
                    myWorld.init();
                    startSelectionBool = true;
                }
            }
        }
        else
        {
            if(myWorld.Server == true)
            {
                updateServer();
                //System.out.println("Server");
            }else
            {
                updateClient();
                //System.out.println("Client");
            }
        }
    }   

    public void updateServer()
    {
        if(Greenfoot.isKeyDown("w"))
        {
            setLocation(this.getX(), this.getY()-1);
        }
        if(Greenfoot.isKeyDown("s"))
        {
            setLocation(this.getX(), this.getY()+1);
        }
        if(Greenfoot.isKeyDown("a"))
        {
            setLocation(this.getX()-1, this.getY());
        }
        if(Greenfoot.isKeyDown("d"))
        {
            setLocation(this.getX()+1, this.getY());
        }
        myWorld.server.sendInts(this.getX(), this.getY());

        updatePosition();
    }

    public void updatePosition()
    {
        int[] w1 = myWorld.server.receiveInts();
        
        if (w1 != null)
        {
            Greenfoot.delay(5);
            player2 = getWorld().getObjects(Player2.class).get(0);

            System.out.println("Works Server");
            player2.setLocation(w1[0], w1[1]);
            System.out.println("2");
        }
        else
        {
            System.out.println("1");
        }
    }

    public void updateClient()
    {
        if(Greenfoot.isKeyDown("w"))
        {
            setLocation(this.getX(), this.getY()-1);
        }
        if(Greenfoot.isKeyDown("s"))
        {
            setLocation(this.getX(), this.getY()+1);
        }
        if(Greenfoot.isKeyDown("a"))
        {
            setLocation(this.getX()-1, this.getY());
        }
        if(Greenfoot.isKeyDown("d"))
        {
            setLocation(this.getX()+1, this.getY());
        }
        myWorld.client.sendInts(this.getX(), this.getY());

        int[] w2 = myWorld.client.receiveInts();
        
        if (w2 == null)
        {
            System.out.println("Return Client");
            return;
        }
        else
        {
            player2 = getWorld().getObjects(Player2.class).get(0);

            player2.setLocation(w2[0], w2[1]);
        }
    }
}

Solution

  • One thing that looks odd is that in updatePosition() you call receiveInts() twice, so the first one will read from the socket then discard it, and the second one will have to wait for the next corresponding sendInts() call. I suspect you want the assignment to w1 before the if statement in updatePosition(), then check if w1 is null.