diff --git a/src/main/java/lab/game/Bullet.java b/src/main/java/lab/game/Bullet.java
index dae49cb0530168e912dfa57b0a92219f4e825e00..59537e0967c1dbf06c87996b0a4f783730eb7fae 100644
--- a/src/main/java/lab/game/Bullet.java
+++ b/src/main/java/lab/game/Bullet.java
@@ -1,11 +1,16 @@
 package lab.game;
 
+import java.io.Serial;
+
 import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.paint.Color;
 
 public class Bullet extends WorldEntity implements Collisionable{
 	
+	@Serial
+	private static final long serialVersionUID = -3773585484081897646L;
+
 	private static final double SIZE = 20;
 
 	protected final MyPoint acceleration;
diff --git a/src/main/java/lab/game/BulletAnimated.java b/src/main/java/lab/game/BulletAnimated.java
index e4a9a118f8cbdf8bd1e9c254d93e76acbe4c356a..99532f0e1820b0b29706333815fb283d8ba992ba 100644
--- a/src/main/java/lab/game/BulletAnimated.java
+++ b/src/main/java/lab/game/BulletAnimated.java
@@ -1,5 +1,6 @@
 package lab.game;
 
+import java.io.Serial;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -8,11 +9,14 @@ import javafx.scene.image.Image;
 
 public class BulletAnimated extends Bullet {
 
+	@Serial
+	private static final long serialVersionUID = 4366455699671618979L;
+	
 	private static final double SIZE = 40;
 	private Cannon cannon;
 	private static Image image = new Image(BulletAnimated.class.getResourceAsStream("fireball-transparent.gif"));
 	
-	private List<HitListener> hitListeners = new ArrayList<>();
+	private transient List<HitListener> hitListeners = new ArrayList<>();
 
 	public BulletAnimated(World world, Cannon cannon, MyPoint position, MyPoint velocity, MyPoint acceleration) {
 		super(world, position, velocity, acceleration);
diff --git a/src/main/java/lab/game/Cannon.java b/src/main/java/lab/game/Cannon.java
index d9a98063aa198b12c2d58f1f673d875286bb2e95..064f81e1e23996a2056e68bb95a9e578b3986843 100644
--- a/src/main/java/lab/game/Cannon.java
+++ b/src/main/java/lab/game/Cannon.java
@@ -1,5 +1,7 @@
 package lab.game;
 
+import java.io.Serial;
+
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.paint.Color;
 import javafx.scene.transform.Affine;
@@ -7,6 +9,9 @@ import javafx.scene.transform.Transform;
 
 public class Cannon extends WorldEntity {
 
+	@Serial
+	private static final long serialVersionUID = 2092588800016758726L;
+	
 	private static final double LENGTH = 60;
 	private static final double WIDTH = 15;
 	private double angle;
@@ -25,7 +30,7 @@ public class Cannon extends WorldEntity {
 
 	@Override
 	public void simulate(double deltaT) {
-		/* nothing to do */
+		/*nothing to do*/
 	}
 
 	public double getAngle() {
diff --git a/src/main/java/lab/game/Ufo.java b/src/main/java/lab/game/Ufo.java
index 6aff6f0cbe536dd9db0dce2602567407b49c5aae..bc5116851fd4556a55c6521f76d5f10a313f809f 100644
--- a/src/main/java/lab/game/Ufo.java
+++ b/src/main/java/lab/game/Ufo.java
@@ -1,5 +1,6 @@
 package lab.game;
 
+import java.io.Serial;
 import java.time.LocalDateTime;
 import java.util.Random;
 
@@ -13,6 +14,9 @@ import lab.Setting;
 
 public class Ufo extends WorldEntity implements Collisionable {
 
+	@Serial
+	private static final long serialVersionUID = -2830189192945805617L;
+
 	private static Logger log = LogManager.getLogger(Ufo.class);
 
 	private static final Random RANDOM = new Random();
diff --git a/src/main/java/lab/game/World.java b/src/main/java/lab/game/World.java
index d2cb07af8d6430bb11b8e987346fb263757e5c13..b649853d27bc1397f5ec7e230049e2fa4877baa1 100644
--- a/src/main/java/lab/game/World.java
+++ b/src/main/java/lab/game/World.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.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedList;
@@ -18,6 +25,8 @@ public class World {
 
 	private final double height;
 
+	private Object entitiesLock = new Object();
+
 	private List<DrawableSimulable> entities;
 	private Collection<DrawableSimulable> entitiesToRemove = new LinkedList<>();
 	private Collection<DrawableSimulable> entitiesToAdd = new LinkedList<>();
@@ -50,11 +59,65 @@ public class World {
 	}
 
 	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();
+					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();
 	}
 
 	public void add(UfoDestroyLog ufoDestroyLog) {
@@ -71,8 +134,10 @@ public class World {
 		gc.clearRect(0, 0, width, height);
 
 		gc.save();
-		for (DrawableSimulable entity : entities) {
-			entity.draw(gc);
+		synchronized (entitiesLock) {
+			for (DrawableSimulable entity : entities) {
+				entity.draw(gc);
+			}
 		}
 		gc.restore();
 	}
@@ -81,14 +146,16 @@ public class World {
 		if (viewMode) {
 			return;
 		}
-		for (DrawableSimulable entity : entities) {
-			entity.simulate(deltaT);
+		synchronized (entitiesLock) {
+			for (DrawableSimulable entity : entities) {
+				entity.simulate(deltaT);
+			}
+			detectCollision();
+			entities.removeAll(entitiesToRemove);
+			entities.addAll(entitiesToAdd);
+			entitiesToAdd.clear();
+			entitiesToRemove.clear();
 		}
-		detectCollision();
-		entities.removeAll(entitiesToRemove);
-		entities.addAll(entitiesToAdd);
-		entitiesToAdd.clear();
-		entitiesToRemove.clear();
 	}
 
 	private void detectCollision() {
diff --git a/src/main/java/lab/game/WorldEntity.java b/src/main/java/lab/game/WorldEntity.java
index 7ab784afe5c1fe453f70d4204ec39e47dc6840bb..8bcfb3870bacf76f706232d7494ff416e5e3a765 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 World world;
+	@Serial
+	private static final long serialVersionUID = -8041266267302181620L;
+	
+	protected final transient World world;
 	protected MyPoint position;
 
 	protected WorldEntity(World world, MyPoint position) {