From 56c84e1ee7093d62617159a3b262476828e4f7d9 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Sun, 22 Oct 2023 20:42:13 +0200 Subject: [PATCH] adding client --- .gitignore | 2 + client/.gitignore | 4 + client/assets/ground.jpg | Bin 0 -> 12486 bytes client/assets/player.glb | Bin 0 -> 70248 bytes client/assets/root.glb | Bin 0 -> 1948 bytes client/assets/root.tscn | 13 ++ client/icon.svg | 1 + client/project.godot | 60 ++++++++ client/scenes/Window.gd | 58 +++++++ client/scenes/main.gd | 299 ++++++++++++++++++++++++++++++++++++ client/scenes/main.gdshader | 21 +++ client/scenes/main.tscn | 89 +++++++++++ client/scenes/player.gd | 67 ++++++++ client/scenes/player.tscn | 24 +++ precheck.gd | 37 +++++ start-bazar-client.sh | 181 ++++++++++++++++++++++ 16 files changed, 856 insertions(+) create mode 100644 client/.gitignore create mode 100644 client/assets/ground.jpg create mode 100644 client/assets/player.glb create mode 100644 client/assets/root.glb create mode 100644 client/assets/root.tscn create mode 100644 client/icon.svg create mode 100644 client/project.godot create mode 100644 client/scenes/Window.gd create mode 100644 client/scenes/main.gd create mode 100644 client/scenes/main.gdshader create mode 100644 client/scenes/main.tscn create mode 100644 client/scenes/player.gd create mode 100644 client/scenes/player.tscn create mode 100644 precheck.gd create mode 100755 start-bazar-client.sh diff --git a/.gitignore b/.gitignore index 5cfae44..2126236 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .rust/ server/target/ +Godot_* +.current_version diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..0b0ef26 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,4 @@ +# Godot 4+ specific ignores +.godot/ +assets/*.import +*.import diff --git a/client/assets/ground.jpg b/client/assets/ground.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dee2d4a2f144480cda63ad72e825f1c15c5483ac GIT binary patch literal 12486 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

