diff --git a/.gitignore b/.gitignore
index a18dabfb9c88c83f8413e54182007abf5a7d3b05..f2b2400d0f5d8b022611dd4ae94cb49657f40974 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,4 +8,7 @@ export_presets.cfg
 
 # Mono-specific ignores
 .mono/
-data_*/
\ No newline at end of file
+data_*/
+
+*.pck
+*.x86_64
diff --git a/client/assets/entities/playerArrow/playerArrow.png b/client/assets/entities/playerArrow/playerArrow.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b658158b6a2211b656d83fee35e3941e5ad376a
Binary files /dev/null and b/client/assets/entities/playerArrow/playerArrow.png differ
diff --git a/client/assets/entities/playerArrow/playerArrow.png.import b/client/assets/entities/playerArrow/playerArrow.png.import
new file mode 100644
index 0000000000000000000000000000000000000000..e226ddb01849ae62ba2912918694aa9fc84bf8f3
--- /dev/null
+++ b/client/assets/entities/playerArrow/playerArrow.png.import
@@ -0,0 +1,36 @@
+[remap]
+
+importer="texture"
+type="StreamTexture"
+path.s3tc="res://.import/playerArrow.png-e97837ed9d5dd05df0543bd68ce1f6fa.s3tc.stex"
+path.etc2="res://.import/playerArrow.png-e97837ed9d5dd05df0543bd68ce1f6fa.etc2.stex"
+metadata={
+"imported_formats": [ "s3tc", "etc2" ],
+"vram_texture": true
+}
+
+[deps]
+
+source_file="res://assets/entities/playerArrow/playerArrow.png"
+dest_files=[ "res://.import/playerArrow.png-e97837ed9d5dd05df0543bd68ce1f6fa.s3tc.stex", "res://.import/playerArrow.png-e97837ed9d5dd05df0543bd68ce1f6fa.etc2.stex" ]
+
+[params]
+
+compress/mode=2
+compress/lossy_quality=0.7
+compress/hdr_mode=0
+compress/bptc_ldr=0
+compress/normal_map=0
+flags/repeat=true
+flags/filter=true
+flags/mipmaps=true
+flags/anisotropic=false
+flags/srgb=2
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/HDR_as_SRGB=false
+process/invert_color=false
+stream=false
+size_limit=0
+detect_3d=false
+svg/scale=1.0
diff --git a/client/assets/icon.png.import b/client/assets/icon.png.import
index 4e9f7bbe50c90bcd21d14777ed715c442566ac91..fe09de77b570be2b21f561d3335ba0a4834019ae 100644
--- a/client/assets/icon.png.import
+++ b/client/assets/icon.png.import
@@ -2,26 +2,28 @@
 
 importer="texture"
 type="StreamTexture"
-path="res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex"
+path.s3tc="res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.s3tc.stex"
+path.etc2="res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.etc2.stex"
 metadata={
-"vram_texture": false
+"imported_formats": [ "s3tc", "etc2" ],
+"vram_texture": true
 }
 
 [deps]
 
 source_file="res://assets/icon.png"
-dest_files=[ "res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.stex" ]
+dest_files=[ "res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.s3tc.stex", "res://.import/icon.png-b6a7fb2db36edd3d95dc42f1dc8c1c5d.etc2.stex" ]
 
 [params]
 
-compress/mode=0
+compress/mode=2
 compress/lossy_quality=0.7
 compress/hdr_mode=0
 compress/bptc_ldr=0
 compress/normal_map=0
-flags/repeat=0
+flags/repeat=true
 flags/filter=true
-flags/mipmaps=false
+flags/mipmaps=true
 flags/anisotropic=false
 flags/srgb=2
 process/fix_alpha_border=true
@@ -30,5 +32,5 @@ process/HDR_as_SRGB=false
 process/invert_color=false
 stream=false
 size_limit=0
-detect_3d=true
+detect_3d=false
 svg/scale=1.0
diff --git a/client/project.godot b/client/project.godot
index 8f39ebe9ebdaebeeefbf2dbda2c76c8fb0e343f1..3ba3c32058feec4b17dd861a4eb85b5e3dcf7ac4 100644
--- a/client/project.godot
+++ b/client/project.godot
@@ -16,8 +16,38 @@ _global_script_class_icons={
 [application]
 
 config/name="client"
-run/main_scene="res://scenes/levels/Game.tscn"
-config/icon="res://icon.png"
+run/main_scene="res://scenes/levels/lobby/lobby.tscn"
+config/icon="res://assets/icon.png"
+
+[autoload]
+
+gamestate="*res://scenes/autoloads/gamestate.gd"
+
+[input]
+
+movementLeft={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":81,"unicode":0,"echo":false,"script":null)
+ ]
+}
+movementJump={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null)
+ ]
+}
+movementRight={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
+ ]
+}
+movementSprint={
+"deadzone": 0.5,
+"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777237,"unicode":0,"echo":false,"script":null)
+ ]
+}
 
 [rendering]
 
