From 9dfbbe330ecf965d2c530ef9d992f3a2a70babf3 Mon Sep 17 00:00:00 2001
From: stefagr <stefagr@stud.ntnu.no>
Date: Tue, 20 Apr 2021 06:24:51 +0200
Subject: [PATCH] added more stuff to server

---
 .../game/controllers/GameController.java      |  21 +++-
 .../game/controllers/NetworkController.java   |  22 +++-
 .../game/controllers/PlayerController.java    |   5 +-
 .../game/controllers/commands/Command.java    |   5 +-
 .../controllers/commands/cUpdateGame.java     |  26 +++++
 .../src/com/mygdx/game/model/GameState.kt     |   1 +
 .../core/src/com/mygdx/game/model/Lobby.java  |   6 +
 ...le__CheckersServer_desktop_desktop_1_0.xml |   9 ++
 CheckersServer/.idea/modules.xml              |   2 +-
 .../core/src/com/mygdx/game/Constants.java    |  16 +++
 .../game/controller/NetworkController.java    |  34 +++++-
 .../game/controller/commands/Command.java     |   5 +-
 .../controller/commands/cPlayerPieceMove.java |  34 +-----
 .../game/controller/commands/cUpdateGame.java |  28 +++++
 .../core/src/com/mygdx/game/model/Field.kt    |  34 ++++++
 .../core/src/com/mygdx/game/model/Game.kt     |  25 ++++
 .../core/src/com/mygdx/game/model/GameMode.kt |  30 +++++
 .../src/com/mygdx/game/model/GameState.kt     |  57 ++++++++++
 .../core/src/com/mygdx/game/model/Lobby.java  |   7 ++
 .../core/src/com/mygdx/game/model/Piece.kt    |  12 ++
 .../model/gamemodes/boards/AbstractBoard.kt   |  13 +++
 .../model/gamemodes/boards/DefaultBoard.kt    |  82 ++++++++++++++
 .../game/model/gamemodes/boards/Direction.kt  |  15 +++
 .../model/gamemodes/rules/AbstractRules.kt    |  16 +++
 .../model/gamemodes/rules/DefaultRules.kt     | 107 ++++++++++++++++++
 25 files changed, 568 insertions(+), 44 deletions(-)
 create mode 100644 CheckersClient/core/src/com/mygdx/game/controllers/commands/cUpdateGame.java
 create mode 100644 CheckersServer/.idea/libraries/Gradle__CheckersServer_desktop_desktop_1_0.xml
 create mode 100644 CheckersServer/core/src/com/mygdx/game/Constants.java
 create mode 100644 CheckersServer/core/src/com/mygdx/game/controller/commands/cUpdateGame.java
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/Field.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/Game.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/GameMode.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/GameState.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/Piece.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/AbstractBoard.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/DefaultBoard.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/Direction.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/AbstractRules.kt
 create mode 100644 CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/DefaultRules.kt

diff --git a/CheckersClient/core/src/com/mygdx/game/controllers/GameController.java b/CheckersClient/core/src/com/mygdx/game/controllers/GameController.java
index cd4d843..2a86a2f 100644
--- a/CheckersClient/core/src/com/mygdx/game/controllers/GameController.java
+++ b/CheckersClient/core/src/com/mygdx/game/controllers/GameController.java
@@ -1,8 +1,11 @@
 package com.mygdx.game.controllers;
 
+import com.badlogic.gdx.Gdx;
 import com.badlogic.gdx.math.Vector3;
 import com.mygdx.game.controllers.commands.cPlayerPieceMove;
 import com.mygdx.game.model.Game;
+import com.mygdx.game.model.GameState;
+import com.mygdx.game.model.Lobby;
 import com.mygdx.game.model.Player;
 import com.mygdx.game.views.PlayView;
 import com.mygdx.game.views.tokens.StarPiece;