NN&xSG(U{Iz01WpR{;t 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 literal 0 HcmV?d00001 diff --git a/client/assets/root.glb b/client/assets/root.glb new file mode 100644 index 0000000000000000000000000000000000000000..6799653ae2fdd899beaac0d3b871bc79b687e14f GIT binary patch literal 1948 zcmb7E+fLg+5FIWp(9#R^_G<03lR9>8`pr(bmN+N`WP;rt?u$0(nZPTJCQa+>) zee7S9{#j=>cH%lfVWr&}&&)Y<*-d)==H4Oz{8#}fE(3gOn6)9ZJdgXVG-N&QaAEnb zU?ukXOt_BgDLsTJJALkSxKOHZP36K!=hHc+vI{Oe+jTHjPit(XGOvwzR?oqVEzT%pVEJ6wR)50Qaf4Q$H|!4Yu#ztV zjvSK&2Voo*cHR;P+_(CDyIpsK-kHNaL=RcZ@_5DVyJF93%O;PtbSAT<7jj0vSjcJG zR?aA>ceQ1xxG+sbh^>n#j&k1R?>0yw$riO1TkhKL(E8y*=nQ9bH!wat)ScG z;?U;bBx&0noVyNp{O093-c&B5=T+8r0|%dko+Y;Lcwf4vrZTFoQPVcw`Eg3ms3}8D zNs}+3>~ObY;6uPk$5LRS|4T80>vM4ZKJfYMIF9-3(kL4=u-7nqqf*{4*X5g=l^>s& zoL1}7=lk60`S@D(Vo_yeFuPs(3&QL7EzzSNlabxZ0H(IQFyXwfWaN!vK)L!FlNkEJRP z`kvzB_K@?=JQyG6iRyqjXQDPLAgbrKco|3hAwJ@aYK!xbPK$iA_yu?hFJS@q3Os^` su!-j;yoNXM0@m?dhv)DNmS7FfHFyONU=ddFT!qK50Z))`1NSog1%c$_SpWb4 literal 0 HcmV?d00001 diff --git a/client/assets/root.tscn b/client/assets/root.tscn new file mode 100644 index 0000000..53dc81c --- /dev/null +++ b/client/assets/root.tscn @@ -0,0 +1,13 @@ +[gd_scene load_steps=3 format=3 uid="uid://c688gu5xrshpg"] + +[ext_resource type="PackedScene" uid="uid://b5ej7nfagdlmf" path="res://assets/root.glb" id="1_s8vvr"] + +[sub_resource type="ConcavePolygonShape3D" id="ConcavePolygonShape3D_rf26g"] +data = PackedVector3Array(20, -1, -20, -21, -1, 20, -21, -1, -20, 20, -1, -20, 20, -1, 20, -21, -1, 20, 20, -3, 20, -21, -1, 20, 20, -1, 20, 20, -3, 20, -21, -3, 20, -21, -1, 20, -21, -3, 20, -21, -1, -20, -21, -1, 20, -21, -3, 20, -21, -3, -20, -21, -1, -20, -21, -3, -20, 20, -3, 20, 20, -3, -20, -21, -3, -20, -21, -3, 20, 20, -3, 20, 20, -3, -20, 20, -1, 20, 20, -1, -20, 20, -3, -20, 20, -3, 20, 20, -1, 20, -21, -3, -20, 20, -1, -20, -21, -1, -20, -21, -3, -20, 20, -3, -20, 20, -1, -20) + +[node name="root" instance=ExtResource("1_s8vvr")] + +[node name="StaticBody3D" type="StaticBody3D" parent="Cube" index="0"] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Cube/StaticBody3D" index="0"] +shape = SubResource("ConcavePolygonShape3D_rf26g") diff --git a/client/icon.svg b/client/icon.svg new file mode 100644 index 0000000..b370ceb --- /dev/null +++ b/client/icon.svg @@ -0,0 +1 @@ + diff --git a/client/project.godot b/client/project.godot new file mode 100644 index 0000000..6e4ed48 --- /dev/null +++ b/client/project.godot @@ -0,0 +1,60 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Khaganat Short Client Server" +run/main_scene="res://scenes/main.tscn" +config/features=PackedStringArray("4.1", "Forward Plus") +config/icon="res://icon.svg" + +[input] + +ui_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194319,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":113,"echo":false,"script":null) +, null] +} +ui_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194321,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) +] +} +ui_up={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194320,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":11,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"echo":false,"script":null) +] +} +ui_down={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194322,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) +] +} +ui_rotate_player={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} + +[rendering] + +environment/defaults/default_clear_color=Color(0.682353, 0.678431, 0.631373, 1) diff --git a/client/scenes/Window.gd b/client/scenes/Window.gd new file mode 100644 index 0000000..1b80c98 --- /dev/null +++ b/client/scenes/Window.gd @@ -0,0 +1,58 @@ +extends Window + +var focus_ok:bool = false +var last_event = null + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(_delta): + pass + + +func _on_button_pressed(): + if $VBoxContainer/TextEdit.get_text() != "": + self.hide() + #get_parent().get_node("CharacterBody3D").set_enable_event(true) + get_parent().connect_enet($VBoxContainer/TextEdit.get_text()) + + +func _on_text_edit_text_changed(value:String): + if len(value) > 0: + $VBoxContainer/Button.disabled = false + else: + $VBoxContainer/Button.disabled = true + + +func _on_focus_entered(): + focus_ok = true + + +func _on_focus_exited(): + focus_ok = false + + +func _on_mouse_entered(): + focus_ok = true + self.get_parent().CharacterBody3D.disabled = true + + +func _on_mouse_exited(): + focus_ok = false + self.get_parent().CharacterBody3D.disabled = false + +func open_windows(): + focus_ok = false + get_parent().get_node("CharacterBody3D").set_enable_event(false) + self.show() + +#func _on_window_input(event): +# if event.is_pressed() == false: +# return +# if focus_ok: +# return +# if (event is InputEventKey) && (self.type_event == 1): +# last_event = event diff --git a/client/scenes/main.gd b/client/scenes/main.gd new file mode 100644 index 0000000..31d868e --- /dev/null +++ b/client/scenes/main.gd @@ -0,0 +1,299 @@ +extends Node3D + +# The player name. +var player_name: String +var connected:bool = false +var enet:ENetConnection +var dataEnet:ENetPacketPeer +var errorEnet:Error +var id = 0 +var maxplayer = 0 + +# Server confirm our account +var account_confirmed:bool = false + +const PLAYER = preload("res://scenes/player.tscn") + +const PORT = 33333 +const ADDR = "127.0.0.1" + +var dtls := PacketPeerDTLS.new() +var udp := PacketPeerUDP.new() + + +func test_cert(filename): + print("------", filename) + enet = ENetConnection.new() + print(enet) + #var cert: X509Certificate = X509Certificate.new() + #errorEnet = cert.load(filename) + #print("load cert:", errorEnet) + #print(cert) + #var client_tls_options = TLSOptions.client_unsafe(cert) + #print(client_tls_options) + errorEnet = enet.create_host(10) + if errorEnet != OK: + print("ERROR ENET.create_host: ", errorEnet) + return + #enet.connect_to_host(ADDR, PORT) + #errorEnet = enet.dtls_client_setup(ADDR, client_tls_options) + #print("dtls_client_setup:", errorEnet) + #if errorEnet != OK: + # print("ERROR ENET: ", errorEnet) + # return + dataEnet = enet.connect_to_host(ADDR, PORT, 10) + print(dataEnet) + if not dataEnet.is_active(): + print("ERROR enet.connect_to_host: ", dataEnet.is_active()) + return + + +func create_server_enet(): + print("------ create_server_enet") + test_cert("res://cert.crt") + + +# Called when the node enters the scene tree for the first time. +func _ready(): + #test_cert("res://cert.crt") + create_server_enet() + pass # Replace with function body. + + +func decode_msg(data:PackedByteArray): + print("==========================") + var cmd = data.decode_u8(0) + print("cmd:", cmd) + var taille = data.decode_u8(1) + print("taille:", taille) + var str:String = "" + var tmp = data.slice(2,taille+2) + print("tmp:", tmp) + + str = tmp.get_string_from_utf8() + + print("str:", str) + print("len str:", len(str)) + + print("==========================") + +func send_account(): + var data:PackedByteArray = PackedByteArray() + + #data.encode_u8(1,0) + data.append(1) + data.append(len(player_name)) + var packed_array = player_name.to_ascii_buffer() +# var str:PackedStringArray = PackedStringArray() +# str.push_back(player_name) + data += packed_array + #data.append_array(str.to_byte_array()) + +# print("-------------------------") +# print(len(packed_array)) +# print("player_name: ", player_name) +# print("packed_array: ", packed_array) +# print("str: ", str) +# print("str -> bytes: ", str.to_byte_array()) +# print("data: ", data) +# print("-------------------------") + + print(player_name, " -> size:", data.size(), " / " , len(player_name) ) + errorEnet = dataEnet.send(1, data, 1) + if errorEnet != OK: + print("ERROR ENET: ", errorEnet) + return + #decode_msg(data) + + +func set_player_position(pos: Vector3): + self.get_node("CharacterBody3D").set_global_position(pos) + + +func get_player_position(): + if not account_confirmed: + return + print("perso: ", id, " ", self.get_node("CharacterBody3D").get_position()) + var pos:PackedFloat64Array = PackedFloat64Array() + var posRaw:Vector3 = self.get_node("CharacterBody3D").get_position() + #posRaw.x = 123456789182729270e15 + #posRaw.y = 2.0 + #posRaw.z = 3.0 + pos.append(posRaw.x) + #print("x:", pos.to_byte_array()) + pos.append(posRaw.y) + #print("x+y:", pos.to_byte_array()) + pos.append(posRaw.z) + #print("x+y+z:", pos.to_byte_array()) + var data:PackedByteArray = PackedByteArray() + data += pos.to_byte_array() + #data.append(len(player_name)) + #var packed_array = player_name.to_ascii_buffer() + #data += packed_array + #print(player_name, " -> size:", data.size(), " / " , len(player_name) ) + errorEnet = dataEnet.send(2, data, 1) + if errorEnet != OK: + print("ERROR ENET: ", errorEnet) + return + + +func bad_acocunt(): + player_name = "" + self.get_node("Window").open_windows() + + +func get_event_received(): + var data = dataEnet.get_packet() + print("get: ", data) + if data[0] == 1: # Return connexion + if data[1] == 0: # OK + id = data.decode_u64(2) + var x = data.decode_double(2+8) + var y = data.decode_double(2+16) + var z = data.decode_double(2+24) + print("id:", id, " x:", x, " y:", y, " z:", z) + self.set_player_position(Vector3(x, y, z)) + account_confirmed = true + self.get_node("CharacterBody3D").set_enable_event(true) + else: # KO + bad_acocunt() + elif data[0] == 3: # Get position + if id == 0: + return + var nb = data[1] + var pos = 2 + for i in nb: + var mid = data.decode_u64(pos) + var mx = data.decode_double(pos+8) + var my = data.decode_double(pos+16) + var mz = data.decode_double(pos+24) + pos += 32 + if mid == id: + print("Me id:", mid, " x:", mx, " y:", my, " z:", mz) + continue + print("-- id:", mid, " x:", mx, " y:", my, " z:", mz) + var child = $Players.find_child(str(mid), false, false) + if child == null: + print("Not found") + if maxplayer > 3: + continue + var scene = preload("res://scenes/player.tscn") + var instance = scene.instantiate() + #var current_scene = scene.instance() + #var GrabbedInstance = PLAYER.instance() + instance.set_name(str(mid)) + $Players.add_child(instance) + #$Players.add_child(scene) + maxplayer += 1 + for child3 in $Players.get_children(): + print(" -> ", child3.get_name()) + var child2 = $Players.find_child(str(mid), false, false) + child2.set_global_position(Vector3(mx, my, mz)) + + else: + child.set_global_position(Vector3(mx, my, mz)) + print("Found:", $Players.get_child_count()) + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(_delta): + #print("state:", dataEnet.get_state()) + get_player_position() + if dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTED: + var event = enet.service() + if event[0] == ENetConnection.EVENT_RECEIVE: + #print("get: ", dataEnet.get_packet()) + get_event_received() + if player_name != "" and not account_confirmed: + send_account() + elif dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTING: + var event = enet.service() + if event[0] == ENetConnection.EVENT_RECEIVE: + pass + elif dataEnet.get_state() == ENetPacketPeer.STATE_DISCONNECTED: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_ACKNOWLEDGING_CONNECT: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTION_PENDING: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTION_SUCCEEDED: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_DISCONNECT_LATER: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_DISCONNECTING: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_ACKNOWLEDGING_DISCONNECT: + var _event = enet.service() + elif dataEnet.get_state() == ENetPacketPeer.STATE_ZOMBIE: + var _event = enet.service() + else: + var _event = enet.service() + + +func _process_ter(_delta): + var res = enet.service(1) + #print(res) + if res[0] == ENetConnection.EVENT_RECEIVE: + #print("EVENT_RECEIVE") + print(dataEnet.get_packet()) + #if res[1] + var data:PackedByteArray = PackedByteArray() + data.append(len(player_name)) + data.append(123) + errorEnet = dataEnet.send(1, data, 1) + if errorEnet != OK: + print("ERROR ENET: ", errorEnet) + return + + +func _process_bis(_delta): + if not dataEnet.is_active(): + create_server_enet() + elif dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTING: + var res = enet.service(1) + print(res) + elif dataEnet.get_state() == ENetPacketPeer.STATE_CONNECTED: + var res = enet.service(1) + print(res) + var data:PackedByteArray = PackedByteArray() + data.append(len(player_name)) + data.append(123) + errorEnet = dataEnet.send(1, data, 1) + if errorEnet != OK: + print("ERROR ENET: ", errorEnet) + return + #print("<> get_state: ", dataEnet.get_state()) + else: + print("get_state: ", dataEnet.get_state()) + return + + if not connected: + if player_name != "": + create_server_enet() + return + var res = enet.service(1) + print(res) + return + if not connected: + if player_name != "": + create_server_enet() + else: + var data:PackedByteArray = PackedByteArray() + data.append(len(player_name)) + data.append(123) + #print(len(data)) + print("active:", dataEnet.is_active()) + print("state:", dataEnet.get_state()) + print("address:", dataEnet.get_remote_address()) + print("port:", dataEnet.get_remote_port()) + errorEnet = dataEnet.send(1, data, 1) + if errorEnet != OK: + print("ERROR ENET: ", errorEnet) + return + #enet.socket_send(ADDR, PORT, data) + + +func connect_enet(_name:String): + player_name = _name + print("My name:" + player_name) + diff --git a/client/scenes/main.gdshader b/client/scenes/main.gdshader new file mode 100644 index 0000000..fc05ebc --- /dev/null +++ b/client/scenes/main.gdshader @@ -0,0 +1,21 @@ +shader_type spatial; + +void fragment() { + bool v = false; + bool w = false; + float b = 0.0; + float g = 0.2; + float r = 0.0; + if ( mod(UV.x,0.005) > 0.0025 ) { + v = true; + }; + if ( mod(UV.y,0.005) > 0.0025 ) { + w = true; + }; + if ( ( v && ! w ) || ( !v && w ) ) { + b = 0.0; + g = 0.0; + r = 0.2; + } + ALBEDO = vec3(r, g, b); +} \ No newline at end of file diff --git a/client/scenes/main.tscn b/client/scenes/main.tscn new file mode 100644 index 0000000..65db350 --- /dev/null +++ b/client/scenes/main.tscn @@ -0,0 +1,89 @@ +[gd_scene load_steps=11 format=3 uid="uid://bemavktwweaog"] + +[ext_resource type="Shader" path="res://scenes/main.gdshader" id="1_caff6"] +[ext_resource type="PackedScene" uid="uid://cg5uqqd4ibdem" path="res://scenes/player.tscn" id="1_nc7b3"] +[ext_resource type="Script" path="res://scenes/main.gd" id="1_ts8of"] +[ext_resource type="Script" path="res://scenes/Window.gd" id="3_uwnj8"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_5dcgs"] +size = Vector3(1000, 1, 1000) + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_gypq5"] +render_priority = 0 +shader = ExtResource("1_caff6") + +[sub_resource type="BoxMesh" id="BoxMesh_fm2j6"] +material = SubResource("ShaderMaterial_gypq5") +size = Vector3(1000, 1, 1000) + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0qg6h"] + +[sub_resource type="Sky" id="Sky_i4xvw"] +sky_material = SubResource("ProceduralSkyMaterial_0qg6h") + +[sub_resource type="Environment" id="Environment_12j7q"] +background_mode = 2 +background_color = Color(0.803922, 0.776471, 0.733333, 1) +sky = SubResource("Sky_i4xvw") +ambient_light_color = Color(0.968627, 0.933333, 0.596078, 1) +reflected_light_source = 2 + +[node name="main" type="Node3D"] +script = ExtResource("1_ts8of") + +[node name="ground" type="StaticBody3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="ground"] +shape = SubResource("BoxShape3D_5dcgs") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="ground"] +mesh = SubResource("BoxMesh_fm2j6") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(-0.866025, 0, -0.5, -0.25, 0.866025, 0.433013, 0.433013, 0.5, -0.75, 0, 50, 0) +shadow_enabled = true +shadow_opacity = 0.5 + +[node name="CharacterBody3D" parent="." instance=ExtResource("1_nc7b3")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, 0) + +[node name="Players" type="Node3D" parent="."] + +[node name="WorldEnvironment" type="WorldEnvironment" parent="."] +environment = SubResource("Environment_12j7q") + +[node name="Window" type="Window" parent="."] +title = "Connexion" +initial_position = 1 +size = Vector2i(300, 100) +script = ExtResource("3_uwnj8") + +[node name="VBoxContainer" type="VBoxContainer" parent="Window"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="Window/VBoxContainer"] +layout_mode = 2 +text = "Login" +horizontal_alignment = 1 + +[node name="TextEdit" type="LineEdit" parent="Window/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 +placeholder_text = "Account" + +[node name="Button" type="Button" parent="Window/VBoxContainer"] +layout_mode = 2 +disabled = true +text = "OK" + +[connection signal="focus_entered" from="Window" to="Window" method="_on_focus_entered"] +[connection signal="focus_exited" from="Window" to="Window" method="_on_focus_exited"] +[connection signal="mouse_entered" from="Window" to="Window" method="_on_mouse_entered"] +[connection signal="mouse_exited" from="Window" to="Window" method="_on_mouse_exited"] +[connection signal="text_changed" from="Window/VBoxContainer/TextEdit" to="Window" method="_on_text_edit_text_changed"] +[connection signal="pressed" from="Window/VBoxContainer/Button" to="Window" method="_on_button_pressed"] diff --git a/client/scenes/player.gd b/client/scenes/player.gd new file mode 100644 index 0000000..e936823 --- /dev/null +++ b/client/scenes/player.gd @@ -0,0 +1,67 @@ +extends CharacterBody3D + + +const SPEED = 30.0 +const JUMP_VELOCITY = 14.5 + +# Get the gravity from the project settings to be synced with RigidBody nodes. +var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +@export var event_disabled:bool = true + +# How fast the player moves in meters per second. +@export var speed = 14 +# The downward acceleration when in the air, in meters per second squared. +@export var fall_acceleration = 75 + +var target_velocity = Vector3.ZERO + +var direction = Vector3.FORWARD +var h_sensitivity:float = 0.1 +var v_sensitivity:float = 0.1 +var camrot_h:float = 0.0 +var camrot_v:float = 0.0 +var h_acceleration:float = 10.0 +var v_acceleration:float = 10.0 +var input_view_camera_move_player_follow_mouse:bool = false + +func _input(event): + if event_disabled: + return + if event is InputEventMouseButton: + if Input.is_action_pressed("ui_rotate_player"): + input_view_camera_move_player_follow_mouse = true + else: + input_view_camera_move_player_follow_mouse = false + + if event is InputEventMouseMotion and input_view_camera_move_player_follow_mouse: + camrot_h += -event.relative.x * h_sensitivity + camrot_v += -event.relative.y * v_sensitivity + +func _physics_process(delta:float): + if event_disabled: + return + var h_rot:float = $h.global_transform.basis.get_euler().y + # Add the gravity. + if not is_on_floor(): + velocity.y -= gravity * delta + + # Handle Jump. + if Input.is_action_just_pressed("ui_accept") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + # Get the input direction and handle the movement/deceleration. + # As good practice, you should replace UI actions with custom gameplay actions. + var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down").rotated(-h_rot) + direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + if direction: + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + else: + velocity.x = move_toward(velocity.x, 0, SPEED) + velocity.z = move_toward(velocity.z, 0, SPEED) + $h.rotation_degrees.y = lerp($h.rotation_degrees.y, camrot_h, delta * h_acceleration) + $h/v.rotation_degrees.x = lerp($h/v.rotation_degrees.x, camrot_v, delta * v_acceleration) + move_and_slide() + +func set_enable_event(state:bool): + event_disabled = ! state diff --git a/client/scenes/player.tscn b/client/scenes/player.tscn new file mode 100644 index 0000000..1d07649 --- /dev/null +++ b/client/scenes/player.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://cg5uqqd4ibdem"] + +[ext_resource type="PackedScene" uid="uid://bng6cjt7kq1hv" path="res://assets/player.glb" id="1_bpxp1"] +[ext_resource type="Script" path="res://scenes/player.gd" id="1_br7n0"] + +[sub_resource type="SphereShape3D" id="SphereShape3D_cjbav"] + +[node name="CharacterBody3D" type="CharacterBody3D"] +script = ExtResource("1_br7n0") + +[node name="Pivot" type="Node3D" parent="."] + +[node name="player" parent="Pivot" instance=ExtResource("1_bpxp1")] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 1, 0) +shape = SubResource("SphereShape3D_cjbav") + +[node name="h" type="Node3D" parent="."] + +[node name="v" type="Node3D" parent="h"] + +[node name="Camera3D" type="Camera3D" parent="h/v"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 5) diff --git a/precheck.gd b/precheck.gd new file mode 100644 index 0000000..f720f16 --- /dev/null +++ b/precheck.gd @@ -0,0 +1,37 @@ +extends MainLoop +#extends Node + +# print("Example") + + +# Called when the node enters the scene tree for the first time. +#func _ready(): +# print("Example _ready") +# # print( get_user_data_dir() ) +# # print(Performance.get_monitor(Performance.TIME_FPS)) +# pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# print("Example _process") +# pass +func _process(delta): + return true + +func _init(): + var info:String = "" + #info = get_base_script() + var processName:String = OS.get_processor_name() + var modelName:String = OS.get_model_name() + var osName:String = OS.get_name() + var version:String = OS.get_version() + var detailCardGraphics: PackedStringArray = OS.get_video_adapter_driver_info() + var idHardware:String = OS.get_unique_id() + var idGodot:String = str(Engine.get_version_info()) + #for i in range(OS.get_screen_cound()): + # print(i) + var data = " - ".join(detailCardGraphics) + print( processName + "!" + modelName + "!" + osName + "!" + version + "!" + data + "!" + idHardware + "!" + idGodot) + + diff --git a/start-bazar-client.sh b/start-bazar-client.sh new file mode 100755 index 0000000..7b6de37 --- /dev/null +++ b/start-bazar-client.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +declare DEBUG=0 +declare HELP=0 +declare EDITOR=0 +declare FORCE=0 +declare IMPORT=0 +declare ERASEIMPORT=0 +declare WORKDIR="$(dirname $(readlink -f $0))" +declare GODOT_SRC="https://downloads.tuxfamily.org/godotengine/4.1.2/Godot_v4.1.2-stable_linux.x86_64.zip" +declare OUTZIP="$WORKDIR/$(basename $GODOT_SRC)" +declare CLIENTDIR="$WORKDIR/client" +declare OPTION="" +declare NEWPRG=0 +declare DISABLEAUTODETECTCARD=0 + +function msg_debug() +{ + if [ $DEBUG -ne 0 ] + then + echo "### DEBUG : $*" >&2 + fi +} + +function msg_info() +{ + echo "--- INFO : $*" >&2 +} + +function msg_error() +{ + echo "*** ERROR : $*" >&2 +} + +function download() +{ + local package="$1" + local out="$2" + if [[ $FORCE -eq 0 && -f $2 ]] + then + return 0 + fi + which curl 1>/dev/null 2>/dev/null + if [ $? -eq 0 ] + then + curl -o $out $package + if [ $? -eq 0 ] + then + msg_info "Package GODOT downloaded" + return 0 + fi + fi + which wget 1>/dev/null 2>/dev/null + if [ $? -eq 0 ] + then + wget $package -O $out + if [ $? -eq 0 ] + then + msg_info "Package GODOT downloaded" + return 0 + fi + fi + msg_error "Impossible to download" + exit 2 +} + +function extract() +{ + local compressed_file="$1" + which unzip 1>/dev/null 2>/dev/null + if [ $? -eq 0 ] + then + fileout=$(unzip -Z1 $compressed_file) + if [[ $FORCE -eq 0 && -f $fileout ]] + then + echo $fileout + return 0 + fi + unzip -u $compressed_file -d $WORKDIR 1>&2 + if [ $? -eq 0 ] + then + msg_info "Uncompressed GODOT" + echo $fileout + NEWPRG=1 + return 0 + fi + fi + msg_error "Impossible to extract" + exit 2 +} + + +while getopts hdeo:s:fix flag +do + case "${flag}" in + h) HELP=1;; + d) DEBUG=1;; + e) EDITOR=1;; + o) OUTZIP=${OPTARG};; + s) GODOT_SRC=${OPTARG};; + f) FORCE=1;; + i) IMPORT=1;; + x) ERASEIMPORT=1;; + y) DISABLEAUTODETECTCARD=1;; + *) HELP=1;; + esac +done + +if [[ $HELP -ne 0 ]] +then + cat << EOF +$(basename $0) [Option] : Donwload Launch Godot + Option: + -h : Show help + -d : Show debug message + -e : Start Godot in editor mode + -f : force download & uncompress + -i : force import data + -x : erase import data + -y : Disable auto detect host (OS/CPU/GPU) + -o : target godot file (downloaded) + -s : Url to download a specific godot version +EOF + exit 1 +fi + +msg_info "Start" +msg_debug "WORKDIR:$WORKDIR OUTZIP:$OUTZIP GODOT_SRC:$GODOT_SRC" +download "$GODOT_SRC" "$OUTZIP" +EXE=$(extract "$OUTZIP") +msg_info "Prg:$EXE" + +if [ $NEWPRG -ne 0 ] +then + echo "--- New program detected" + ERASEIMPORT=1 + IMPORT=1 +elif [ $DISABLEAUTODETECTCARD -eq 0 ] +then + echo "--- Check host" + $WORKDIR/$EXE --script precheck.gd > $WORKDIR/.current_version.tmp + if [ -f $WORKDIR/.current_version ] + then + diff $WORKDIR/.current_version.tmp $WORKDIR/.current_version >/dev/null + if [ $? -ne 0 ] + then + ERASEIMPORT=1 + IMPORT=1 + mv $WORKDIR/.current_version.tmp $WORKDIR/.current_version + else + rm $WORKDIR/.current_version.tmp + fi + else + ERASEIMPORT=1 + IMPORT=1 + mv $WORKDIR/.current_version.tmp $WORKDIR/.current_version + fi +fi + +if [ $ERASEIMPORT -ne 0 ] +then + echo "--- Erase imported data" + rm -f $WORKDIR/.godot/imported/* +fi + +if [[ ($IMPORT -ne 0) || (! -d $WORKDIR/.godot) ]] +then + echo "--- Launch import (please wait)" + $WORKDIR/$EXE --editor --quit + echo "--- Import finished" +fi + +if [ $EDITOR -ne 0 ] +then + OPTION="$OPTION -e" +fi + +cd $CLIENTDIR +$WORKDIR/$EXE $OPTION + +msg_info "End"