diff --git a/client/scenes/autoloads/gamestate.gd b/client/scenes/autoloads/gamestate.gd
new file mode 100644
index 0000000000000000000000000000000000000000..19a0611fef23e7c2b13990c84ff7b2d0efa8ea3d
--- /dev/null
+++ b/client/scenes/autoloads/gamestate.gd
@@ -0,0 +1,62 @@
+extends Node
+
+const GAMEPATH = "/root/game/"
+
+var players = {}
+
+signal connected_to_server
+signal connection_failed
+signal server_disconnected
+
+
+func joinServer(ip, port):
+	# Create the network client
+	var peer_join = NetworkedMultiplayerENet.new()
+	peer_join.create_client(ip, int(port))
+	get_tree().set_network_peer(peer_join)
+	
+	print("Trying to join the server ", ip, ":", port) 
+
+
+puppet func registerPlayer(id): 
+	players[id] = str(id)
+	print("Player add, id: ", id) 
+
+
+puppet func removePlayer(id):
+	players.erase(id)
+	if has_node(GAMEPATH+str(id)):
+		get_node(GAMEPATH+str(id)).queue_free()
+	
+	print("Player ", str(id), " removed")
+
+
+puppet func startGame():
+	print("The server has started the game (you lost btw)")
+	print("players: ", players.values())
+
+	get_node("/root/lobby").hide()
+	
+	var game = preload("res://scenes/levels/game/game.tscn").instance()
+	var player_scene = preload("res://scenes/entities/player/player.tscn")
+	get_tree().get_root().add_child(game)
+	
+	# TODO: check (and perhaps) the scene changing functionality
+	# get_tree().change_scene("res://scenes/levels/game/game.tscn")
+
+	#Next evey player will spa every other player including the server's own client! Try to move this to server only 
+	var i = 1
+	for peer_id in players:
+		var player = player_scene.instance()
+		
+		player.set_name(str(peer_id))
+		get_node(GAMEPATH).add_child(player)
+			
+		
+		var spawnPosition = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation()
+		player.translate(spawnPosition)
+		
+		i+=1
+		
+	var playerArrow = preload("res://scenes/entities/playerArrow/playerArrow.tscn").instance()
+	get_node(GAMEPATH+str(get_tree().get_network_unique_id())).add_child(playerArrow)
\ No newline at end of file
diff --git a/client/scenes/autoloads/globals.gd b/client/scenes/autoloads/globals.gd
deleted file mode 100644
index 0d9e32b4c2ed9620ba77669386e18b477a038993..0000000000000000000000000000000000000000
--- a/client/scenes/autoloads/globals.gd
+++ /dev/null
@@ -1 +0,0 @@
-const test = 42o
diff --git a/client/scenes/entities/bloc/bloc.tscn b/client/scenes/entities/bloc/bloc.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..8d6ebc3ba58db8abda997e096e88ea203ec61150
--- /dev/null
+++ b/client/scenes/entities/bloc/bloc.tscn
@@ -0,0 +1,10 @@
+[gd_scene load_steps=2 format=2]
+
+[sub_resource type="CubeMesh" id=1]
+
+[node name="Bloc" type="Spatial"]
+
+[node name="MeshInstance" type="MeshInstance" parent="."]
+transform = Transform( 0.5, 0, 0, 0, 0.3, 0, 0, 0, 1, 0, 0, 0 )
+mesh = SubResource( 1 )
+material/0 = null
diff --git a/client/scenes/entities/player/Player.gd b/client/scenes/entities/player/Player.gd
deleted file mode 100644
index 233131b27ed8b917b293cad19f4345929f73b10f..0000000000000000000000000000000000000000
--- a/client/scenes/entities/player/Player.gd
+++ /dev/null
@@ -1,81 +0,0 @@
-extends Spatial
-
-var player
-
-var vel:Vector3 = Vector3()
-const MAX_SPEED:float = 8.0
-
-const ACCEL:float = 8.5
-const SPRINT_ACCEL:float = 16.0
-const DEACCEL:float = 16.0
-
-const MAX_SPRINT_SPEED:float = 12.0
-var is_sprinting:bool = false
-
-const JUMP_SPEED:float = 16.0
-const GRAVITY:float = -28.0
-
-const MAX_SLOPE_ANGLE:int = 40
-
-var dir:Vector3 = Vector3()
-
-func _ready():
-	player = $KinematicBody
-
-func _physics_process(delta):
-	
-	process_input(delta)
-	process_movement(delta)
-	
-func process_input(delta):
-	
-	dir = Vector3()
-	var input_movement:int = 0
-	
-	if Input.is_action_pressed("movement_left"):
-		input_movement = -1
-	if Input.is_action_pressed("movement_right"):
-		input_movement = 1
-		
-	if player.is_on_floor() || player.is_on_wall():
-		if Input.is_action_just_pressed("movement_jump"):
-			vel.y = JUMP_SPEED
-		
-	if Input.is_action_pressed("movement_sprint"):
-		is_sprinting = true
-	else:
-		is_sprinting = false
-		
-	dir.x = input_movement
-
-func process_movement(delta):
-	
-	dir.y = 0
-	dir.z = 0
-	# dir = dir.normalized()
-	
-	vel.y += delta * GRAVITY
-	
-	var hvel:Vector3 = vel
-	hvel.y = 0
-	hvel.z = 0
-	
-	var target = dir
-	if is_sprinting:
-		target *= MAX_SPRINT_SPEED
-	else:
-		target *= MAX_SPEED
-	
-	var accel
-	if dir.dot(hvel)>0:
-		if is_sprinting:
-			accel = SPRINT_ACCEL
-		else:
-			accel = ACCEL
-	else:
-		accel = DEACCEL
-		
-	hvel = hvel.linear_interpolate(target, accel * delta)
-	vel.x = hvel.x
-		
-	vel = player.move_and_slide(vel, Vector3(0,1,0), 0.05, 4, deg2rad(MAX_SLOPE_ANGLE))
\ No newline at end of file
diff --git a/client/scenes/entities/player/Player.tscn b/client/scenes/entities/player/Player.tscn
deleted file mode 100644
index 5fbde1dd90d0ae37730378cbdd608d39a908c47d..0000000000000000000000000000000000000000
--- a/client/scenes/entities/player/Player.tscn
+++ /dev/null
@@ -1,35 +0,0 @@
-[gd_scene load_steps=4 format=2]
-
-[ext_resource path="res://scenes/entities/player/Player.gd" type="Script" id=1]
-
-[sub_resource type="CapsuleShape" id=1]
-radius = 0.209134
-
-[sub_resource type="BoxShape" id=2]
-extents = Vector3( 0.236482, 0.0564314, 0.280348 )
-
-[node name="Player" type="Spatial"]
-script = ExtResource( 1 )
-
-[node name="KinematicBody" type="KinematicBody" parent="."]
-
-[node name="Body_CollisionShape" type="CollisionShape" parent="KinematicBody"]
-transform = Transform( 1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0.585563, 0 )
-shape = SubResource( 1 )
-
-[node name="Feet_CollisionShape" type="CollisionShape" parent="KinematicBody"]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.131137, 0 )
-shape = SubResource( 2 )
-
-[node name="Model" type="Spatial" parent="KinematicBody"]
-
-[node name="CSGBox" type="CSGBox" parent="KinematicBody/Model"]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 )
-width = 0.35
-height = 1.05787
-depth = 0.684
-
-[node name="CSGSphere" type="CSGSphere" parent="KinematicBody/Model"]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 )
-radius = 0.2
-radial_segments = 24
diff --git a/client/scenes/entities/player/player.gd b/client/scenes/entities/player/player.gd
new file mode 100644
index 0000000000000000000000000000000000000000..b1de2aa2cdf1c54b31805c473a44b2da1b719249
--- /dev/null
+++ b/client/scenes/entities/player/player.gd
@@ -0,0 +1,5 @@
+extends KinematicBody
+
+# Update the player's position based on the position computed by the remote scene on the server
+puppet func getRemoteMovement(position):
+	self.set_translation(position)
\ No newline at end of file
diff --git a/client/scenes/entities/player/player.tscn b/client/scenes/entities/player/player.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..3cfc97070d9f06f2c9f605a0f46537fc35f9860a
--- /dev/null
+++ b/client/scenes/entities/player/player.tscn
@@ -0,0 +1,19 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://scenes/entities/player/player.gd" type="Script" id=1]
+
+[node name="Player" type="KinematicBody"]
+script = ExtResource( 1 )
+
+[node name="Model" type="Spatial" parent="."]
+
+[node name="CSGBox" type="CSGBox" parent="Model"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 )
+width = 0.35
+height = 1.05787
+depth = 0.684
+
+[node name="CSGSphere" type="CSGSphere" parent="Model"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 )
+radius = 0.2
+radial_segments = 24
diff --git a/client/scenes/entities/playerArrow/playerArrow.tscn b/client/scenes/entities/playerArrow/playerArrow.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..956f3ef3ff4e514ae7d876e029db18262ff7bd22
--- /dev/null
+++ b/client/scenes/entities/playerArrow/playerArrow.tscn
@@ -0,0 +1,7 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://assets/entities/playerArrow/playerArrow.png" type="Texture" id=1]
+
+[node name="playerArrow" type="Sprite3D"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.75, 0 )
+texture = ExtResource( 1 )
diff --git a/client/scenes/levels/Game.tscn b/client/scenes/levels/Game.tscn
deleted file mode 100644
index 612844743e859f4178e30ffa0b5bf0b084972b69..0000000000000000000000000000000000000000
--- a/client/scenes/levels/Game.tscn
+++ /dev/null
@@ -1,25 +0,0 @@
-[gd_scene load_steps=4 format=2]
-
-[ext_resource path="res://scenes/entities/player/Player.tscn" type="PackedScene" id=1]
-[ext_resource path="res://Camera.gd" type="Script" id=2]
-[ext_resource path="res://scenes/entities/bloc/Bloc.tscn" type="PackedScene" id=3]
-
-
-
-[node name="Spatial" type="Spatial"]
-
-[node name="Player" parent="." instance=ExtResource( 1 )]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.80767, 0 )
-
-[node name="Camera" type="Camera" parent="."]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.08, 18.986 )
-fov = 30.0
-script = ExtResource( 2 )
-
-[node name="Structure" type="Spatial" parent="."]
-
-[node name="Bloc" parent="Structure" instance=ExtResource( 3 )]
-transform = Transform( 10, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
-
-[node name="Bloc2" parent="Structure" instance=ExtResource( 3 )]
-transform = Transform( 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.15191, 0 )
diff --git a/client/scenes/levels/game/game.gd b/client/scenes/levels/game/game.gd
new file mode 100644
index 0000000000000000000000000000000000000000..4209e3a26a417c6ba05fce97ef707fbcba1611c3
--- /dev/null
+++ b/client/scenes/levels/game/game.gd
@@ -0,0 +1,29 @@
+extends Node
+
+var movementInput:int = 0
+var jumpInput:bool = false
+var sprintInput:bool = false
+
+func _physics_process(delta):
+	getPlayerInput()
+	
+func getPlayerInput():
+	movementInput = 0
+		
+	if Input.is_action_pressed("movementLeft"):
+		movementInput -= 1
+	if Input.is_action_pressed("movementRight"):
+		movementInput += 1
+		
+	if Input.is_action_pressed("movementJump"):
+		jumpInput = true
+	else:
+		jumpInput = false
+		
+	if Input.is_action_pressed("movementSprint"):
+		sprintInput = true
+	else:
+		sprintInput = false
+	
+	# Sent without safety resend
+	rpc_unreliable_id(1, "sendPlayerInputs", movementInput, sprintInput, jumpInput)
\ No newline at end of file
diff --git a/client/scenes/levels/game/game.tscn b/client/scenes/levels/game/game.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..b024073bf74f71db10408aecf92de1329ff4fe5c
--- /dev/null
+++ b/client/scenes/levels/game/game.tscn
@@ -0,0 +1,30 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://scenes/levels/game/game.gd" type="Script" id=1]
+[ext_resource path="res://scenes/entities/bloc/bloc.tscn" type="PackedScene" id=2]
+
+[node name="game" type="Spatial"]
+script = ExtResource( 1 )
+
+[node name="camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.08, 52.4675 )
+fov = 30.0
+
+[node name="structure" type="Spatial" parent="."]
+
+[node name="bloc" parent="structure" instance=ExtResource( 2 )]
+transform = Transform( 10, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
+
+[node name="bloc2" parent="structure" instance=ExtResource( 2 )]
+transform = Transform( 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.15191, 0 )
+
+[node name="spawnCollection" type="Spatial" parent="."]
+
+[node name="spawn1" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 6, 0 )
+
+[node name="spawn2" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, 0 )
+
+[node name="spawn3" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 6, 0 )
diff --git a/client/scenes/levels/lobby/lobby.gd b/client/scenes/levels/lobby/lobby.gd
new file mode 100644
index 0000000000000000000000000000000000000000..0603a645ee166e46207be127816417a0dc1141c0
--- /dev/null
+++ b/client/scenes/levels/lobby/lobby.gd
@@ -0,0 +1,36 @@
+extends Control
+
+func _ready():
+	#gamestate.connect("connected_to_server", self, "_player_connected")
+	get_tree().connect("connected_to_server", self, "_player_connected")
+	get_tree().connect("connection_failed", self, "_connection_failed")
+	get_tree().connect("server_disconnected", self, "_player_disconnected")
+
+
+func _on_joinButton_pressed():
+	
+	# Get and check the Ip
+	var ip = get_node("menu/ipLineEdit").text
+	if not ip.is_valid_ip_address():
+		get_node("menu/errorLabel").text = "Invalid IPv4 address!"
+		return
+
+	# Get and check the port
+	var port = get_node("menu/portLineEdit").text
+	if port == "":
+		get_node("menu/errorLabel").text = "Invalid port!"
+		return
+
+	get_node("menu/errorLabel").text=""
+	get_node("menu/joinButton").disabled = true
+	
+	gamestate.joinServer(ip, port)
+
+#func _player_connected():
+#	print("You successfuly joined the server with the id " + str(gamestate.get_network_unique_id()))
+#
+#func _connection_failed():
+#	print("Connection failure")
+#
+#func _player_disconnected():
+#	print("You disconnected the server")
\ No newline at end of file
diff --git a/client/scenes/levels/lobby/lobby.tscn b/client/scenes/levels/lobby/lobby.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..0d19c5a3093e480d13c13afacaa0bd4cb392609b
--- /dev/null
+++ b/client/scenes/levels/lobby/lobby.tscn
@@ -0,0 +1,78 @@
+[gd_scene load_steps=2 format=2]
+
+[ext_resource path="res://scenes/levels/lobby/lobby.gd" type="Script" id=1]
+
+[node name="lobby" type="Control"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+script = ExtResource( 1 )
+
+[node name="menu" type="Panel" parent="."]
+margin_right = 506.0
+margin_bottom = 302.0
+
+[node name="ipLabel" type="Label" parent="menu"]
+margin_left = 25.0
+margin_top = 30.0
+margin_right = 105.0
+margin_bottom = 45.0
+rect_pivot_offset = Vector2( 85, -10 )
+text = "IP:"
+
+[node name="ipLineEdit" type="LineEdit" parent="menu"]
+margin_left = 25.0
+margin_top = 55.0
+margin_right = 125.0
+margin_bottom = 90.0
+rect_pivot_offset = Vector2( 55, 16 )
+hint_tooltip = "91.121.81.74 : lucas
+127.0.0.1 : local"
+text = "127.0.0.1"
+
+[node name="portLabel" type="Label" parent="menu"]
+margin_left = 155.0
+margin_top = 30.0
+margin_right = 255.0
+margin_bottom = 45.0
+text = "Port:"
+
+[node name="portLineEdit" type="LineEdit" parent="menu"]
+margin_left = 155.0
+margin_top = 55.0
+margin_right = 255.0
+margin_bottom = 90.0
+rect_pivot_offset = Vector2( 55, 16 )
+hint_tooltip = "défini en dur: 10001"
+text = "10001"
+
+[node name="nameLabel" type="Label" parent="menu"]
+margin_left = 25.0
+margin_top = 130.0
+margin_right = 105.0
+margin_bottom = 145.0
+rect_pivot_offset = Vector2( 85, -10 )
+text = "Name:"
+
+[node name="nameLineEdit" type="LineEdit" parent="menu"]
+margin_left = 25.0
+margin_top = 155.0
+margin_right = 125.0
+margin_bottom = 190.0
+rect_pivot_offset = Vector2( 55, 16 )
+hint_tooltip = "91.121.81.74 : lucas
+127.0.0.1 : local"
+text = "Player"
+
+[node name="joinButton" type="Button" parent="menu"]
+margin_left = 319.0
+margin_top = 133.0
+margin_right = 398.0
+margin_bottom = 181.0
+text = "Join"
+
+[node name="errorLabel" type="Label" parent="menu"]
+margin_left = 55.0
+margin_top = 244.0
+margin_right = 455.0
+margin_bottom = 277.0
+[connection signal="pressed" from="menu/joinButton" to="." method="_on_joinButton_pressed"]
diff --git a/client/scenes/levels/testnetwork/Node.gd b/client/scenes/levels/testnetwork/Node.gd
deleted file mode 100644
index a936c80ab4bae3cc2a2608e4e4411a1476f74423..0000000000000000000000000000000000000000
--- a/client/scenes/levels/testnetwork/Node.gd
+++ /dev/null
@@ -1,40 +0,0 @@
-#client
-
-extends Node
-
-var peer = NetworkedMultiplayerENet.new()
-export var is_server = false
-
-func _ready():
-	peer.create_client("91.121.81.74",10001)
-	get_tree().set_network_peer(peer)
-	
-	get_tree().connect("connected_to_server", self, "_connected_ok") #connexion effectuée
-	get_tree().connect("connection_failed", self, "_connected_failed") #connextion error
-	get_tree().connect("server_disconnected", self, "_server_disconnected") #déconnexion
-		
-		
-
-
-	
-remote func get_message(mess):
-	if mess == "quit":
-		print("Received order to quit")
-		get_tree().set_network_peer(null)
-		get_tree().quit()
-	else:
-		print(mess)
-
-#Quand connexion effectuée
-func _connected_ok():
-	print("Connection to server successful")
-	set_network_master(get_tree().get_network_unique_id())
-	rpc("get_message","Hello there")
-	rpc("get_message","quit")
-	
-#Quand connection error
-func _connected_failed():
-	print("Failed to connect to server")	
-
-
-
diff --git a/client/scenes/levels/testnetwork/Node.tscn b/client/scenes/levels/testnetwork/Node.tscn
deleted file mode 100644
index 2e8394175f5e19cf806e3a6a35b99c9987397086..0000000000000000000000000000000000000000
--- a/client/scenes/levels/testnetwork/Node.tscn
+++ /dev/null
@@ -1,7 +0,0 @@
-[gd_scene load_steps=2 format=2]
-
-[ext_resource path="res://scenes/levels/testnetwork/Node.gd" type="Script" id=1]
-
-
-[node name="Node" type="Node"]
-script = ExtResource( 1 )
diff --git a/server/icon.png.import b/server/icon.png.import
old mode 100755
new mode 100644
diff --git a/server/project.godot b/server/project.godot
index 5c7800efe543ba77e794903c86c34d4f2d159993..60cd1c0d90b3ac984dedd757913c62145c9959c7 100644
--- a/server/project.godot
+++ b/server/project.godot
@@ -16,9 +16,13 @@ _global_script_class_icons={
 [application]
 
 config/name="server"
-run/main_scene="res://scenes/Node.tscn"
+run/main_scene="res://scenes/levels/lobby/lobby.tscn"
 config/icon="res://icon.png"
 
+[autoload]
+
+gamestate="*res://scenes/autoloads/gamestate.gd"
+
 [rendering]
 
 environment/default_environment="res://default_env.tres"
diff --git a/server/scenes/Node.tscn b/server/scenes/Node.tscn
deleted file mode 100644
index 6fd2dd1d24acb3a91e9af7e80a052a9314fc6a0e..0000000000000000000000000000000000000000
--- a/server/scenes/Node.tscn
+++ /dev/null
@@ -1,6 +0,0 @@
-[gd_scene load_steps=2 format=2]
-
-[ext_resource path="res://scripts/Node.gd" type="Script" id=1]
-
-[node name="Node" type="Node"]
-script = ExtResource( 1 )
diff --git a/server/scenes/autoloads/gamestate.gd b/server/scenes/autoloads/gamestate.gd
new file mode 100644
index 0000000000000000000000000000000000000000..d355e540a5609abbc53da1733feff5572b5593a6
--- /dev/null
+++ b/server/scenes/autoloads/gamestate.gd
@@ -0,0 +1,86 @@
+extends Node
+
+const GAMEPATH = "/root/game/"
+
+const PORT = 10001
+const MAX_CLIENTS = 1
+
+var players = {}
+
+func _ready():
+	# When a client connects to the server
+	get_tree().connect("network_peer_connected", self, "_playerConnected")
+	# When a client disconnects gracefully or times out
+	get_tree().connect("network_peer_disconnected", self, "_playerDisconnected")
+	
+	# Server init
+	var peer = NetworkedMultiplayerENet.new()
+	peer.create_server(PORT, MAX_CLIENTS)
+	get_tree().set_network_peer(peer)
+	
+	print("Server now hosting")
+
+
+# Called when a player connects
+func _playerConnected(id):
+	if (players.size()>MAX_CLIENTS):
+		print("There is already enough players")
+		return
+		
+	else:
+		registerPlayer(id)
+		
+	if (players.size()==MAX_CLIENTS):
+		startGame()
+
+
+func registerPlayer(id):
+	# Sending the list of existing players to the new player from ther server's personal list
+	for peer_id in players:
+		rpc_id(peer_id, "registerPlayer", id)
+		rpc_id(id, "registerPlayer", peer_id)
+		
+	# Granting self-awareness
+	rpc_id(id, "registerPlayer", id)
+		
+	# Adding the new id to anyones array
+	players[id] = str(id)
+	
+	print("New player registered: ", id) 
+
+
+func _playerDisconnected(id):
+	players.erase(id)
+	
+	# Broadcast the info and remove from the remote scene
+	if has_node(GAMEPATH+str(id)):
+		rpc("removePlayer", id)
+		get_node(GAMEPATH+str(id)).queue_free()
+	
+	print("Player ", str(id), " disconnected")
+
+
+func startGame():
+	# Instancing the map and adding it to the scene tree
+	var game = preload("res://scenes/levels/game/game.tscn").instance()
+	get_tree().get_root().add_child(game)
+	
+	var playerScene = preload("res://scenes/entities/player/player.tscn")
+
+	var i = 1
+	for peer_id in players:
+		# TODO: Replace by a spawnPlayer function !!!
+		var player = playerScene.instance()
+		
+		player.set_name(str(peer_id))
+		get_node(GAMEPATH).add_child(player)
+		
+		var spawnPosition = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation()
+		player.translate(spawnPosition)
+		
+		i+=1
+	
+	# Broadcast the beginning of the game
+	rpc("startGame")
+
+	print("game started with players ", players.values())
\ No newline at end of file
diff --git a/client/scenes/entities/bloc/Bloc.tscn b/server/scenes/entities/bloc/bloc.tscn
similarity index 100%
rename from client/scenes/entities/bloc/Bloc.tscn
rename to server/scenes/entities/bloc/bloc.tscn
diff --git a/server/scenes/entities/player/player.gd b/server/scenes/entities/player/player.gd
new file mode 100644
index 0000000000000000000000000000000000000000..3e334ba2a59d1a463002d15cca31838f9c1e6b1b
--- /dev/null
+++ b/server/scenes/entities/player/player.gd
@@ -0,0 +1,75 @@
+extends KinematicBody
+
+# duh
+const MAX_SPEED:float = 8.0
+
+# duh 2
+const ACCEL:float = 8.5
+const SPRINT_ACCEL:float = 16.0
+const DEACCEL:float = 16.0
+
+# duh 3: the vengeance
+const MAX_SPRINT_SPEED:float = 12.0
+var isSprinting:bool = false
+
+# duh 4: the return of the vengeance 2
+const JUMP_SPEED:float = 16.0
+var isJumping:bool = false
+
+# TODO: unreal, try to understand that, genius
+const GRAVITY:float = -28.0
+
+# Velocity updated continuously by move_and_slide
+var vel:Vector3 = Vector3()
+
+const FLOOR_NORMAL:Vector3 = Vector3(0,1,0)
+
+var motion:float = 0
+
+# called by the engine
+func _physics_process(delta):
+	processMovement(delta)
+	broadcastMovement(delta)
+
+# Called from the game script to update the vars
+func getPlayerInputs(movementInput, sprintInput, jumpInput):
+	motion = movementInput
+	isSprinting = sprintInput
+	isJumping = jumpInput
+	
+func processMovement(delta):
+	if self.is_on_floor():
+		if isJumping:
+			vel.y = JUMP_SPEED
+	
+	# Consider the gravity
+	vel.y += delta * GRAVITY
+	
+	# Speed of the player
+	var target = Vector3(motion, 0, 0)
+	
+	if isSprinting:
+		target *= MAX_SPRINT_SPEED
+	else:
+		target *= MAX_SPEED
+	
+	# Acceleration of the player if he is moving horizontally
+	var accel
+	var hvel:Vector3 = Vector3(vel.x,0,0)
+	if target.dot(hvel)>0:
+		if isSprinting:
+			accel = SPRINT_ACCEL
+		else:
+			accel = ACCEL
+	else:
+		accel = DEACCEL
+		
+	# Interpolating speed and acceleration through time and getting it
+	vel.x = hvel.linear_interpolate(target, accel * delta).x
+	
+	# Update the velocity after the collisions (physical engine ftw)
+	vel = self.move_and_slide(vel, FLOOR_NORMAL)
+	
+func broadcastMovement(delta):
+	# Send the position of the player
+	rpc("getRemoteMovement", self.get_translation())
\ No newline at end of file
diff --git a/server/scenes/entities/player/player.tscn b/server/scenes/entities/player/player.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..d768d61dc6f862e4fd299022eef47f2211dd2ba5
--- /dev/null
+++ b/server/scenes/entities/player/player.tscn
@@ -0,0 +1,26 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://scenes/entities/player/player.gd" type="Script" id=1]
+
+[sub_resource type="BoxShape" id=1]
+extents = Vector3( 0.175, 0.275, 0.7 )
+
+[node name="Player" type="KinematicBody"]
+script = ExtResource( 1 )
+
+[node name="Body_CollisionShape" type="CollisionShape" parent="."]
+transform = Transform( 1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0.65, 0 )
+shape = SubResource( 1 )
+
+[node name="Model" type="Spatial" parent="."]
+
+[node name="CSGBox" type="CSGBox" parent="Model"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 )
+width = 0.35
+height = 1.05787
+depth = 0.684
+
+[node name="CSGSphere" type="CSGSphere" parent="Model"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 )
+radius = 0.2
+radial_segments = 24
diff --git a/server/scenes/levels/game/game.gd b/server/scenes/levels/game/game.gd
new file mode 100644
index 0000000000000000000000000000000000000000..6eb3b6b507fb47c8c88b09fae370d9a167995521
--- /dev/null
+++ b/server/scenes/levels/game/game.gd
@@ -0,0 +1,7 @@
+extends Node
+
+master func sendPlayerInputs(movementInput, jumpInput, sprintInput):
+	
+	# Get the input from a client and send it to the matchig remote player
+	var senderId = get_tree().get_rpc_sender_id()
+	gamestate.get_node("/root/game/"+str(senderId)).getPlayerInputs(movementInput, jumpInput, sprintInput)
\ No newline at end of file
diff --git a/server/scenes/levels/game/game.tscn b/server/scenes/levels/game/game.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..c15286266653284c58cba924d443a7ae55af5cd6
--- /dev/null
+++ b/server/scenes/levels/game/game.tscn
@@ -0,0 +1,30 @@
+[gd_scene load_steps=3 format=2]
+
+[ext_resource path="res://scenes/levels/game/game.gd" type="Script" id=1]
+[ext_resource path="res://scenes/entities/bloc/bloc.tscn" type="PackedScene" id=2]
+
+[node name="game" type="Spatial"]
+script = ExtResource( 1 )
+
+[node name="camera" type="Camera" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.08, 18.986 )
+fov = 30.0
+
+[node name="structure" type="Spatial" parent="."]
+
+[node name="bloc" parent="structure" instance=ExtResource( 2 )]
+transform = Transform( 10, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 )
+
+[node name="bloc2" parent="structure" instance=ExtResource( 2 )]
+transform = Transform( 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.15191, 0 )
+
+[node name="spawnCollection" type="Spatial" parent="."]
+
+[node name="spawn1" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 6, 0 )
+
+[node name="spawn2" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, 0 )
+
+[node name="spawn3" type="Position3D" parent="spawnCollection"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 6, 0 )
diff --git a/server/scenes/levels/lobby/lobby.tscn b/server/scenes/levels/lobby/lobby.tscn
new file mode 100644
index 0000000000000000000000000000000000000000..bc3961980ae98913184267920dbe06174468d5b9
--- /dev/null
+++ b/server/scenes/levels/lobby/lobby.tscn
@@ -0,0 +1,3 @@
+[gd_scene format=2]
+
+[node name="lobby" type="Node"]
diff --git a/server/scripts/Node.gd b/server/scripts/Node.gd
deleted file mode 100755
index 2b70dfc5fa5541e48f81941ef390b308abcbc85b..0000000000000000000000000000000000000000
--- a/server/scripts/Node.gd
+++ /dev/null
@@ -1,41 +0,0 @@
-#server
-
-extends Node
-
-var peer = NetworkedMultiplayerENet.new()
-export var PORT = 10001
-
-func _ready():
-	peer.create_server(PORT,2)
-	get_tree().set_network_peer(peer)
-	
-	get_tree().connect("network_peer_connected", self, "_player_connected") #Quand un client se connecte
-	get_tree().connect("network_peer_disconnected", self, "_player_disconnected") #Quand un client se déconnecte
-	
-		
-		
-
-#Quand un client se connecte		
-func _player_connected(id):
-	print("Player ", id, " connected")
-	set_network_master(id)
-	
-#Quand un client se déconnecte
-func _player_disconnected(id):
-	print("Player ", id, " disconnected")
-	
-
-remote func get_message(mess):
-	if mess == "quit":
-		print("Received order to quit")
-		get_tree().set_network_peer(null)
-		get_tree().quit()
-	else:
-		print(mess)
-
-	
-func _messageToAll(fct,msg):
-	rpc(fct,msg)
-
-func _messageToOne(id, fct, msg):
-	rpc(id, fct, msg)