@@ -19,7 +22,7 @@ public class GameController {
     private final PlayerController playerController;
     private final List<List<Float>> playerNameTextFieldCoordinates;
 
-    public GameController(Game model, PlayView view, PlayerController playerController) {
+    public GameController(Game model, PlayView view, final PlayerController playerController) {
         this.model = model;
         this.view = view;
         this.playerController = playerController;
@@ -35,6 +38,19 @@ public class GameController {
         this.view.initializePieces(this.model.getStartFieldCoordinates());
         this.view.placePlayerNames(usedBoardSlots, playerNameTextFieldCoordinates);
         this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(this.model.getPlayerTurnSlot()));
+
+        playerController.getLobby().setGame(model); //set game in playerController
+        playerController.updateGame(); //send to server
+        Thread thread = new Thread(){
+            public void run(){
+                while (playerController.getLastCommand() == null) {
+                    System.out.println("Waiting for game update");
+                }
+                GameState gs = (GameState) playerController.getLobby().getGame();
+                System.out.println("gameUpdate received: " + gs);
+            }
+        };
+        thread.start();
     }
 
     public void handleClick(float x, float y) {
@@ -62,7 +78,10 @@ public class GameController {
                         this.view.movePiece(activePiece, cubeCoordinates);
                         activePiece.setRotateHead(false);
                         activePiece = null;
+
                         playerController.getNetWorkController().sendToServer(new cPlayerPieceMove(previousCoordinateClicked, cubeCoordinates, playerController.getLobby().getID(), playerController.getPlayer().getID()));
+                        //playerController.updateGame();
+
                         previousCoordinateClicked = null;
 
                         this.view.placeTurnIndicator(playerNameTextFieldCoordinates.get(this.model.getPlayerTurnSlot()));
diff --git a/CheckersClient/core/src/com/mygdx/game/controllers/NetworkController.java b/CheckersClient/core/src/com/mygdx/game/controllers/NetworkController.java
index 92da9b2..c81de43 100644
--- a/CheckersClient/core/src/com/mygdx/game/controllers/NetworkController.java
+++ b/CheckersClient/core/src/com/mygdx/game/controllers/NetworkController.java
@@ -5,8 +5,15 @@ import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryonet.Client;
 import com.mygdx.game.controllers.commands.Command;
 import com.mygdx.game.controllers.commands.*;
+import com.mygdx.game.model.DefaultBoard;
+import com.mygdx.game.model.Field;
+import com.mygdx.game.model.Game;
+import com.mygdx.game.model.GameMode;
+import com.mygdx.game.model.GameState;
 import com.mygdx.game.model.Lobby;
+import com.mygdx.game.model.Piece;
 import com.mygdx.game.model.Player;
+import com.mygdx.game.model.gamemodes.rules.DefaultRules;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -23,7 +30,8 @@ public class NetworkController {
         this.client = new Client();
         client.start();
         try {
-            String IP4_LAN_ADDRESS = "192.168.0.136"; //122 //"192.168.87.20";
+            //192.168.0.136
+            String IP4_LAN_ADDRESS = "192.168.10.154"; //122 //"192.168.87.20";
             client.connect(10000, IP4_LAN_ADDRESS, 54555, 54777);
         } catch (IOException e) {
             e.printStackTrace();
@@ -53,6 +61,18 @@ public class NetworkController {
         kryo.register(cSetPlayerName.class, 27);
         kryo.register(cStartGame.class, 28);
         kryo.register(Vector3.class, 29);
+        kryo.register(cUpdateGame.class, 30);
+        kryo.register(Game.class, 31);
+        kryo.register(GameState.class, 32);
+        kryo.register(GameMode.class, 33);
+        kryo.register(Piece.class, 34);
+        kryo.register(Field.class, 35);
+        kryo.register(DefaultBoard.class, 36);
+        kryo.register(DefaultRules.class, 37);
+        kryo.register(java.util.HashMap.class, 38);
+        kryo.register(java.util.Arrays.asList().getClass(), 39);
+        kryo.register(kotlin.collections.EmptyList.class, 40); //works anyway ignore
+        kryo.register(java.util.LinkedHashSet.class, 41);
     }
 
     public Client getClient() { return client; }
diff --git a/CheckersClient/core/src/com/mygdx/game/controllers/PlayerController.java b/CheckersClient/core/src/com/mygdx/game/controllers/PlayerController.java
index 04f9ecf..6ce3dd2 100644
--- a/CheckersClient/core/src/com/mygdx/game/controllers/PlayerController.java
+++ b/CheckersClient/core/src/com/mygdx/game/controllers/PlayerController.java
@@ -5,9 +5,6 @@ import com.esotericsoftware.kryonet.Listener;
 import com.mygdx.game.controllers.commands.*;
 import com.mygdx.game.model.Lobby;
 import com.mygdx.game.model.Player;
-
-import org.javatuples.Pair;
-
 import java.util.ArrayList;
 import java.util.LinkedList;
 
@@ -69,6 +66,8 @@ public class PlayerController {
 
     public void leaveLobby(int id) { sendCommand(new cLobbyLeave(id)); }
 
+    public void updateGame(){ sendCommand(new cUpdateGame(lobby.getGame(), lobby.getID()));}
+
     public Lobby getLobby(){ return lobby; }
 
     public ArrayList<Lobby> getLobbyList(){ return lobbies; }
diff --git a/CheckersClient/core/src/com/mygdx/game/controllers/commands/Command.java b/CheckersClient/core/src/com/mygdx/game/controllers/commands/Command.java
index b8bb4a0..79f1dd1 100644
--- a/CheckersClient/core/src/com/mygdx/game/controllers/commands/Command.java
+++ b/CheckersClient/core/src/com/mygdx/game/controllers/commands/Command.java
@@ -30,9 +30,12 @@ public class Command{
 
     @Override
     public String toString() {
+        String toString;
+        if(data == null) toString = "null";
+        else toString = data.toString();
         return "Command{" +
                 "text='" + text + '\'' +
-                "data='" + data.toString() + '\'' +
+                "data='" + toString + '\'' +
                 '}';
     }
 }
\ No newline at end of file
diff --git a/CheckersClient/core/src/com/mygdx/game/controllers/commands/cUpdateGame.java b/CheckersClient/core/src/com/mygdx/game/controllers/commands/cUpdateGame.java
new file mode 100644
index 0000000..c6eaf2b
--- /dev/null
+++ b/CheckersClient/core/src/com/mygdx/game/controllers/commands/cUpdateGame.java
@@ -0,0 +1,26 @@
+package com.mygdx.game.controllers.commands;
+
+import com.esotericsoftware.kryonet.Connection;
+import com.mygdx.game.controllers.PlayerController;
+
+import java.util.ArrayList;
+
+public class cUpdateGame extends Command{
+
+    public cUpdateGame() { super("cUpdateGame"); }
+
+    public cUpdateGame(Object game, int lobbyId ) {
+        super("cUpdateGame");
+        ArrayList<Object> data = new ArrayList<Object>();
+        data.add(game);
+        data.add(lobbyId);
+        this.data = data;
+    }
+
+    @Override
+    public void execute(PlayerController playerController, Connection connection){
+        playerController.getLobby().setGame(data);  //gameState as object, need to cast before using
+        if(data == null) System.out.println("gameState update received and it is null");
+        else System.out.println("gameState update received correctly");
+    }
+}
diff --git a/CheckersClient/core/src/com/mygdx/game/model/GameState.kt b/CheckersClient/core/src/com/mygdx/game/model/GameState.kt
index c153bb6..35ece69 100644
--- a/CheckersClient/core/src/com/mygdx/game/model/GameState.kt
+++ b/CheckersClient/core/src/com/mygdx/game/model/GameState.kt
@@ -52,4 +52,5 @@ class GameState(gameMode: GameMode) {
     fun setFinished() {
         isFinished = true
     }
+
 }
\ No newline at end of file
diff --git a/CheckersClient/core/src/com/mygdx/game/model/Lobby.java b/CheckersClient/core/src/com/mygdx/game/model/Lobby.java
index a6ba03f..1e0cd58 100644
--- a/CheckersClient/core/src/com/mygdx/game/model/Lobby.java
+++ b/CheckersClient/core/src/com/mygdx/game/model/Lobby.java
@@ -11,6 +11,7 @@ public class Lobby {
     private int MAX_PLAYERS;
     private ArrayList<Player> players;
     private boolean lobbyGameStarted = false;
+    private Object game;
 
     public Lobby() {}
 
@@ -24,6 +25,7 @@ public class Lobby {
         this.name = name;
         this.MAX_PLAYERS = MAX_PLAYERS;
         players = new ArrayList<Player>();
+        game = null;
     }
 
     public int getID(){ return ID; }
@@ -62,6 +64,10 @@ public class Lobby {
         return players;
     }
 
+    public void setGame(Object gameState){ this.game = gameState; }
+
+    public Object getGame(){ return this.game; }
+
     public LinkedHashSet<Integer> getPlayersID(){
         LinkedHashSet<Integer> set = new LinkedHashSet<Integer>();
         for(Player player : players){
diff --git a/CheckersServer/.idea/libraries/Gradle__CheckersServer_desktop_desktop_1_0.xml b/CheckersServer/.idea/libraries/Gradle__CheckersServer_desktop_desktop_1_0.xml
new file mode 100644
index 0000000..369215d
--- /dev/null
+++ b/CheckersServer/.idea/libraries/Gradle__CheckersServer_desktop_desktop_1_0.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+  <library name="Gradle: CheckersServer.desktop.desktop-1.0">
+    <CLASSES>
+      <root url="jar://$PROJECT_DIR$/desktop/build/libs/desktop-1.0.jar!/" />
+    </CLASSES>
+    <JAVADOC />
+    <SOURCES />
+  </library>
+</component>
\ No newline at end of file
diff --git a/CheckersServer/.idea/modules.xml b/CheckersServer/.idea/modules.xml
index 1b6b39a..a8a1a25 100644
--- a/CheckersServer/.idea/modules.xml
+++ b/CheckersServer/.idea/modules.xml
@@ -2,7 +2,7 @@
 <project version="4">
   <component name="ProjectModuleManager">
     <modules>
-      <module fileurl="file://$PROJECT_DIR$/.idea/modules/CheckersServer.iml" filepath="$PROJECT_DIR$/.idea/modules/CheckersServer.iml" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/CheckersServer.iml" filepath="$PROJECT_DIR$/.idea/CheckersServer.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/modules/android/CheckersServer.android.iml" filepath="$PROJECT_DIR$/.idea/modules/android/CheckersServer.android.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/modules/core/CheckersServer.core.iml" filepath="$PROJECT_DIR$/.idea/modules/core/CheckersServer.core.iml" />
       <module fileurl="file://$PROJECT_DIR$/.idea/modules/desktop/CheckersServer.desktop.iml" filepath="$PROJECT_DIR$/.idea/modules/desktop/CheckersServer.desktop.iml" />
diff --git a/CheckersServer/core/src/com/mygdx/game/Constants.java b/CheckersServer/core/src/com/mygdx/game/Constants.java
new file mode 100644
index 0000000..5170020
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/Constants.java
@@ -0,0 +1,16 @@
+package com.mygdx.game;
+
+import java.util.HashMap;
+
+public class Constants {
+    public static final int PLAYER_NAME_TEXT_FIELD_WIDTH = 340;
+    public static final int PLAYER_NAME_TEXT_FIELD_HEIGHT = 80;
+    public static final HashMap<Integer, String> AVAILABLEAVATARSHASHMAP = new HashMap<Integer, String>() {{
+        put(0, "RegularGuy");
+        put(1, "HipsterGirl");
+        put(2, "HighSchoolGuy");
+        put(3, "RocketGuy");
+        put(4, "AsianGirl");
+        put(5, "Grandma");
+    }};
+}
diff --git a/CheckersServer/core/src/com/mygdx/game/controller/NetworkController.java b/CheckersServer/core/src/com/mygdx/game/controller/NetworkController.java
index 69788e3..1340ac8 100644
--- a/CheckersServer/core/src/com/mygdx/game/controller/NetworkController.java
+++ b/CheckersServer/core/src/com/mygdx/game/controller/NetworkController.java
@@ -1,17 +1,22 @@
 package com.mygdx.game.controller;
 
-import com.badlogic.gdx.math.Vector3;
 import com.esotericsoftware.kryo.Kryo;
 import com.esotericsoftware.kryonet.Connection;
 import com.esotericsoftware.kryonet.Listener;
 import com.esotericsoftware.kryonet.Server;
 import com.mygdx.game.controller.commands.*;
+import com.mygdx.game.model.DefaultBoard;
+import com.mygdx.game.model.Field;
+import com.mygdx.game.model.Game;
+import com.mygdx.game.model.GameMode;
+import com.mygdx.game.model.GameState;
 import com.mygdx.game.model.Lobby;
+import com.mygdx.game.model.Piece;
 import com.mygdx.game.model.Player;
+import com.mygdx.game.model.gamemodes.rules.DefaultRules;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashSet;
 
 public class NetworkController {
@@ -27,7 +32,7 @@ public class NetworkController {
     private Kryo kryo;
 
     public NetworkController(){
-        server = new Server();
+        server = new Server(16384,3072);
         server.start();
         try {
             server.bind(54555, 54777);
@@ -124,6 +129,16 @@ public class NetworkController {
         return new Lobby(-1);
     }
 
+    public Object updateGame(Game game, int lobbyID){
+        Lobby lobby = getLobby(lobbyID);
+        if (lobby.getID() != -1){
+            lobby.setGame(game);
+            lobbies.set(lobbies.indexOf(lobby), lobby);
+            return game;
+        }
+        return null;
+    }
+
     public Lobby getLobby(int lobbyID){
         int lobby_idx = lobbies.indexOf(new Lobby(lobbyID));
         if (lobby_idx != -1){
@@ -160,7 +175,18 @@ public class NetworkController {
         kryo.register(cSetPlayerReady.class, 26);
         kryo.register(cSetPlayerName.class, 27);
         kryo.register(cStartGame.class, 28);
-        kryo.register(Vector3.class, 29);
+        kryo.register(cUpdateGame.class, 30);
+        kryo.register(Game.class, 31);
+        kryo.register(GameState.class, 32);
+        kryo.register(GameMode.class, 33);
+        kryo.register(Piece.class, 34);
+        kryo.register(Field.class, 35);
+        kryo.register(DefaultBoard.class, 36);
+        kryo.register(DefaultRules.class, 37);
+        kryo.register(java.util.HashMap.class, 38);
+        kryo.register(java.util.Arrays.asList().getClass(), 39);
+        kryo.register(kotlin.collections.EmptyList.class, 40); //works anyway ignore
+        kryo.register(java.util.LinkedHashSet.class, 41);
     }
 
     public NetworkController getNetworkController() { return this; }
diff --git a/CheckersServer/core/src/com/mygdx/game/controller/commands/Command.java b/CheckersServer/core/src/com/mygdx/game/controller/commands/Command.java
index 017f74c..dca9d8c 100644
--- a/CheckersServer/core/src/com/mygdx/game/controller/commands/Command.java
+++ b/CheckersServer/core/src/com/mygdx/game/controller/commands/Command.java
@@ -26,9 +26,12 @@ public class Command{
 
     @Override
     public String toString() {
+        String toString;
+        if(data == null) toString = "null";
+        else toString = data.toString();
         return "Command{" +
                 "text='" + text + '\'' +
-                "data='" + data.toString() + '\'' +
+                "data='" + toString + '\'' +
                 '}';
     }
 }
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/controller/commands/cPlayerPieceMove.java b/CheckersServer/core/src/com/mygdx/game/controller/commands/cPlayerPieceMove.java
index b718675..9504cab 100644
--- a/CheckersServer/core/src/com/mygdx/game/controller/commands/cPlayerPieceMove.java
+++ b/CheckersServer/core/src/com/mygdx/game/controller/commands/cPlayerPieceMove.java
@@ -1,48 +1,18 @@
 package com.mygdx.game.controller.commands;
 
-import com.badlogic.gdx.math.Vector3;
 import com.esotericsoftware.kryonet.Connection;
 import com.mygdx.game.controller.NetworkController;
 
-import java.util.ArrayList;
-
 public class cPlayerPieceMove extends Command {
 
-    Vector3 fromCoordinates;
-    Vector3 toCordinates;
-    int lobby_id;
-    int playerId;
-
     public cPlayerPieceMove() {
         super("cPlayerPieceMove");
     }
 
-    /*public cPlayerPieceMove(Vector3 fromCoordinates, Vector3 toCoordinates, int lobbyId, int playerId) {
-        super("cPlayerPieceMove");
-
-        this.fromCoordinates = fromCoordinates;
-        this.toCordinates = toCoordinates;
-        this.lobby_id = lobbyId;
-        this.playerId = playerId;
-
-        ArrayList<Object> data = new ArrayList<Object>();
-        data.add(fromCoordinates);
-        data.add(toCoordinates);
-        data.add(playerId);
-        this.data = data;
-    }*/
-
     @Override
     public void execute(NetworkController net, Connection connection){
-        if (data instanceof ArrayList) {
-            System.out.println("Checking if valid move.. If valid, moving player piece from A to B... Updating model.. Sending move to clients....");
-        }
-
-        for (Connection c : net.getConnections(net.getLobby(lobby_id))) {
-            if (c != connection) {
-                c.sendTCP(this);
-            }
-        }
+        System.out.println("Checking if valid move.. If valid, moving player piece from A to B... Updating model.. Sending move to clients....");
+        connection.sendTCP(this);
     }
 }
 
diff --git a/CheckersServer/core/src/com/mygdx/game/controller/commands/cUpdateGame.java b/CheckersServer/core/src/com/mygdx/game/controller/commands/cUpdateGame.java
new file mode 100644
index 0000000..76359a6
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/controller/commands/cUpdateGame.java
@@ -0,0 +1,28 @@
+package com.mygdx.game.controller.commands;
+
+import com.esotericsoftware.kryonet.Connection;
+import com.mygdx.game.controller.NetworkController;
+import com.mygdx.game.model.Game;
+import com.mygdx.game.model.Lobby;
+
+import java.util.ArrayList;
+
+public class cUpdateGame extends Command{
+
+    public cUpdateGame() { super("cUpdateGame"); }
+
+    public cUpdateGame(Game game) { super("cUpdateGame", game); }
+
+    @Override
+    public void execute(NetworkController net, Connection connection){
+        if(data instanceof ArrayList){
+            Game gameState = (Game)((ArrayList) data).get(0);
+            int lobbyID = (int) ((ArrayList) data).get(1);
+            data = net.updateGame(gameState, lobbyID);
+            for (Connection c : net.getConnections(net.getLobby(lobbyID))) {
+                c.sendTCP(this);
+            }
+        }
+        System.out.println("Game update request received");
+    }
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/Field.kt b/CheckersServer/core/src/com/mygdx/game/model/Field.kt
new file mode 100644
index 0000000..015e5ce
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/Field.kt
@@ -0,0 +1,34 @@
+//Inside gameState, data for a specific field
+package com.mygdx.game.model
+
+import java.lang.Exception
+
+class Field {
+
+    private var piece: Piece?
+    //private var powerup: Powerup?
+
+    init {
+        this.piece = null
+    }
+
+    fun setPiece(piece: Piece) {
+        if (this.piece != null) {
+            throw Exception("Field already holds a piece.")
+        } else {
+            this.piece = piece
+        }
+    }
+
+    fun getPiece(): Piece? {
+        return this.piece
+    }
+
+    fun hasPiece(): Boolean {
+        return this.piece != null
+    }
+
+    fun removePiece() {
+        this.piece = null
+    }
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/Game.kt b/CheckersServer/core/src/com/mygdx/game/model/Game.kt
new file mode 100644
index 0000000..fd32d0c
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/Game.kt
@@ -0,0 +1,25 @@
+package com.mygdx.game.model
+
+import com.badlogic.gdx.math.Vector3
+
+class Game(gameState: GameState, playerIds: LinkedHashSet<Int>) {
+
+    private var gameState: GameState
+    private var playerIds: LinkedHashSet<Int>
+    private var playerTurnId: Int
+    private var playerTurnIndex: Int = 0 // TODO: Random from server
+    private var playerTurnSlot: Int
+    private var playerFinishedIds: List<Int> = listOf()
+    private var usedBoardSlots: List<Int>
+
+    init {
+        this.gameState = gameState
+        this.playerIds = playerIds
+        this.gameState.getBoardState().placePiecesAtStart(this.gameState.getRules(), this.playerIds)
+
+        usedBoardSlots =  this.gameState.getRules().getUsedBoardSlots(playerIds.size)
+        playerTurnSlot = usedBoardSlots[0]
+        playerTurnId = playerIds.elementAt(playerTurnIndex)
+    }
+
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/GameMode.kt b/CheckersServer/core/src/com/mygdx/game/model/GameMode.kt
new file mode 100644
index 0000000..98f51fb
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/GameMode.kt
@@ -0,0 +1,30 @@
+package com.mygdx.game.model//Holds a ruleset and a board
+
+class GameMode(rules:AbstractRules, board:AbstractBoard) {
+
+    private var rules: AbstractRules
+    private var board: AbstractBoard
+
+    init { }
+
+    init {
+        this.rules = rules
+        this.board = board
+    }
+
+    fun setBoard(board:AbstractBoard) {
+        this.board = board
+    }
+
+    fun getBoard(): AbstractBoard {
+        return this.board
+    }
+
+    fun setRules(rules: AbstractRules) {
+        this.rules = rules
+    }
+
+    fun getRules(): AbstractRules {
+        return this.rules
+    }
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/GameState.kt b/CheckersServer/core/src/com/mygdx/game/model/GameState.kt
new file mode 100644
index 0000000..40d43c0
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/GameState.kt
@@ -0,0 +1,57 @@
+package com.mygdx.game.model
+
+import com.mygdx.game.model.gamemodes.rules.DefaultRules
+
+/*
+Holds the state of the game and all data related to this.
+*/
+class GameState(gameMode: GameMode) {
+
+    private var boardState: AbstractBoard
+    private var rules: AbstractRules
+    private var isStarted: Boolean
+    private var winner: Int?
+    private var isFinished: Boolean = false
+
+    init { }
+
+    init {
+        this.rules = gameMode.getRules()
+        this.boardState = gameMode.getBoard()
+
+        this.isStarted = false
+        this.winner = null
+    }
+
+    fun getBoardState(): AbstractBoard {
+        return boardState
+    }
+
+    fun getRules(): AbstractRules {
+        return rules
+    }
+
+    fun isStarted(): Boolean {
+        return isStarted
+    }
+
+    fun setStarted() {
+        this.isStarted = true
+    }
+
+    fun isFinished(): Boolean {
+        return isFinished
+    }
+
+    fun getWinner(): Int? {
+        return this.winner
+    }
+
+    fun setWinner(winner: Int) {
+        this.winner = winner
+    }
+
+    fun setFinished() {
+        isFinished = true
+    }
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/Lobby.java b/CheckersServer/core/src/com/mygdx/game/model/Lobby.java
index 46496c4..2d6e8b5 100644
--- a/CheckersServer/core/src/com/mygdx/game/model/Lobby.java
+++ b/CheckersServer/core/src/com/mygdx/game/model/Lobby.java
@@ -1,5 +1,6 @@
 package com.mygdx.game.model;
 
+
 import java.util.ArrayList;
 import java.util.HashSet;
 
@@ -9,6 +10,7 @@ public class Lobby {
     private String name;
     private int MAX_PLAYERS;
     private ArrayList<Player> players;
+    private Game game;
 
     public Lobby() {}
 
@@ -22,6 +24,7 @@ public class Lobby {
         this.name = name;
         this.MAX_PLAYERS = MAX_PLAYERS;
         players = new ArrayList<Player>();
+        game = null;
     }
 
     public int playerJoin(Player player){
@@ -84,6 +87,10 @@ public class Lobby {
         }
     }
 
+    public void setGame(Game game){ this.game = game; }
+
+    public Object getGame(){ return this.game; }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/CheckersServer/core/src/com/mygdx/game/model/Piece.kt b/CheckersServer/core/src/com/mygdx/game/model/Piece.kt
new file mode 100644
index 0000000..9c2dc1a
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/Piece.kt
@@ -0,0 +1,12 @@
+package com.mygdx.game.model
+
+class Piece(ownerId: Int) {
+
+    private var ownerId: Int = ownerId
+
+    init { }
+
+    fun getOwnerId(): Int {
+        return this.ownerId
+    }
+}
diff --git a/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/AbstractBoard.kt b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/AbstractBoard.kt
new file mode 100644
index 0000000..06d857d
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/AbstractBoard.kt
@@ -0,0 +1,13 @@
+package com.mygdx.game.model
+
+import com.badlogic.gdx.math.Vector3
+
+abstract class AbstractBoard {
+
+    var fields = HashMap<Vector3, Field>()
+
+    abstract fun computeFields() // Computes all fields on the board
+    abstract fun fieldExists(coordinates: Vector3): Boolean
+    abstract fun placePiecesAtStart(rules: AbstractRules, playerIds: HashSet<Int>)
+    abstract fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/DefaultBoard.kt b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/DefaultBoard.kt
new file mode 100644
index 0000000..a20a6b3
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/DefaultBoard.kt
@@ -0,0 +1,82 @@
+//General board class
+package com.mygdx.game.model
+
+import com.badlogic.gdx.math.Vector3
+import java.lang.Integer.max
+import java.lang.Integer.min
+
+class DefaultBoard: AbstractBoard() {
+    var r = 8
+
+    init { }
+
+    init {
+        computeFields()
+    }
+
+    override fun computeFields() {
+        // https://www.redblobgames.com/grids/hexagons/#range
+        for (x in -r..r) {
+            loop@ for (y in max(-r, -x - r)..min(r, -x + r)) {
+                val z = -x - y
+
+                val coordinates = Vector3(x.toFloat(), y.toFloat(), z.toFloat())
+                if (!fieldShouldBeAddedToBoard(coordinates)) {
+                    continue@loop
+                }
+                fields[coordinates] = Field()
+            }
+        }
+    }
+
+    override fun placePiecesAtStart(rules: AbstractRules, playerIds: HashSet<Int>) {
+
+        val startFields: List<List<Vector3>> = rules.generateStartFields(playerIds.size)
+
+        for ((playerIndex, coordinateSet: List<Vector3>) in startFields.withIndex()) {
+            for (coordinate: Vector3 in coordinateSet) {
+                val piece = Piece(playerIds.elementAt(playerIndex))
+                fields[coordinate]?.setPiece(piece)
+            }
+        }
+    }
+
+    override fun fieldExists(coordinates: Vector3): Boolean {
+        return fields[coordinates] != null
+    }
+
+    override fun movePiece(fromCoordinates: Vector3, toCoordinates: Vector3): Boolean {
+        val piece = fields[fromCoordinates]?.getPiece()
+
+        if (piece != null) {
+            fields[toCoordinates]?.setPiece(piece)
+            fields[fromCoordinates]?.removePiece()
+            return true
+        }
+        return false
+    }
+
+    private fun fieldShouldBeAddedToBoard(coordinates: Vector3) : Boolean {
+        val x = coordinates.x
+        val y = coordinates.y
+        val z = coordinates.z
+
+        // Upper right
+        if (x > 4) {
+            if (y < -4 || z < -4)
+                return false
+        }
+        // Bottom
+        if (z > 4) {
+            if (y < -4 || x < -4)
+                return false
+        }
+        // Upper left
+        if (y > 4) {
+            if (x < -4 || z < -4) {
+                return false
+            }
+        }
+        return true
+    }
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/Direction.kt b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/Direction.kt
new file mode 100644
index 0000000..e49fa59
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/boards/Direction.kt
@@ -0,0 +1,15 @@
+package com.mygdx.game.model
+
+import com.badlogic.gdx.math.Vector3
+
+enum class Direction {
+    UPPERRIGHT,
+    RIGHT,
+    LOWERRIGHT,
+    LOWERLEFT,
+    LEFT,
+    UPPERLEFT
+}
+
+// Sequence matches Direction enum above (UpperRight, Right, LowerRight, LowerLeft, Left, UpperLeft)
+var directionalUnitVectors = listOf(Vector3(1F, 0F, -1F), Vector3(1F, -1F, 0F), Vector3(0F, -1F, 1F), Vector3(-1F, 0F, 1F), Vector3(-1F, 1F, 0F), Vector3(0F, 1F, -1F))
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/AbstractRules.kt b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/AbstractRules.kt
new file mode 100644
index 0000000..618a82f
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/AbstractRules.kt
@@ -0,0 +1,16 @@
+package com.mygdx.game.model
+
+import com.badlogic.gdx.math.Vector3
+
+abstract class AbstractRules {
+
+    abstract var startFields: List<List<Vector3>> // List containing list of startfields for each player
+    abstract var moveRange: Int                   // How far a piece can be moved
+    abstract var jumpRange: Int                   // How many pieces a piece can jump over
+
+    abstract fun getPlayerStartfields(boardSlot: Int) : List<Vector3>                // Returns a list of startfields for a given player
+    abstract fun getPlayerTargetFields(boardSlot: Int) : List<Vector3>               // Returns a list of targetfields for a given player
+    abstract fun generateStartFields(playerCount: Int = 6): List<List<Vector3>>      // Returns a list with lists of startfields
+    abstract fun getUsedBoardSlots(playerCount: Int): List<Int>                      // Returns a list with used boardslots
+    abstract fun getPlayerNameCoordinates(hex_side_length: Float): List<List<Float>> // Returns a list with lists of coordinates for playernames
+}
\ No newline at end of file
diff --git a/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/DefaultRules.kt b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/DefaultRules.kt
new file mode 100644
index 0000000..a3e2591
--- /dev/null
+++ b/CheckersServer/core/src/com/mygdx/game/model/gamemodes/rules/DefaultRules.kt
@@ -0,0 +1,107 @@
+package com.mygdx.game.model.gamemodes.rules
+
+import com.badlogic.gdx.Gdx
+import com.badlogic.gdx.math.Vector3
+import com.mygdx.game.Constants
+import com.mygdx.game.model.AbstractRules
+
+class DefaultRules: AbstractRules() {
+    override var startFields = generateStartFields()
+    override var moveRange = 1
+    override var jumpRange = 2
+
+    init { }
+
+    override fun getPlayerStartfields(boardSlot: Int): List<Vector3> {
+        return startFields[boardSlot]
+    }
+
+    override fun getPlayerTargetFields(boardSlot: Int): List<Vector3> {
+        var slot = boardSlot
+
+        for (i in 0..2) {
+            slot++
+            // Wrap around to first player
+            if(slot == 6) {
+                slot = 0
+            }
+        }
+        return startFields[slot]
+    }
+
+    // Sequence: top, upperright, lowerright, bottom, lowerleft, upperleft
+    override fun generateStartFields(playerCount: Int): List<List<Vector3>> {
+        val startFields: MutableList<List<Vector3>> = mutableListOf()
+        val allStartFields: List<List<Vector3>> = listOf(
+                listOf(Vector3(1F, 4F, -5F), Vector3(2F, 3F, -5F), Vector3(3F, 2F, -5F), Vector3(4F, 1F, -5F),
+                        Vector3(2F, 4F, -6F), Vector3(3F, 3F, -6F), Vector3(4F, 2F, -6F), Vector3(3F, 4F, -7F),
+                        Vector3(4F, 3F, -7F), Vector3(4F, 4F, -8F)
+                ),
+                listOf(Vector3(5F, -1F, -4F), Vector3(5F, -2F, -3F), Vector3(5F, -3F, -2F), Vector3(5F, -4F, -1F),
+                        Vector3(6F, -2F, -4F), Vector3(6F, -3F, -3F), Vector3(6F, -4F, -2F), Vector3(7F, -3F, -4F),
+                        Vector3(7F, -4F, -3F), Vector3(8F, -4F, -4F)
+                ),
+                listOf(Vector3(4F, -5F, 1F), Vector3(3F, -5F, 2F), Vector3(2F, -5F, 3F), Vector3(1F, -5F, 4F),
+                        Vector3(4F, -6F, 2F), Vector3(3F, -6F, 3F), Vector3(2F, -6F, 4F), Vector3(4F, -7F, 3F),
+                        Vector3(3F, -7F, 4F), Vector3(4F, -8F, 4F)
+                ),
+                listOf(Vector3(-4F, -1F, 5F), Vector3(-3F, -2F, 5F), Vector3(-2F, -3F, 5F), Vector3(-1F, -4F, 5F),
+                        Vector3(-4F, -2F, 6F), Vector3(-3F, -3F, 6F), Vector3(-2F, -4F, 6F), Vector3(-4F, -3F, 7F),
+                        Vector3(-3F, -4F, 7F), Vector3(-4F, -4F, 8F)
+                ),
+                listOf(Vector3(-5F, 4F, 1F), Vector3(-5F, 3F, 2F), Vector3(-5F, 2F, 3F), Vector3(-5F, 1F, 4F),
+                        Vector3(-6F, 4F, 2F), Vector3(-6F, 3F, 3F), Vector3(-6F, 2F, 4F), Vector3(-7F, 4F, 3F),
+                        Vector3(-7F, 3F, 4F), Vector3(-8F, 4F, 4F)
+                ),
+                listOf(Vector3(-1F, 5F, -4F), Vector3(-2F, 5F, -3F), Vector3(-3F, 5F, -2F), Vector3(-4F, 5F, -1F),
+                        Vector3(-2F, 6F, -4F), Vector3(-3F, 6F, -3F), Vector3(-4F, 6F, -2F), Vector3(-3F, 7F, -4F),
+                        Vector3(-4F, 7F, -3F), Vector3(-4F, 8F, -4F)
+                )
+        )
+
+        when (playerCount) {
+            2 -> {
+                startFields.add(allStartFields[0])
+                startFields.add(allStartFields[3])
+            }
+            4 -> {
+                startFields.add(allStartFields[1])
+                startFields.add(allStartFields[2])
+                startFields.add(allStartFields[4])
+                startFields.add(allStartFields[5])
+            }
+            6 -> startFields.addAll(allStartFields)
+            else -> {
+                print("ERROR: DefaultBoard needs 2, 4 or 6 players.")
+            }
+        }
+
+        return startFields
+    }
+
+    override fun getUsedBoardSlots(playerCount: Int): List<Int> {
+        return when (playerCount) {
+            2 -> {
+                listOf(0, 3)
+            }
+            4 -> {
+                listOf(1, 2, 4, 5)
+            }
+            else -> {
+                listOf(0, 1, 2, 3, 4, 5)
+            }
+        }
+    }
+
+    override fun getPlayerNameCoordinates(hex_side_length: Float): List<List<Float>> {
+        return listOf(
+                listOf(Gdx.graphics.width / 2f - Constants.PLAYER_NAME_TEXT_FIELD_WIDTH - 2.5f * hex_side_length, Gdx.graphics.height - Constants.PLAYER_NAME_TEXT_FIELD_HEIGHT - 1.5f * hex_side_length),
+                listOf(Gdx.graphics.width / 2f + Constants.PLAYER_NAME_TEXT_FIELD_WIDTH + 4f * hex_side_length, Gdx.graphics.height / 2f + 4 * hex_side_length),
+                listOf(Gdx.graphics.width / 2f + Constants.PLAYER_NAME_TEXT_FIELD_WIDTH + 4f * hex_side_length, Gdx.graphics.height / 2f - 5 * hex_side_length),
+                listOf(Gdx.graphics.width / 2f - Constants.PLAYER_NAME_TEXT_FIELD_WIDTH - 2.5f * hex_side_length, 1.5f * hex_side_length),
+                listOf(Gdx.graphics.width / 2f - Constants.PLAYER_NAME_TEXT_FIELD_WIDTH - 12f * hex_side_length, Gdx.graphics.height / 2f - 5 * hex_side_length),
+                listOf(Gdx.graphics.width / 2f - Constants.PLAYER_NAME_TEXT_FIELD_WIDTH - 12f * hex_side_length, Gdx.graphics.height / 2f + 4 * hex_side_length)
+        )
+    }
+}
+
-- 
GitLab