Compare commits

...

18 Commits
v0.0.3 ... main

Author SHA1 Message Date
3ea967ae59 Update README.md 2025-03-24 16:19:02 +00:00
eb22e7673f set version to 0.0.4
All checks were successful
Build Godot Project1 / godot (cadastery-server.x86_64, server) (push) Successful in 2m32s
Build Godot Project1 / godot (cadastery.exe, windows) (push) Successful in 23s
Build Godot Project1 / godot (cadastery.x86_64, linux) (push) Successful in 27s
Build Godot Project1 / godot (cadastery.zip, mac) (push) Successful in 35s
2025-02-15 19:01:06 +10:00
a604032b79 change consoler to read a file with intervals 2025-02-15 03:07:14 +10:00
f10eebd332 add message_sent signal to consoler 2025-02-15 02:14:27 +10:00
f9603e0a5a tweak consoler 2025-02-15 02:04:54 +10:00
ed41775543 add server console input 2025-02-15 02:02:05 +10:00
809da74969 update Dockerfile 2025-02-15 01:36:31 +10:00
42ef398544 add escaping bbcode tags to chat 2025-02-15 00:56:09 +10:00
1db73736c4 add mono font to chat 2025-02-15 00:40:55 +10:00
c3e906f33c add extra check for controlling player 2025-02-15 00:35:10 +10:00
fa6cf57e0c refactor networker and menus 2025-02-15 00:33:40 +10:00
df06be7542 add _ to private variables 2025-02-15 00:16:38 +10:00
2268cb995d add chat history 2025-02-15 00:07:49 +10:00
01f93fbbad add max message length and disable context menu with chat 2025-02-15 00:02:09 +10:00
293c19170d add caret blink to chat 2025-02-14 23:58:40 +10:00
65c0124861 set max name length 2025-02-14 23:51:48 +10:00
2d9933b627 add Menu class and refactor men-related cursor capturing 2025-02-14 23:49:00 +10:00
7ba087f6e1 close chat on submit 2025-02-14 23:24:19 +10:00
17 changed files with 214 additions and 77 deletions

View File

@ -7,10 +7,7 @@ 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
RUN dnf install -y unzip
RUN dnf install -y wayland-devel
RUN dnf install -y fontconfig
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 \

View File

@ -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.

View File

@ -11,7 +11,7 @@ config_version=5
[application]
config/name="cadastery"
config/version="0.0.3"
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]
@ -48,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]

View File

