Search code examples
javamultithreadinglwjglpacket

Multi-threading Issue - Passing objects between threads


I'm currently trying to make a really simple multiplayer game in java (with OpenGL (LWJGL)) and currently the program runs on two different threads.

Thread 1: Runs all the game logic and rendering

Thread 2: Handles the connection between server and client

So basically thread 2 sits and wait for incoming packets and whenever it receives a login-packet I want it to create a player-object but it seems like the new object is created on thread 2 and that causes the following error when trying to render:

Exception in thread "Thread-2" java.lang.IllegalStateException: No GLCapabilities instance has been set for the current thread.

I'm fairly new to both OpenGL and multi-threading and there is probably a pretty straightforward and easy solution to this but I'm wondering how I can create an object when receiving the packet and add it to thread 1.

Thread 2:

public void run() {
    while (running) {
        byte[] data = new byte[1024];
        DatagramPacket packet = new DatagramPacket(data, data.length);
        try {
            socket.receive(packet);
        } catch (IOException e) {
            e.printStackTrace();
        }
        parsePacket(packet.getData(), packet.getAddress(), packet.getPort());
        }
    }

parsePacket() checks the type of the packet and if it's a login-packet it will call the following method:

public void addPlayerToGame(byte[] data, InetAddress address, int port) {
    Packet00Login packet = new Packet00Login(data);

    level.addObject(new PlayerMP(packet.getUsername(), new Vector3f(0.0f, 0.0f, 0.0f), address, port));
} 

The addObject method simply adds the objects to an arraylist.

public void addObject(GameObject o) {
    this.objects.add(o);
}

All objects are then being rendered with this call on thread 1:

public void render() {
    for (GameObject o : objects) {
        o.render();
    }
    player.render();
}

Solution

  • You shouldn't modify your GameObject list from the second thread since changes are extremely high you will be iterating on that list in the first thread. Which would cause a current modification exception. Or worse, creating undefined behaviors with openGL.

    What you have to do is having a task list on your first thread. Every loop, you execute all tasks in the task list then clear it.

    So instead of directly adding an game object to the list, add a task to add the object.

    (Also, make sure to make the execution of the tasks thread safe)