diff --git a/src/main/java/lab/game/Level.java b/src/main/java/lab/game/Level.java
index 234c52e50a544eff66ddf9ccd054f7b2d31f7014..d2c640cad83296540409464040940703c5cff6fd 100644
--- a/src/main/java/lab/game/Level.java
+++ b/src/main/java/lab/game/Level.java
@@ -1,5 +1,12 @@
 package lab.game;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -14,6 +21,8 @@ import lombok.extern.log4j.Log4j2;
 @Log4j2
 public class Level {
 
+	private Object entitiesLock = new Object();
+
 	private boolean viewMode;
 
 	private double width;
@@ -51,11 +60,67 @@ public class Level {
 	}
 
 	public void startServer() {
-		// TODO:
+		new Thread(() -> {
+			try (ServerSocket listenSocket = new ServerSocket(4600)) {
+				while (!Thread.currentThread().isInterrupted()) {
+					try {
+						Socket client = listenSocket.accept();
+						new Thread(() -> handleViewer(client), "Viewer handler").start();
+					} catch (IOException e) {
+						e.printStackTrace();
+					}
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+
+		}).start();
+	}
+
+	public void handleViewer(Socket client) {
+		try (OutputStream outputStream = client.getOutputStream();
+				ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream)) {
+			while (!Thread.currentThread().isInterrupted()) {
+				synchronized (entitiesLock) {
+					objectOutputStream.reset();
+					synchronized (entitiesLock) {
+						objectOutputStream.writeObject(entities);
+					}
+					objectOutputStream.flush();
+				}
+				sleepForWhile();
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private void sleepForWhile() {
+		try {
+			Thread.sleep(20);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+		}
 	}
 
 	public void connectToServer() {
-		// TODO:
+		new Thread(() -> {
+			try (Socket socketToServer = new Socket("localhost", 4600);
+					InputStream inputStream = socketToServer.getInputStream();
+					ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
+				while (!Thread.currentThread().isInterrupted()) {
+					Object o = objectInputStream.readObject();
+					if (o instanceof List l) {
+						synchronized (entitiesLock) {
+							entities = l;
+						}
+					}
+				}
+			} catch (IOException | ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+
+		}).start();
 	}
 
 	record MonsterDeadLog(LocalDateTime time, MyPoint position) {
@@ -70,8 +135,10 @@ public class Level {
 	public void draw(GraphicsContext gc) {
 		gc.setFill(Color.WHITE);
 		gc.clearRect(0, 0, width, height);
-		for (DrawableSimulable entity : entities) {
-			entity.draw(gc);
+		synchronized (entitiesLock) {
+			for (DrawableSimulable entity : entities) {
+				entity.draw(gc);
+			}
 		}
 	}
 
@@ -79,15 +146,17 @@ public class Level {
 		if (viewMode) {
 			return;
 		}
-		for (DrawableSimulable entity : entities) {
-			entity.simulate(delay);
+		synchronized (entitiesLock) {
+			for (DrawableSimulable entity : entities) {
+				entity.simulate(delay);
+			}
+			detectCollisions();
+			entities.removeAll(entitiesToRemove);
+			entities.addAll(entitiesToAdd);
+			entitiesToAdd.clear();
+			entitiesToRemove.clear();
+			entities.sort(Comparator.comparing(DrawableSimulable::getZIndex));
 		}
-		detectCollisions();
-		entities.removeAll(entitiesToRemove);
-		entities.addAll(entitiesToAdd);
-		entitiesToAdd.clear();
-		entitiesToRemove.clear();
-		entities.sort(Comparator.comparing(DrawableSimulable::getZIndex));
 	}
 
 	private void detectCollisions() {
diff --git a/src/main/java/lab/game/Monster.java b/src/main/java/lab/game/Monster.java
index d9c27882a0fb51fd9dc31781b9cac72a7b65e7b2..2877a56c0375394c37862b7b82e71a55ea5d1d11 100644
--- a/src/main/java/lab/game/Monster.java
+++ b/src/main/java/lab/game/Monster.java
@@ -1,5 +1,6 @@
 package lab.game;
 
+import java.io.Serial;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
@@ -14,13 +15,16 @@ import lab.Config;
 
 public class Monster extends WorldEntity implements Collisionable {
 
+	@Serial
+	private static final long serialVersionUID = 4227585479714088964L;
+
 	private static Logger log = LogManager.getLogger(Monster.class);
 
 	private static final Random RANDOM = new Random();
 
 	private static Image image;
 	private MyPoint speed;
-	private List<DeadListener> deadListeners = new ArrayList<>();
+	private transient List<DeadListener> deadListeners = new ArrayList<>();
 
 	public Monster(Level level) {
 		super(level, new MyPoint(0, 0), 100);
diff --git a/src/main/java/lab/game/MyDimension.java b/src/main/java/lab/game/MyDimension.java
index d76dfb2d145377badc1ebc26748cd66add897ba4..20cb459c8816555b7a83e5edc0765f62c651948a 100644
--- a/src/main/java/lab/game/MyDimension.java
+++ b/src/main/java/lab/game/MyDimension.java
@@ -1,5 +1,6 @@
 package lab.game;
 
+import java.io.Serial;
 import java.io.Serializable;
 
 import lombok.AllArgsConstructor;
@@ -7,7 +8,10 @@ import lombok.Getter;
 
 @AllArgsConstructor
 @Getter
-public class MyDimension {
+public class MyDimension implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = -4053578370437363200L;
 
 	private double width;
 
diff --git a/src/main/java/lab/game/MyPoint.java b/src/main/java/lab/game/MyPoint.java
index 721a676cc1f3c5d7a2fbd4612c011591480b9965..265ed63439f69a47bc520d87dfcc70b9784bff2e 100644
--- a/src/main/java/lab/game/MyPoint.java
+++ b/src/main/java/lab/game/MyPoint.java
@@ -1,6 +1,12 @@
 package lab.game;
 
-public class MyPoint {
+import java.io.Serial;
+import java.io.Serializable;
+
+public class MyPoint implements Serializable {
+
+	@Serial
+	private static final long serialVersionUID = 5131948780897974323L;
 
 	public double x;
 	public double y;
diff --git a/src/main/java/lab/game/NicerObstacle.java b/src/main/java/lab/game/NicerObstacle.java
index 140412ca3c9f0cd9a7bd54c4fd0d403988f7ad21..dc8138a5fd9a1fb9e855966663ad85c1edf58b95 100644
--- a/src/main/java/lab/game/NicerObstacle.java
+++ b/src/main/java/lab/game/NicerObstacle.java
@@ -1,10 +1,15 @@
 package lab.game;
 
+import java.io.Serial;
+
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
 public class NicerObstacle extends WorldEntity {
 
+	@Serial
+	private static final long serialVersionUID = -6623353377339746275L;
+	
 	private static Image image;
 
 	public NicerObstacle(Level level, MyPoint position) {
@@ -12,18 +17,18 @@ public class NicerObstacle extends WorldEntity {
 	}
 
 	private static Image getImage() {
-		if (image == null) {
+		if(image == null){
 			image = new Image(NicerObstacle.class.getResourceAsStream("spike.gif"));
 		}
 		return image;
 	}
-
+	
 	public void drawInternal(GraphicsContext gc) {
 		gc.drawImage(getImage(), position.getX(), position.getY());
 	}
 
 	public void simulate(double delay) {
-		/* nothing to do */
+		/*nothing to do*/
 	}
 
 }
diff --git a/src/main/java/lab/game/Obstacle.java b/src/main/java/lab/game/Obstacle.java
index 4bc5a981ff3b3349cc41a32640267c5d650eb696..285fdb7e7d190fb4530381e99b74df1f30c0989a 100644
--- a/src/main/java/lab/game/Obstacle.java
+++ b/src/main/java/lab/game/Obstacle.java
@@ -1,11 +1,15 @@
 package lab.game;
 
+import java.io.Serial;
+
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.paint.Color;
 import lab.Config;
 
 public class Obstacle extends WorldEntity {
 
+	@Serial
+	private static final long serialVersionUID = 3430702588557969248L;
 	private MyDimension size;
 
 	public Obstacle(Level level) {
@@ -27,7 +31,7 @@ public class Obstacle extends WorldEntity {
 	}
 
 	public void simulate(double delay) {
-		/* nothing to do */
+		/*nothing to do*/
 	}
 
 }
diff --git a/src/main/java/lab/game/Player.java b/src/main/java/lab/game/Player.java
index 1c84de4b3beaee839d217eb1d0d242e3e3e0947c..8ad0eda3ff0b64951e4bca29261c36d12ab0ca08 100644
--- a/src/main/java/lab/game/Player.java
+++ b/src/main/java/lab/game/Player.java
@@ -1,5 +1,6 @@
 package lab.game;
 
+import java.io.Serial;
 import java.util.Random;
 
 import javafx.geometry.Rectangle2D;
@@ -12,6 +13,9 @@ import lab.Config;
 
 public class Player extends WorldEntity implements Collisionable {
 
+	@Serial
+	private static final long serialVersionUID = -4487836387706082936L;
+
 	private static final Random RANDOM = new Random();
 
 	private MyPoint speed;
diff --git a/src/main/java/lab/game/WorldEntity.java b/src/main/java/lab/game/WorldEntity.java
index 965ef45510c362cb3b4f82929e8fde32dcc6c699..067e052856e5a09a92410ab4f36ef6c78d5c8b38 100644
--- a/src/main/java/lab/game/WorldEntity.java
+++ b/src/main/java/lab/game/WorldEntity.java
@@ -1,10 +1,16 @@
 package lab.game;
 
+import java.io.Serial;
+import java.io.Serializable;
+
 import javafx.scene.canvas.GraphicsContext;
 
-public abstract class WorldEntity implements DrawableSimulable {
+public abstract  class WorldEntity implements DrawableSimulable, Serializable {
 
-	protected final Level level;
+	@Serial
+	private static final long serialVersionUID = 2626363250832813659L;
+	
+	protected transient final Level level;
 	protected MyPoint position;
 	private int zIndex;
 
@@ -36,5 +42,5 @@ public abstract class WorldEntity implements DrawableSimulable {
 	public int getZIndex() {
 		return zIndex;
 	}
-
+	
 }