@ -6,9 +6,10 @@
[node name="Title" type="Node"]
script = ExtResource("1_l5ce6")
[node name="Menu" type="CanvasLayer" parent="."]
[node name="PlayMenu" type="CanvasLayer" parent="."]
script = ExtResource("1_gunvo")
[node name="PlayMenu" type="Panel" parent="Menu"]
[node name="Panel" type="Panel" parent="PlayMenu"]
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
@ -20,9 +21,8 @@ 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
@ -34,54 +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("../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="AddressLabel" 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 = "Address:"
horizontal_alignment = 2
[node name="AddressEdit" 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
[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("../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

View File

@ -66,3 +66,6 @@ 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

View File

@ -1,4 +1,9 @@
[gd_scene format=3 uid="uid://bjrbngxkvhn7f"]
[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
@ -10,6 +15,7 @@ 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

View 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("")

View File

@ -3,6 +3,8 @@ extends Node
func _ready() -> void:
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 _unhandled_input(event: InputEvent) -> void:
@ -15,3 +17,11 @@ func _unhandled_input(event: InputEvent) -> 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

View File

@ -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")
@ -53,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 = []
@ -127,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,
@ -153,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:

View File

@ -7,6 +7,7 @@ const DEFAULT_PORT: int = 10567
const MAX_PEERS: int = 20
var players := {}
var is_dedicated: bool = false
var _peer: ENetMultiplayerPeer
var _local_player_info := {"name": ""}
@ -35,6 +36,7 @@ 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)
@ -100,7 +102,7 @@ func player_name(peer_id: int) -> String:
return str(peer_id)
func _switch_scene(from: Node, to: PackedScene) -> void:
func _switch_scene(to: PackedScene, from: Node) -> void:
if from:
from.queue_free()
@ -111,7 +113,7 @@ func _switch_scene(from: Node, to: PackedScene) -> void:
func _load_main() -> void:
print("Loading Main...")
_switch_scene($/root/Title, _main_scene)
_switch_scene(_main_scene, $/root/Title)
func _add_player(peer_id: int, player_info: Dictionary) -> void:
@ -177,5 +179,5 @@ func _on_multiplayer_server_disconnected() -> void:
var message := "Server disconnected"
printerr(message)
players.clear()
_switch_scene($/root/Main, _title_scene)
_switch_scene(_title_scene, $/root/Main)
network_error.emit(message)

View File

@ -1,12 +1,23 @@
extends Node
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)

View File

@ -2,12 +2,13 @@ class_name Main
extends Node
@onready var player_holder: Node = $Players
@onready var player_spawner: MultiplayerSpawner = $PlayerSpawner
@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)
_player_spawner.spawned.connect(_on_player_spawner_spawned)
_player_spawner.despawned.connect(_on_player_spawner_despawned)
Referencer.main = self
@ -16,7 +17,7 @@ func _exit_tree() -> void:
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("menu") and not Referencer.chat.open:
if event.is_action_pressed("menu") and Inputer.can_control_player():
get_tree().quit()

View File

@ -88,7 +88,10 @@ func _unhandled_input(event: InputEvent) -> void:
if not is_multiplayer_authority():
return
if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
if (
not Inputer.can_control_player()
or Input.mouse_mode != Input.MOUSE_MODE_CAPTURED
):
return
if event is InputEventMouseMotion:
@ -167,9 +170,7 @@ 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 and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED
)
var has_input := input_dir.length() > 0 and Inputer.can_control_player()
if has_input:
var direction := (
@ -203,7 +204,7 @@ func _vertical_movement(delta: float) -> void:
func _jumping() -> void:
if (
Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED
Inputer.can_control_player()
and Input.is_action_just_pressed("jump")
and is_on_floor()
):

View File

@ -1,8 +1,6 @@
extends Node
@onready var _play_menu: Control = $Menu/PlayMenu
@onready var _menus: Array[Control] = [_play_menu]
@onready var _play_menu: PlayMenu = $PlayMenu
func _ready() -> void:
@ -11,3 +9,5 @@ func _ready() -> void:
if Networker.is_dedicated_server():
Networker.call_deferred("host_game", true)
return
_play_menu.open()

View File

@ -1,10 +1,15 @@
class_name Chat
extends CanvasLayer
extends Menu
var open: bool = false
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
@ -16,6 +21,7 @@ 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
@ -25,54 +31,94 @@ func _exit_tree() -> void:
func _input(event: InputEvent) -> void:
if event.is_action_pressed("menu"):
call_deferred("_close")
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 Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
return
if event.is_action_pressed("chat") and not open:
open = true
_message_edit.visible = true
_message_edit.grab_focus()
_msg_scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_AUTO
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if event.is_action_pressed("chat") and not is_open:
open()
func _close() -> void:
open = false
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
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
@rpc("any_peer", "call_local", "reliable", 1)
func _send_message(message: String) -> void:
var player_name := (
Networker.players[multiplayer.get_remote_sender_id()]["name"] as String
)
var message_node := _make_message_node(player_name, message)
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(player_name: String, message: String) -> RichTextLabel:
func _make_message_node(message: String, player_name: String = "") -> RichTextLabel:
var node := _chat_message_scene.instantiate() as RichTextLabel
node.text = "[b]" + player_name + ":[/b] " + message
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 = ""
_send_message.rpc(message)
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
View 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)

View File

@ -1,15 +1,16 @@
extends Panel
class_name PlayMenu
extends Menu
const SERVER_HISTORY_PATH := "user://server_history"
var _server_history: PackedStringArray = []
var _history_position: int = 0
@onready var _name_edit: LineEdit = $MarginContainer/GridContainer/NameEdit
@onready var _address_edit: LineEdit = $MarginContainer/GridContainer/AddressEdit
@onready var _host_button: Button = $MarginContainer/GridContainer/HostButton
@onready var _join_button: Button = $MarginContainer/GridContainer/JoinButton
@onready var _error_label: Label = $ErrorLabel
@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: