Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3ea967ae59 | |||
| eb22e7673f | |||
| a604032b79 | |||
| f10eebd332 | |||
| f9603e0a5a | |||
| ed41775543 | |||
| 809da74969 | |||
| 42ef398544 | |||
| 1db73736c4 | |||
| c3e906f33c | |||
| fa6cf57e0c | |||
| df06be7542 | |||
| 2268cb995d | |||
| 01f93fbbad | |||
| 293c19170d | |||
| 65c0124861 | |||
| 2d9933b627 | |||
| 7ba087f6e1 | |||
| 97c15d5b1b | |||
| 3b182431ae | |||
| 76676f53f5 | |||
| d90c0e5ee7 | |||
| bb7f8ead08 | |||
| bb3b75929a | |||
| c57c724f0a | |||
| 26fe3ae790 | |||
| f41c047f26 | |||
| 3568f927fc | |||
| 3d53e70e7b | |||
| 6a02e40f01 | |||
| 030fa8bfaf | |||
| e1c073adcb | |||
| 904e2b2ccd | |||
| 58c35aa9c3 | |||
| 2fd79f4d5f | |||
| 9aa67cf490 | |||
| 25a3b67cd2 | |||
| c1719d8dd5 | |||
| 2867918c92 | |||
| 64ba702ac3 | |||
| 8c5cf83803 | |||
| 0652e0d23b | |||
| 669eed3a1b | |||
| 31e94e6408 | |||
| c5a7af2869 | |||
| c3a4a70280 | |||
| be821a2645 | |||
| 25196cc796 | |||
| facc984c36 | |||
| 1d4632a66c | |||
| 07cfb07cc6 | |||
| fff9a3eb11 | |||
| 963b70f674 | |||
| 3a4c76cd67 | |||
| 0fcb151f87 | |||
| 340a176e55 | |||
| a762c2d8ad | |||
| cac56adbdb | |||
| 5e9627e453 | |||
| 819c678201 | |||
| 8a52846c2d |
27
Dockerfile
Normal file
27
Dockerfile
Normal file
@ -0,0 +1,27 @@
|
||||
FROM fedora:latest
|
||||
|
||||
ARG GODOT_VERSION="4.3"
|
||||
ARG SERVER_PORT=10567
|
||||
ENV GODOT_FILE_NAME="Godot_v${GODOT_VERSION}-stable_linux.x86_64"
|
||||
|
||||
ENV GODOT_GAME_NAME="cadastery-server"
|
||||
|
||||
RUN dnf update -y
|
||||
RUN dnf install -y wget unzip wayland-devel fontconfig
|
||||
|
||||
ADD https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}-stable//${GODOT_FILE_NAME}.zip ./
|
||||
RUN mkdir -p ~/.cache \
|
||||
&& mkdir -p ~/.config/godot \
|
||||
&& unzip ${GODOT_FILE_NAME}.zip \
|
||||
&& mv ${GODOT_FILE_NAME} /usr/local/bin/godot \
|
||||
&& rm -f ${GODOT_FILE_NAME}.zip
|
||||
|
||||
WORKDIR /godotapp
|
||||
COPY . .
|
||||
|
||||
RUN godot --headless --export-pack "server" /godotapp/${GODOT_GAME_NAME}.pck
|
||||
|
||||
EXPOSE ${SERVER_PORT}/udp
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
ENTRYPOINT godot --main-pack ${GODOT_GAME_NAME}.pck
|
||||
@ -1 +1,3 @@
|
||||
Source code for Cadastery.
|
||||
|
||||
If you want to clone the repo, make sure you have [Git LFS](https://git-lfs.com/) installed.
|
||||
|
||||
14
docker-compose.yaml
Normal file
14
docker-compose.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
services:
|
||||
cadastery:
|
||||
build: .
|
||||
ports:
|
||||
- '10567:10567'
|
||||
- '10567:10567/udp'
|
||||
volumes:
|
||||
- cadastery-server-userdata:/root/.local/share/Cadastery
|
||||
tty: true
|
||||
container_name: cadastery-server
|
||||
|
||||
volumes:
|
||||
cadastery-server-userdata:
|
||||
driver: local
|
||||
@ -11,7 +11,7 @@ config_version=5
|
||||
[application]
|
||||
|
||||
config/name="cadastery"
|
||||
config/version="0.0.1"
|
||||
config/version="0.0.4"
|
||||
run/main_scene="res://scenes/title.tscn"
|
||||
config/use_custom_user_dir=true
|
||||
config/custom_user_dir_name="Cadastery"
|
||||
@ -28,6 +28,7 @@ Networker="*res://scripts/globals/networker.gd"
|
||||
Cursorer="*res://scripts/globals/cursorer.gd"
|
||||
Referencer="*res://scripts/globals/referencer.gd"
|
||||
Inputer="*res://scripts/globals/inputer.gd"
|
||||
Consoler="*res://scripts/globals/consoler.gd"
|
||||
|
||||
[debug]
|
||||
|
||||
@ -40,7 +41,6 @@ gdscript/warnings/integer_division=0
|
||||
|
||||
window/size/viewport_width=1920
|
||||
window/size/viewport_height=1080
|
||||
window/size/always_on_top=true
|
||||
window/size/window_width_override=1280
|
||||
window/size/window_height_override=720
|
||||
window/stretch/mode="canvas_items"
|
||||
@ -49,7 +49,6 @@ window/stretch/aspect="expand"
|
||||
[editor]
|
||||
|
||||
movie_writer/movie_file="E:/Projects/Games/cadastery/build/records/movie.avi"
|
||||
movie_writer/fps=120
|
||||
|
||||
[filesystem]
|
||||
|
||||
@ -58,6 +57,20 @@ import/blender/enabled=false
|
||||
|
||||
[input]
|
||||
|
||||
ui_accept={
|
||||
"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":4194309,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, 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":4194310,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, 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":32,"physical_keycode":0,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":0,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
ui_cancel={
|
||||
"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":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
move_forward={
|
||||
"deadzone": 0.5,
|
||||
"events": [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":119,"location":0,"echo":false,"script":null)
|
||||
@ -130,6 +143,28 @@ toggle_debug={
|
||||
"events": [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":96,"key_label":0,"unicode":96,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
crouch={
|
||||
"deadzone": 0.5,
|
||||
"events": [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":4194326,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":1,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
run={
|
||||
"deadzone": 0.5,
|
||||
"events": [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":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":7,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
look_slow={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":8,"pressure":0.0,"pressed":true,"script":null)
|
||||
]
|
||||
}
|
||||
chat={
|
||||
"deadzone": 0.5,
|
||||
"events": [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":84,"key_label":0,"unicode":116,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
@ -144,4 +179,3 @@ common/physics_interpolation=true
|
||||
[rendering]
|
||||
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
anti_aliasing/quality/msaa_3d=2
|
||||
|
||||
@ -4,5 +4,7 @@
|
||||
|
||||
[resource]
|
||||
albedo_texture = ExtResource("1_f5hmr")
|
||||
metallic_specular = 0.0
|
||||
roughness = 0.0
|
||||
uv1_triplanar = true
|
||||
texture_filter = 0
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://b7fc42grqckl0"]
|
||||
[gd_scene load_steps=5 format=3 uid="uid://b7fc42grqckl0"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/main.gd" id="1_80y7k"]
|
||||
[ext_resource type="PackedScene" uid="uid://b3t5vrqb1eym2" path="res://scenes/ui/chat.tscn" id="3_8t1rc"]
|
||||
[ext_resource type="Material" uid="uid://00ldcihmubqo" path="res://resources/materials/test_triplanar.tres" id="3_vk6ds"]
|
||||
|
||||
[sub_resource type="Environment" id="Environment_wyusq"]
|
||||
@ -18,12 +19,18 @@ use_collision = true
|
||||
|
||||
[node name="CSGBox3D" type="CSGBox3D" parent="Geometry/CSGCombiner3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -50, 0)
|
||||
size = Vector3(10, 100, 10)
|
||||
size = Vector3(40, 100, 10)
|
||||
|
||||
[node name="Lights" type="Node" parent="."]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="Lights"]
|
||||
transform = Transform3D(0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, -0.75, 0.433013, 0, 0, 0)
|
||||
shadow_enabled = true
|
||||
shadow_blur = 2.0
|
||||
|
||||
[node name="UI" type="Node" parent="."]
|
||||
|
||||
[node name="Chat" parent="UI" instance=ExtResource("3_8t1rc")]
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_wyusq")
|
||||
|
||||
@ -19,6 +19,9 @@ properties/1/replication_mode = 1
|
||||
properties/2/path = NodePath("Camera3D:rotation")
|
||||
properties/2/spawn = true
|
||||
properties/2/replication_mode = 1
|
||||
properties/3/path = NodePath("Camera3D:position")
|
||||
properties/3/spawn = true
|
||||
properties/3/replication_mode = 1
|
||||
|
||||
[node name="Player" type="CharacterBody3D"]
|
||||
collision_layer = 2
|
||||
@ -41,7 +44,6 @@ mesh = SubResource("BoxMesh_v4nai")
|
||||
|
||||
[node name="NameLabel" type="Label3D" parent="."]
|
||||
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 2.15, 0)
|
||||
text = "name"
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||
replication_config = SubResource("SceneReplicationConfig_j6f6x")
|
||||
|
||||
@ -1,33 +1,28 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bnlglddkrxuf0"]
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bnlglddkrxuf0"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/play_menu.gd" id="1_gunvo"]
|
||||
[ext_resource type="Script" path="res://scripts/title.gd" id="1_l5ce6"]
|
||||
|
||||
[node name="Title" type="Node"]
|
||||
script = ExtResource("1_l5ce6")
|
||||
|
||||
[node name="Menu" type="Control" parent="."]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
[node name="PlayMenu" type="CanvasLayer" parent="."]
|
||||
script = ExtResource("1_gunvo")
|
||||
|
||||
[node name="PlayMenu" type="Panel" parent="Menu"]
|
||||
layout_mode = 1
|
||||
[node name="Panel" type="Panel" parent="PlayMenu"]
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_left = -216.0
|
||||
offset_left = -321.5
|
||||
offset_top = -84.0
|
||||
offset_right = 216.0
|
||||
offset_right = 321.5
|
||||
offset_bottom = 84.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_gunvo")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Menu/PlayMenu"]
|
||||
[node name="MarginContainer" type="MarginContainer" parent="PlayMenu/Panel"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
@ -39,53 +34,55 @@ theme_override_constants/margin_top = 20
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="Menu/PlayMenu/MarginContainer"]
|
||||
[node name="GridContainer" type="GridContainer" parent="PlayMenu/Panel/MarginContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 10
|
||||
theme_override_constants/v_separation = 20
|
||||
columns = 3
|
||||
|
||||
[node name="NameLabel" type="Label" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="NameLabel" type="Label" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "Name:"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="NameEdit" type="LineEdit" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="NameEdit" type="LineEdit" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
focus_neighbor_right = NodePath("../HostButton")
|
||||
focus_neighbor_bottom = NodePath("../IpEdit")
|
||||
focus_neighbor_bottom = NodePath("../AddressEdit")
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "ass"
|
||||
max_length = 16
|
||||
|
||||
[node name="HostButton" type="Button" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="HostButton" type="Button" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
focus_neighbor_left = NodePath("../NameEdit")
|
||||
focus_neighbor_bottom = NodePath("../JoinButton")
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "Host"
|
||||
|
||||
[node name="IpLabel" type="Label" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="AddressLabel" type="Label" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "IP:"
|
||||
text = "Address:"
|
||||
horizontal_alignment = 2
|
||||
|
||||
[node name="IpEdit" type="LineEdit" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="AddressEdit" type="LineEdit" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
focus_neighbor_top = NodePath("../NameEdit")
|
||||
focus_neighbor_right = NodePath("../JoinButton")
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "127.0.0.1"
|
||||
|
||||
[node name="JoinButton" type="Button" parent="Menu/PlayMenu/MarginContainer/GridContainer"]
|
||||
[node name="JoinButton" type="Button" parent="PlayMenu/Panel/MarginContainer/GridContainer"]
|
||||
layout_mode = 2
|
||||
focus_neighbor_left = NodePath("../IpEdit")
|
||||
focus_neighbor_left = NodePath("../AddressEdit")
|
||||
focus_neighbor_top = NodePath("../HostButton")
|
||||
theme_override_font_sizes/font_size = 26
|
||||
text = "Join"
|
||||
|
||||
[node name="ErrorLabel" type="Label" parent="Menu/PlayMenu"]
|
||||
[node name="ErrorLabel" type="Label" parent="PlayMenu/Panel"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
|
||||
71
scenes/ui/chat.tscn
Normal file
71
scenes/ui/chat.tscn
Normal file
@ -0,0 +1,71 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://b3t5vrqb1eym2"]
|
||||
|
||||
[ext_resource type="Script" path="res://scripts/ui/chat.gd" id="1_ulx3h"]
|
||||
|
||||
[node name="Chat" type="CanvasLayer"]
|
||||
script = ExtResource("1_ulx3h")
|
||||
|
||||
[node name="MsgMargin" type="MarginContainer" parent="."]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_bottom = -70.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
theme_override_constants/margin_left = 50
|
||||
theme_override_constants/margin_right = 50
|
||||
|
||||
[node name="MsgVBox" type="VBoxContainer" parent="MsgMargin"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
theme_override_constants/separation = 0
|
||||
|
||||
[node name="MsgScroll" type="ScrollContainer" parent="MsgMargin/MsgVBox"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
follow_focus = true
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="MsgMargin" type="MarginContainer" parent="MsgMargin/MsgVBox/MsgScroll"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 30
|
||||
|
||||
[node name="MsgContainer" type="VBoxContainer" parent="MsgMargin/MsgVBox/MsgScroll/MsgMargin"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
alignment = 2
|
||||
|
||||
[node name="EditMargin" type="MarginContainer" parent="."]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_top = 1010.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 2
|
||||
theme_override_constants/margin_left = 50
|
||||
theme_override_constants/margin_right = 50
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="EditVBox" type="VBoxContainer" parent="EditMargin"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="MessageEdit" type="LineEdit" parent="EditMargin/EditVBox"]
|
||||
layout_mode = 2
|
||||
theme_override_font_sizes/font_size = 26
|
||||
max_length = 256
|
||||
context_menu_enabled = false
|
||||
caret_blink = true
|
||||
26
scenes/ui/chat_message.tscn
Normal file
26
scenes/ui/chat_message.tscn
Normal file
@ -0,0 +1,26 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bjrbngxkvhn7f"]
|
||||
|
||||
[sub_resource type="SystemFont" id="SystemFont_mq8v6"]
|
||||
font_names = PackedStringArray("Monospace")
|
||||
font_weight = 600
|
||||
subpixel_positioning = 0
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel"]
|
||||
clip_contents = false
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 0.501961)
|
||||
theme_override_constants/outline_size = 20
|
||||
theme_override_fonts/mono_font = SubResource("SystemFont_mq8v6")
|
||||
theme_override_font_sizes/bold_italics_font_size = 26
|
||||
theme_override_font_sizes/italics_font_size = 26
|
||||
theme_override_font_sizes/mono_font_size = 26
|
||||
theme_override_font_sizes/normal_font_size = 26
|
||||
theme_override_font_sizes/bold_font_size = 26
|
||||
bbcode_enabled = true
|
||||
text = "[b]name:[/b] lorem ipsum"
|
||||
fit_content = true
|
||||
@ -50,7 +50,7 @@ func _process(_delta: float) -> void:
|
||||
_control.queue_redraw()
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("toggle_debug"):
|
||||
mode = wrapi(mode + 1, 0, Mode.size()) as Mode
|
||||
_update_visibility()
|
||||
@ -112,7 +112,7 @@ func _update_visibility() -> void:
|
||||
|
||||
|
||||
func _unproject(pos: Vector3) -> Vector2:
|
||||
return Referencer.main_camera.unproject_position(pos)
|
||||
return Referencer.camera.unproject_position(pos)
|
||||
|
||||
|
||||
func _update_controls_label() -> void:
|
||||
@ -196,8 +196,8 @@ func _append_event(key: String, frame: int, args: Array[Variant]) -> void:
|
||||
|
||||
func _draw_vector(from: Vector3, to: Vector3, color: Color) -> void:
|
||||
if (
|
||||
not Referencer.main_camera.is_position_in_frustum(from)
|
||||
and not Referencer.main_camera.is_position_in_frustum(to)
|
||||
not Referencer.camera.is_position_in_frustum(from)
|
||||
and not Referencer.camera.is_position_in_frustum(to)
|
||||
):
|
||||
return
|
||||
|
||||
@ -223,7 +223,7 @@ func _draw_triangle(
|
||||
|
||||
|
||||
func _draw_marker(pos: Vector3, radius: float, color: Color) -> void:
|
||||
if not Referencer.main_camera.is_position_in_frustum(pos):
|
||||
if not Referencer.camera.is_position_in_frustum(pos):
|
||||
return
|
||||
|
||||
var x_start := _unproject(pos + (Vector3.LEFT * radius))
|
||||
@ -240,7 +240,7 @@ func _draw_marker(pos: Vector3, radius: float, color: Color) -> void:
|
||||
|
||||
|
||||
func _draw_circle(pos: Vector3, color: Color) -> void:
|
||||
if not Referencer.main_camera.is_position_in_frustum(pos):
|
||||
if not Referencer.camera.is_position_in_frustum(pos):
|
||||
return
|
||||
|
||||
var point := _unproject(pos)
|
||||
@ -284,7 +284,7 @@ func _on_control_draw() -> void:
|
||||
|
||||
_set_label_texts()
|
||||
|
||||
if !Referencer.main_camera:
|
||||
if !Referencer.camera:
|
||||
return
|
||||
|
||||
for v: Dictionary in _vectors_to_draw.values():
|
||||
|
||||
35
scripts/globals/consoler.gd
Normal file
35
scripts/globals/consoler.gd
Normal file
@ -0,0 +1,35 @@
|
||||
extends Node
|
||||
|
||||
signal message_sent(message: String)
|
||||
|
||||
const SERVER_CONSOLE_INPUT_PATH := "user://server_console_input"
|
||||
const READING_INTERVAL: float = 10
|
||||
|
||||
var reading_timer: float = 0
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not Networker.is_dedicated or Referencer.chat == null:
|
||||
return
|
||||
|
||||
reading_timer -= delta
|
||||
|
||||
if reading_timer > 0:
|
||||
return
|
||||
|
||||
reading_timer = READING_INTERVAL
|
||||
|
||||
var file := FileAccess.open(SERVER_CONSOLE_INPUT_PATH, FileAccess.READ)
|
||||
if not file:
|
||||
return
|
||||
|
||||
var text := file.get_as_text()
|
||||
if not text:
|
||||
return
|
||||
|
||||
message_sent.emit(text)
|
||||
|
||||
file = FileAccess.open(SERVER_CONSOLE_INPUT_PATH, FileAccess.WRITE)
|
||||
if not file:
|
||||
return
|
||||
file.store_string("")
|
||||
@ -2,10 +2,12 @@ extends Node
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
Networker.main_loaded.connect(_on_networker_main_loaded)
|
||||
Referencer.main_loaded.connect(_on_referencer_main_loaded)
|
||||
Referencer.menu_opened.connect(_on_referencer_menu_opened)
|
||||
Referencer.menu_closed.connect(_on_referencer_menu_closed)
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("toggle_cursor_capture"):
|
||||
if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
@ -13,5 +15,13 @@ func _input(event: InputEvent) -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
|
||||
func _on_networker_main_loaded() -> void:
|
||||
func _on_referencer_main_loaded() -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
|
||||
func _on_referencer_menu_opened(_menu: Menu) -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
|
||||
func _on_referencer_menu_closed(_menu: Menu) -> void:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
|
||||
|
||||
@ -10,14 +10,15 @@ const RIGHT_TRIGGER_SPRITE_INDEX: int = 21
|
||||
const LEFT_STICK_SPRITE_INDEX: int = 23
|
||||
const RIGHT_STICK_SPRITE_INDEX: int = 24
|
||||
|
||||
@export var prompt_grid_size: int = 5
|
||||
@export var prompt_icon_size: int = 60
|
||||
|
||||
@export var mode: Mode = Mode.KB_MOUSE
|
||||
@export var controller: ControllerType = ControllerType.XBOX:
|
||||
|
||||
@export var _controller: ControllerType = ControllerType.XBOX:
|
||||
set(value):
|
||||
_set_current_prompts(value)
|
||||
controller = value
|
||||
_controller = value
|
||||
|
||||
@export var _prompt_grid_size: int = 5
|
||||
@export var _prompt_icon_size: int = 60
|
||||
|
||||
var _prompts_xbox := preload("res://assets/textures/ui/prompts_xbox.png")
|
||||
var _prompts_sony := preload("res://assets/textures/ui/prompts_sony.png")
|
||||
@ -43,7 +44,6 @@ func _input(event: InputEvent) -> void:
|
||||
var event_mode := _get_event_mode(event)
|
||||
if mode == Mode.KB_MOUSE and event_mode == Mode.CONTROLLER:
|
||||
mode = Mode.CONTROLLER
|
||||
|
||||
mode_changed.emit(mode)
|
||||
|
||||
if mode == Mode.CONTROLLER and event_mode == Mode.KB_MOUSE:
|
||||
@ -54,6 +54,10 @@ func _input(event: InputEvent) -> void:
|
||||
Debugger.text("input", _get_event_prompt_current_mode(event))
|
||||
|
||||
|
||||
func can_control_player() -> bool:
|
||||
return Referencer.menu == null
|
||||
|
||||
|
||||
func get_action_prompt(action: StringName) -> String:
|
||||
var events := InputMap.action_get_events(action)
|
||||
var bbcode: PackedStringArray = []
|
||||
@ -128,17 +132,17 @@ func _get_prompt_sprite(index: int) -> String:
|
||||
region.position.y,
|
||||
region.size.x,
|
||||
region.size.y,
|
||||
prompt_icon_size,
|
||||
prompt_icon_size,
|
||||
_prompt_icon_size,
|
||||
_prompt_icon_size,
|
||||
_current_prompts.resource_path
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
func _get_prompt_sprite_region(index: int) -> Rect2i:
|
||||
var corner_x: int = index % prompt_grid_size
|
||||
var corner_y: int = index / prompt_grid_size
|
||||
var sprite_size: int = _current_prompts.get_width() / prompt_grid_size
|
||||
var corner_x: int = index % _prompt_grid_size
|
||||
var corner_y: int = index / _prompt_grid_size
|
||||
var sprite_size: int = _current_prompts.get_width() / _prompt_grid_size
|
||||
return Rect2i(
|
||||
corner_x * sprite_size,
|
||||
corner_y * sprite_size,
|
||||
@ -154,13 +158,13 @@ func _get_controller_type() -> void:
|
||||
or controller_name.contains("sony")
|
||||
or controller_name.contains("playstation")
|
||||
):
|
||||
controller = ControllerType.SONY
|
||||
_controller = ControllerType.SONY
|
||||
elif controller_name.contains("steam"):
|
||||
controller = ControllerType.STEAM
|
||||
_controller = ControllerType.STEAM
|
||||
elif controller_name.contains("nintendo"):
|
||||
controller = ControllerType.NINTENDO
|
||||
_controller = ControllerType.NINTENDO
|
||||
else:
|
||||
controller = ControllerType.XBOX
|
||||
_controller = ControllerType.XBOX
|
||||
|
||||
|
||||
func _set_current_prompts(type: ControllerType) -> void:
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
extends Node
|
||||
|
||||
signal main_loaded
|
||||
signal player_connected(peer_id: int, player_info: Dictionary)
|
||||
signal player_registered(peer_id: int, player_info: Dictionary)
|
||||
signal network_error(message: String)
|
||||
|
||||
const DEFAULT_PORT: int = 10567
|
||||
const MAX_PEERS: int = 20
|
||||
|
||||
var _peer: ENetMultiplayerPeer
|
||||
var players := {}
|
||||
var is_dedicated: bool = false
|
||||
|
||||
var _peer: ENetMultiplayerPeer
|
||||
var _local_player_info := {"name": ""}
|
||||
var _players := {}
|
||||
|
||||
var _title_scene := preload("res://scenes/title.tscn")
|
||||
var _main_scene := preload("res://scenes/main.tscn")
|
||||
@ -27,7 +27,7 @@ func _ready() -> void:
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
Debugger.text("_local_player_info", _local_player_info)
|
||||
Debugger.text("_players", _players)
|
||||
Debugger.text("players", players)
|
||||
|
||||
|
||||
func set_local_player_info(username: String) -> void:
|
||||
@ -36,15 +36,20 @@ func set_local_player_info(username: String) -> void:
|
||||
|
||||
func host_game(dedicated: bool = false) -> void:
|
||||
print("Hosting...")
|
||||
is_dedicated = dedicated
|
||||
_peer = ENetMultiplayerPeer.new()
|
||||
var error := _peer.create_server(DEFAULT_PORT, MAX_PEERS)
|
||||
|
||||
if error:
|
||||
match error:
|
||||
ERR_ALREADY_IN_USE:
|
||||
network_error.emit("Already in use")
|
||||
var message := "Already in use"
|
||||
printerr(message)
|
||||
network_error.emit(message)
|
||||
ERR_CANT_CREATE:
|
||||
network_error.emit("Cannot create server")
|
||||
var message := "Cannot create server"
|
||||
printerr(message)
|
||||
network_error.emit(message)
|
||||
return
|
||||
|
||||
multiplayer.set_multiplayer_peer(_peer)
|
||||
@ -52,22 +57,26 @@ func host_game(dedicated: bool = false) -> void:
|
||||
_load_main()
|
||||
|
||||
if not dedicated:
|
||||
_players[1] = _local_player_info
|
||||
player_connected.emit(1, _local_player_info)
|
||||
_add_player(multiplayer.get_unique_id())
|
||||
players[1] = _local_player_info
|
||||
print("Registered player ", 1, " ", _local_player_info)
|
||||
_add_player(multiplayer.get_unique_id(), _local_player_info)
|
||||
|
||||
|
||||
func join_game(ip: String) -> void:
|
||||
print("Joining " + ip + "...")
|
||||
func join_game(address: String) -> void:
|
||||
print("Joining " + address + "...")
|
||||
_peer = ENetMultiplayerPeer.new()
|
||||
var error := _peer.create_client(ip, DEFAULT_PORT)
|
||||
var error := _peer.create_client(address, DEFAULT_PORT)
|
||||
|
||||
if error:
|
||||
match error:
|
||||
ERR_ALREADY_IN_USE:
|
||||
network_error.emit("Already in use")
|
||||
var message := "Already in use"
|
||||
printerr(message)
|
||||
network_error.emit(message)
|
||||
ERR_CANT_CREATE:
|
||||
network_error.emit("Cannot create server")
|
||||
var message := "Cannot create client"
|
||||
printerr(message)
|
||||
network_error.emit(message)
|
||||
return
|
||||
|
||||
multiplayer.set_multiplayer_peer(_peer)
|
||||
@ -75,7 +84,25 @@ func join_game(ip: String) -> void:
|
||||
_load_main()
|
||||
|
||||
|
||||
func _switch_scene(from: Node, to: PackedScene) -> void:
|
||||
func is_active() -> bool:
|
||||
return (
|
||||
multiplayer.multiplayer_peer.get_connection_status()
|
||||
== MultiplayerPeer.CONNECTION_CONNECTED
|
||||
)
|
||||
|
||||
|
||||
func is_dedicated_server() -> bool:
|
||||
return OS.has_feature("dedicated_server") or DisplayServer.get_name() == "headless"
|
||||
|
||||
|
||||
func player_name(peer_id: int) -> String:
|
||||
if peer_id in players:
|
||||
return str(peer_id) + " (" + players[peer_id]["name"] + ")"
|
||||
|
||||
return str(peer_id)
|
||||
|
||||
|
||||
func _switch_scene(to: PackedScene, from: Node) -> void:
|
||||
if from:
|
||||
from.queue_free()
|
||||
|
||||
@ -86,68 +113,71 @@ func _switch_scene(from: Node, to: PackedScene) -> void:
|
||||
|
||||
func _load_main() -> void:
|
||||
print("Loading Main...")
|
||||
_switch_scene($/root/Title, _main_scene)
|
||||
main_loaded.emit()
|
||||
_switch_scene(_main_scene, $/root/Title)
|
||||
|
||||
|
||||
func _add_player(peer_id: int) -> void:
|
||||
func _add_player(peer_id: int, player_info: Dictionary) -> void:
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
|
||||
print("Adding player ", peer_id)
|
||||
print("Adding player ", player_name(peer_id))
|
||||
var player := _player_scene.instantiate() as Player
|
||||
player.name = str(peer_id)
|
||||
|
||||
var player_holder: Node = $/root/Main/Players
|
||||
player_holder.add_child(player, true)
|
||||
Referencer.main.player_holder.add_child(player, true)
|
||||
player.set_info(player_info)
|
||||
|
||||
|
||||
func _remove_player(peer_id: int) -> void:
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
|
||||
print("Removing player ", peer_id)
|
||||
var player_holder: Node = $/root/Main/Players
|
||||
var player := player_holder.get_node_or_null(str(peer_id))
|
||||
print("Removing player ", player_name(peer_id))
|
||||
var player := Referencer.main.player_holder.get_node_or_null(str(peer_id))
|
||||
if player:
|
||||
player.queue_free()
|
||||
|
||||
|
||||
@rpc("any_peer", "reliable")
|
||||
func _register_player(player_info: Dictionary) -> void:
|
||||
print("Registering player ", player_info)
|
||||
var player_id := multiplayer.get_remote_sender_id()
|
||||
_players[player_id] = player_info
|
||||
player_connected.emit(player_id, player_info)
|
||||
var peer_id := multiplayer.get_remote_sender_id()
|
||||
print("Registering player ", peer_id, " ", player_info)
|
||||
if peer_id == 1 and !player_info["name"]:
|
||||
print("Skipping registering the host")
|
||||
return
|
||||
players[peer_id] = player_info
|
||||
player_registered.emit(peer_id, player_info)
|
||||
|
||||
|
||||
func _on_multiplayer_peer_connected(peer_id: int) -> void:
|
||||
print("Peer connected ", peer_id)
|
||||
_add_player(peer_id)
|
||||
_register_player.rpc_id(peer_id, _local_player_info)
|
||||
_add_player(peer_id, _local_player_info)
|
||||
|
||||
|
||||
func _on_multiplayer_peer_disconnected(peer_id: int) -> void:
|
||||
print("Peer disconnected ", peer_id)
|
||||
_players.erase(peer_id)
|
||||
print("Peer disconnected ", player_name(peer_id))
|
||||
_remove_player(peer_id)
|
||||
players.erase(peer_id)
|
||||
|
||||
|
||||
func _on_multiplayer_connected_to_server() -> void:
|
||||
print("Connected to server")
|
||||
var peer_id := multiplayer.get_unique_id()
|
||||
_players[peer_id] = _local_player_info
|
||||
player_connected.emit(peer_id, _local_player_info)
|
||||
print("Connected to server as ", peer_id)
|
||||
players[peer_id] = _local_player_info
|
||||
print("Registered player ", peer_id, " ", _local_player_info)
|
||||
|
||||
|
||||
func _on_multiplayer_connection_failed() -> void:
|
||||
printerr("Connection failed")
|
||||
multiplayer.set_multiplayer_peer(null)
|
||||
network_error.emit("Connection failed")
|
||||
var message := "Connection failed"
|
||||
printerr(message)
|
||||
network_error.emit(message)
|
||||
|
||||
|
||||
func _on_multiplayer_server_disconnected() -> void:
|
||||
printerr("Server disconnected")
|
||||
_players.clear()
|
||||
_switch_scene($/root/Main, _title_scene)
|
||||
network_error.emit("Server disconnected")
|
||||
var message := "Server disconnected"
|
||||
printerr(message)
|
||||
players.clear()
|
||||
_switch_scene(_title_scene, $/root/Main)
|
||||
network_error.emit(message)
|
||||
|
||||
@ -1,4 +1,23 @@
|
||||
extends Node
|
||||
|
||||
var main_camera: Camera3D
|
||||
signal main_loaded
|
||||
signal menu_opened(menu_node: Menu)
|
||||
signal menu_closed(menu_node: Menu)
|
||||
|
||||
var camera: Camera3D
|
||||
var player: Player
|
||||
var menu: Menu
|
||||
var main: Main:
|
||||
set(value):
|
||||
if value:
|
||||
main_loaded.emit()
|
||||
main = value
|
||||
var chat: Chat
|
||||
|
||||
|
||||
func set_menu_opened(menu_node: Menu) -> void:
|
||||
menu_opened.emit(menu_node)
|
||||
|
||||
|
||||
func set_menu_closed(menu_node: Menu) -> void:
|
||||
menu_closed.emit(menu_node)
|
||||
|
||||
@ -4,6 +4,10 @@ const SETTING_USAGE_FLAG := PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_EDIT
|
||||
const CONFIG_PATH := "user://settings.cfg"
|
||||
|
||||
@export_group("Gameplay")
|
||||
@export_subgroup("Camera")
|
||||
@export var camera_fov: float = 75:
|
||||
set(value):
|
||||
camera_fov = value
|
||||
|
||||
@export_group("Video")
|
||||
@export_subgroup("Display")
|
||||
|
||||
@ -1,6 +1,37 @@
|
||||
class_name Main
|
||||
extends Node
|
||||
|
||||
@onready var player_holder: Node = $Players
|
||||
|
||||
@onready var _player_spawner: MultiplayerSpawner = $PlayerSpawner
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_player_spawner.spawned.connect(_on_player_spawner_spawned)
|
||||
_player_spawner.despawned.connect(_on_player_spawner_despawned)
|
||||
Referencer.main = self
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
Referencer.main = null
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("menu"):
|
||||
if event.is_action_pressed("menu") and Inputer.can_control_player():
|
||||
get_tree().quit()
|
||||
|
||||
|
||||
func _on_player_spawner_spawned(node: Node) -> void:
|
||||
if node is not Player:
|
||||
return
|
||||
|
||||
var player := node as Player
|
||||
print("Spawned player ", Networker.player_name(int(str(player.name))))
|
||||
|
||||
|
||||
func _on_player_spawner_despawned(node: Node) -> void:
|
||||
if node is not Player:
|
||||
return
|
||||
|
||||
var player := node as Player
|
||||
print("Despawned player ", Networker.player_name(int(str(player.name))))
|
||||
|
||||
@ -2,48 +2,63 @@ class_name Player
|
||||
extends CharacterBody3D
|
||||
|
||||
const MOVE_SPEED: float = 5
|
||||
const MOVE_ACCELERATION: float = 25
|
||||
const RUN_SPEED: float = 10
|
||||
const CROUCH_SPEED: float = 1
|
||||
const MOVE_ACCELERATION: float = 50
|
||||
const MOVE_DECELERATION: float = 25
|
||||
|
||||
const JUMP_FORCE: float = 10
|
||||
const FALL_SPEED: float = 20
|
||||
const FALL_ACCELERATION: float = 25
|
||||
|
||||
const CAMERA_CROUCH_HEIGHT: float = 1
|
||||
const CAMERA_HEIGHT_SPEED: float = 5
|
||||
const CAMERA_RUN_EXTRA_FOV: float = 5
|
||||
const CAMERA_FOV_SPEED: float = 50
|
||||
|
||||
@export var _respawn_height: float = -100
|
||||
|
||||
var _peer_id: int = 1
|
||||
var _respawn_point: Vector3
|
||||
var _default_camera_height: float
|
||||
|
||||
var _crouch: bool = false
|
||||
var _run: bool = false
|
||||
|
||||
@onready var _camera: Camera3D = $Camera3D
|
||||
@onready var _name_label: Label3D = $NameLabel
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
set_multiplayer_authority(str(name).to_int())
|
||||
_peer_id = str(name).to_int()
|
||||
print("Player ", Networker.player_name(_peer_id), " enter tree")
|
||||
set_multiplayer_authority(_peer_id)
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_name_label.text = str(name)
|
||||
Networker.player_registered.connect(_on_networker_player_registered)
|
||||
if not is_multiplayer_authority():
|
||||
return
|
||||
|
||||
_default_camera_height = _camera.position.y
|
||||
_respawn_point = global_position
|
||||
_camera.make_current()
|
||||
Referencer.player = self
|
||||
Referencer.main_camera = _camera
|
||||
print("Player ", name, " ready")
|
||||
Referencer.camera = _camera
|
||||
print("Player ", Networker.player_name(_peer_id), " ready authority")
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if not is_multiplayer_authority():
|
||||
print("Player ", Networker.player_name(_peer_id), " exit tree")
|
||||
if Networker.is_active() and not is_multiplayer_authority():
|
||||
return
|
||||
|
||||
Referencer.player = null
|
||||
Referencer.main_camera = null
|
||||
print("Player ", name, " exiting tree")
|
||||
Referencer.camera = null
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not is_multiplayer_authority():
|
||||
if Networker.is_active() and not is_multiplayer_authority():
|
||||
Debugger.vector(
|
||||
"look" + str(name),
|
||||
_camera.global_position,
|
||||
@ -54,6 +69,7 @@ func _process(delta: float) -> void:
|
||||
|
||||
_process_respawning()
|
||||
_process_controller_rotating(delta)
|
||||
_process_camera(delta)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
@ -63,7 +79,7 @@ func _physics_process(delta: float) -> void:
|
||||
_lateral_movement(delta)
|
||||
_vertical_movement(delta)
|
||||
|
||||
_jumping(delta)
|
||||
_jumping()
|
||||
|
||||
move_and_slide()
|
||||
|
||||
@ -72,9 +88,28 @@ func _unhandled_input(event: InputEvent) -> void:
|
||||
if not is_multiplayer_authority():
|
||||
return
|
||||
|
||||
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
|
||||
if event is InputEventMouseMotion:
|
||||
_handle_mouse_rotating(event as InputEventMouseMotion)
|
||||
if (
|
||||
not Inputer.can_control_player()
|
||||
or Input.mouse_mode != Input.MOUSE_MODE_CAPTURED
|
||||
):
|
||||
return
|
||||
|
||||
if event is InputEventMouseMotion:
|
||||
_handle_mouse_rotating(event as InputEventMouseMotion)
|
||||
|
||||
if event.is_action_pressed("crouch"):
|
||||
_crouch = true
|
||||
if event.is_action_released("crouch"):
|
||||
_crouch = false
|
||||
|
||||
if event.is_action_pressed("run"):
|
||||
_run = true
|
||||
if event.is_action_released("run"):
|
||||
_run = false
|
||||
|
||||
|
||||
func set_info(player_info: Dictionary) -> void:
|
||||
_name_label.text = player_info["name"]
|
||||
|
||||
|
||||
func _process_respawning() -> void:
|
||||
@ -94,36 +129,62 @@ func _process_controller_rotating(delta: float) -> void:
|
||||
)
|
||||
)
|
||||
|
||||
var look_slow: float = 0.25 if Input.is_action_pressed("look_slow") else 1.0
|
||||
|
||||
rotate_y(
|
||||
(
|
||||
-controller_raw_input.x
|
||||
* deg_to_rad(Settings.controller_sensitivity_horizontal)
|
||||
* look_slow
|
||||
* delta
|
||||
* (-1 if Settings.invert_controller_horizontal else 1)
|
||||
* (-1.0 if Settings.invert_controller_horizontal else 1.0)
|
||||
)
|
||||
)
|
||||
_camera.rotate_x(
|
||||
(
|
||||
-controller_raw_input.y
|
||||
* deg_to_rad(Settings.controller_sensitivity_vertical)
|
||||
* look_slow
|
||||
* delta
|
||||
* (-1 if Settings.invert_controller_vertical else 1)
|
||||
* (-1.0 if Settings.invert_controller_vertical else 1.0)
|
||||
)
|
||||
)
|
||||
_camera.rotation.x = clampf(_camera.rotation.x, PI / -2, PI / 2)
|
||||
|
||||
|
||||
func _process_camera(delta: float) -> void:
|
||||
var camera_height := _default_camera_height
|
||||
if _crouch:
|
||||
camera_height = CAMERA_CROUCH_HEIGHT
|
||||
_camera.position.y = move_toward(
|
||||
_camera.position.y, camera_height, CAMERA_HEIGHT_SPEED * delta
|
||||
)
|
||||
|
||||
var camera_fov := Settings.camera_fov
|
||||
if _run:
|
||||
camera_fov += CAMERA_RUN_EXTRA_FOV
|
||||
_camera.fov = move_toward(_camera.fov, camera_fov, CAMERA_FOV_SPEED * delta)
|
||||
|
||||
|
||||
func _lateral_movement(delta: float) -> void:
|
||||
var input_dir := Input.get_vector(
|
||||
"move_left", "move_right", "move_forward", "move_back"
|
||||
)
|
||||
var has_input := input_dir.length() > 0
|
||||
var has_input := input_dir.length() > 0 and Inputer.can_control_player()
|
||||
|
||||
if has_input:
|
||||
var direction := (
|
||||
(transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
|
||||
)
|
||||
var new_velocity := direction * MOVE_SPEED
|
||||
var speed := MOVE_SPEED
|
||||
Debugger.text("move_mode", "move", 2)
|
||||
if _crouch:
|
||||
speed = CROUCH_SPEED
|
||||
Debugger.text("move_mode", "crouch", 2)
|
||||
if _run:
|
||||
speed = RUN_SPEED
|
||||
Debugger.text("move_mode", "run", 2)
|
||||
var new_velocity := direction * speed
|
||||
new_velocity.y = velocity.y
|
||||
velocity = velocity.move_toward(new_velocity, MOVE_ACCELERATION * delta)
|
||||
else:
|
||||
@ -141,8 +202,12 @@ func _vertical_movement(delta: float) -> void:
|
||||
velocity.y = 0
|
||||
|
||||
|
||||
func _jumping(_delta: float) -> void:
|
||||
if Input.is_action_just_pressed("jump") and is_on_floor():
|
||||
func _jumping() -> void:
|
||||
if (
|
||||
Inputer.can_control_player()
|
||||
and Input.is_action_just_pressed("jump")
|
||||
and is_on_floor()
|
||||
):
|
||||
velocity.y = JUMP_FORCE
|
||||
|
||||
|
||||
@ -165,3 +230,9 @@ func _handle_mouse_rotating(event: InputEventMouseMotion) -> void:
|
||||
)
|
||||
)
|
||||
_camera.rotation.x = clamp(_camera.rotation.x, -PI / 2, PI / 2)
|
||||
|
||||
|
||||
func _on_networker_player_registered(peer_id: int, player_info: Dictionary) -> void:
|
||||
if peer_id != _peer_id:
|
||||
return
|
||||
set_info(player_info)
|
||||
|
||||
13
scripts/title.gd
Normal file
13
scripts/title.gd
Normal file
@ -0,0 +1,13 @@
|
||||
extends Node
|
||||
|
||||
@onready var _play_menu: PlayMenu = $PlayMenu
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
print("Cadastery v", ProjectSettings.get_setting("application/config/version"))
|
||||
|
||||
if Networker.is_dedicated_server():
|
||||
Networker.call_deferred("host_game", true)
|
||||
return
|
||||
|
||||
_play_menu.open()
|
||||
124
scripts/ui/chat.gd
Normal file
124
scripts/ui/chat.gd
Normal file
@ -0,0 +1,124 @@
|
||||
class_name Chat
|
||||
extends Menu
|
||||
|
||||
const BBCODE_TAGS_TO_ESCAPE: PackedStringArray = [
|
||||
"url", "img", "font", "dropcap", "opentype_features", "outline_size"
|
||||
]
|
||||
|
||||
var _chat_message_scene := preload("res://scenes/ui/chat_message.tscn")
|
||||
|
||||
var _message_history: PackedStringArray = []
|
||||
var _history_position: int = 0
|
||||
|
||||
@onready var _msg_scroll: ScrollContainer = $MsgMargin/MsgVBox/MsgScroll
|
||||
@onready
|
||||
var _msg_container: Container = $MsgMargin/MsgVBox/MsgScroll/MsgMargin/MsgContainer
|
||||
@onready var _msg_margin: Container = $MsgMargin/MsgVBox/MsgScroll/MsgMargin
|
||||
@onready var _message_edit: LineEdit = $EditMargin/EditVBox/MessageEdit
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_message_edit.text_submitted.connect(_on_message_edit_text_submitted)
|
||||
_message_edit.visible = false
|
||||
_msg_margin.minimum_size_changed.connect(_on_message_margin_minimum_size_changed)
|
||||
Consoler.message_sent.connect(_on_consoler_message_sent)
|
||||
Referencer.chat = self
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
Referencer.chat = null
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("menu"):
|
||||
call_deferred("close")
|
||||
|
||||
if _message_edit.has_focus():
|
||||
if (
|
||||
event.is_action_pressed("ui_up")
|
||||
and _history_position + 1 <= _message_history.size()
|
||||
):
|
||||
_history_position += 1
|
||||
_set_message_from_history()
|
||||
|
||||
if event.is_action_pressed("ui_down") and _history_position - 1 >= 0:
|
||||
_history_position -= 1
|
||||
_set_message_from_history()
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("chat") and not is_open:
|
||||
open()
|
||||
|
||||
|
||||
func open() -> void:
|
||||
super.open()
|
||||
_message_edit.visible = true
|
||||
_message_edit.grab_focus()
|
||||
_msg_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO
|
||||
|
||||
|
||||
func close() -> void:
|
||||
super.close()
|
||||
_message_edit.release_focus()
|
||||
_message_edit.visible = false
|
||||
_msg_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_SHOW_NEVER
|
||||
|
||||
|
||||
@rpc("any_peer", "call_local", "reliable", 1)
|
||||
func _send_message(message: String, server: bool = false) -> void:
|
||||
var player_name := ""
|
||||
if not server:
|
||||
player_name = (
|
||||
Networker.players[multiplayer.get_remote_sender_id()]["name"] as String
|
||||
)
|
||||
var message_node := _make_message_node(message, player_name)
|
||||
_msg_container.add_child(message_node)
|
||||
print(player_name + ": " + message)
|
||||
|
||||
|
||||
func _make_message_node(message: String, player_name: String = "") -> RichTextLabel:
|
||||
var node := _chat_message_scene.instantiate() as RichTextLabel
|
||||
if player_name:
|
||||
node.text = "[b]" + player_name + ":[/b] " + _escape_bbcode_tags(message)
|
||||
else:
|
||||
node.text = message
|
||||
|
||||
return node
|
||||
|
||||
|
||||
func _set_message_from_history() -> void:
|
||||
if _history_position > 0:
|
||||
var message := _message_history[-_history_position]
|
||||
_message_edit.text = message
|
||||
else:
|
||||
_message_edit.text = ""
|
||||
|
||||
|
||||
func _escape_bbcode_tags(message: String) -> String:
|
||||
for tag_name in BBCODE_TAGS_TO_ESCAPE:
|
||||
var tag := "[" + tag_name
|
||||
if tag in message:
|
||||
message = message.replace(tag, "[lb]" + tag_name)
|
||||
return message
|
||||
|
||||
|
||||
func _on_message_edit_text_submitted(message: String) -> void:
|
||||
if _message_edit.text == "":
|
||||
return
|
||||
_message_edit.text = ""
|
||||
if not (message in _message_history):
|
||||
_message_history.append(message)
|
||||
_history_position = 0
|
||||
close()
|
||||
_send_message.rpc(message, false)
|
||||
|
||||
|
||||
func _on_message_margin_minimum_size_changed() -> void:
|
||||
_msg_scroll.set_deferred(
|
||||
"scroll_vertical", int(_msg_scroll.get_v_scroll_bar().max_value) + 100
|
||||
)
|
||||
|
||||
|
||||
func _on_consoler_message_sent(message: String) -> void:
|
||||
_send_message.rpc(message, true)
|
||||
16
scripts/ui/menu.gd
Normal file
16
scripts/ui/menu.gd
Normal file
@ -0,0 +1,16 @@
|
||||
class_name Menu
|
||||
extends CanvasLayer
|
||||
|
||||
var is_open: bool = false
|
||||
|
||||
|
||||
func open() -> void:
|
||||
is_open = true
|
||||
Referencer.menu = self
|
||||
Referencer.set_menu_opened(self)
|
||||
|
||||
|
||||
func close() -> void:
|
||||
is_open = false
|
||||
Referencer.menu = null
|
||||
Referencer.set_menu_closed(self)
|
||||
@ -1,15 +1,20 @@
|
||||
extends Panel
|
||||
class_name PlayMenu
|
||||
extends Menu
|
||||
|
||||
@onready var _name_edit: LineEdit = $MarginContainer/GridContainer/NameEdit
|
||||
@onready var _ip_edit: LineEdit = $MarginContainer/GridContainer/IpEdit
|
||||
@onready var _host_button: Button = $MarginContainer/GridContainer/HostButton
|
||||
@onready var _join_button: Button = $MarginContainer/GridContainer/JoinButton
|
||||
@onready var _error_label: Label = $ErrorLabel
|
||||
const SERVER_HISTORY_PATH := "user://server_history"
|
||||
|
||||
var _server_history: PackedStringArray = []
|
||||
var _history_position: int = 0
|
||||
|
||||
@onready var _name_edit: LineEdit = $Panel/MarginContainer/GridContainer/NameEdit
|
||||
@onready var _address_edit: LineEdit = $Panel/MarginContainer/GridContainer/AddressEdit
|
||||
@onready var _host_button: Button = $Panel/MarginContainer/GridContainer/HostButton
|
||||
@onready var _join_button: Button = $Panel/MarginContainer/GridContainer/JoinButton
|
||||
@onready var _error_label: Label = $Panel/ErrorLabel
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if OS.has_feature("dedicated_server") or DisplayServer.get_name() == "headless":
|
||||
Networker.call_deferred("host_game", true)
|
||||
if Networker.is_dedicated_server():
|
||||
return
|
||||
|
||||
_host_button.pressed.connect(_on_host_button_pressed)
|
||||
@ -18,27 +23,68 @@ func _ready() -> void:
|
||||
_error_label.text = ""
|
||||
_name_edit.grab_focus()
|
||||
|
||||
var file := FileAccess.open(SERVER_HISTORY_PATH, FileAccess.READ)
|
||||
if file:
|
||||
_server_history = file.get_as_text().strip_edges().split("\n")
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if _address_edit.has_focus():
|
||||
if (
|
||||
event.is_action_pressed("ui_up")
|
||||
and _history_position + 1 <= _server_history.size()
|
||||
):
|
||||
_history_position += 1
|
||||
_set_address_from_history()
|
||||
|
||||
if event.is_action_pressed("ui_down") and _history_position - 1 >= 0:
|
||||
_history_position -= 1
|
||||
_set_address_from_history()
|
||||
|
||||
|
||||
func _set_address_from_history() -> void:
|
||||
if _history_position > 0:
|
||||
var address := _server_history[-_history_position]
|
||||
_address_edit.text = address
|
||||
else:
|
||||
_address_edit.text = ""
|
||||
|
||||
|
||||
func _display_error(message: String) -> void:
|
||||
_error_label.text = message
|
||||
|
||||
|
||||
func _on_host_button_pressed() -> void:
|
||||
if !_name_edit.text:
|
||||
_display_error("Name cannot be empty")
|
||||
return
|
||||
|
||||
Networker.set_local_player_info(_name_edit.text)
|
||||
Networker.host_game()
|
||||
|
||||
|
||||
func _on_join_button_pressed() -> void:
|
||||
var ip: String = _ip_edit.text
|
||||
if not ip.is_valid_ip_address():
|
||||
_display_error("Invalid IP address")
|
||||
if !_name_edit.text:
|
||||
_display_error("Name cannot be empty")
|
||||
return
|
||||
|
||||
_join_button.disabled = true
|
||||
_host_button.disabled = true
|
||||
|
||||
var address := _address_edit.text
|
||||
|
||||
if not (address in _server_history):
|
||||
_server_history.append(address)
|
||||
var file := FileAccess.open(SERVER_HISTORY_PATH, FileAccess.READ_WRITE)
|
||||
if file:
|
||||
file.seek_end()
|
||||
file.store_line(address)
|
||||
else:
|
||||
file = FileAccess.open(SERVER_HISTORY_PATH, FileAccess.WRITE)
|
||||
file.store_line(address)
|
||||
|
||||
Networker.set_local_player_info(_name_edit.text)
|
||||
Networker.join_game(_ip_edit.text)
|
||||
Networker.join_game(address)
|
||||
|
||||
|
||||
func _on_networker_network_error(message: String) -> void:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user