Init commit
This commit is contained in:
0
godot/.gdextension
Normal file
0
godot/.gdextension
Normal file
BIN
godot/assets/models/characters/model.glb
(Stored with Git LFS)
Normal file
BIN
godot/assets/models/characters/model.glb
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
godot/assets/models/characters/model.glb.import
(Stored with Git LFS)
Normal file
BIN
godot/assets/models/characters/model.glb.import
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
godot/assets/models/maps/lowpoly_tdm_1/map.glb
(Stored with Git LFS)
Normal file
BIN
godot/assets/models/maps/lowpoly_tdm_1/map.glb
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
godot/assets/models/maps/lowpoly_tdm_1/map.glb.import
(Stored with Git LFS)
Normal file
BIN
godot/assets/models/maps/lowpoly_tdm_1/map.glb.import
(Stored with Git LFS)
Normal file
Binary file not shown.
1
godot/icon.svg
Normal file
1
godot/icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128"><rect width="124" height="124" x="2" y="2" fill="#363d52" stroke="#212532" stroke-width="4" rx="14"/><g fill="#fff" transform="translate(12.322 12.322)scale(.101)"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 814 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H446l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c0 34 58 34 58 0v-86c0-34-58-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042" transform="translate(12.322 12.322)scale(.101)"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></svg>
|
After Width: | Height: | Size: 994 B |
37
godot/icon.svg.import
Normal file
37
godot/icon.svg.import
Normal file
@ -0,0 +1,37 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ds2iifncj650s"
|
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
72
godot/project.godot
Normal file
72
godot/project.godot
Normal file
@ -0,0 +1,72 @@
|
||||
; 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="Killbox"
|
||||
config/version="0.1.0"
|
||||
run/main_scene="res://scenes/game_root/game_root.tscn"
|
||||
config/features=PackedStringArray("4.3", "Forward Plus")
|
||||
config/icon="res://icon.svg"
|
||||
|
||||
[autoload]
|
||||
|
||||
logger="*res://scenes/utils/logger.gd"
|
||||
consts="*res://scenes/utils/consts.gd"
|
||||
GameServerAutoload="*res://scenes/server/server.gd"
|
||||
|
||||
[display]
|
||||
|
||||
window/size/mode=4
|
||||
|
||||
[input]
|
||||
|
||||
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)
|
||||
]
|
||||
}
|
||||
move_backward={
|
||||
"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":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_left={
|
||||
"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":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
move_right={
|
||||
"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":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
shoot={
|
||||
"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)
|
||||
]
|
||||
}
|
||||
jump={
|
||||
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[layer_names]
|
||||
|
||||
3d_render/layer_1="Static world"
|
||||
3d_render/layer_2="Player node"
|
||||
3d_render/layer_3="Characters on the server"
|
||||
3d_physics/layer_1="Static world"
|
||||
3d_navigation/layer_1="Static world"
|
||||
3d_physics/layer_2="Player node"
|
||||
3d_navigation/layer_2="Player Node"
|
||||
3d_physics/layer_3="Characters on the server"
|
||||
3d_navigation/layer_3="Characters on the server"
|
14
godot/rust_bindings.gdextension
Normal file
14
godot/rust_bindings.gdextension
Normal file
@ -0,0 +1,14 @@
|
||||
[configuration]
|
||||
entry_symbol = "gdext_rust_init"
|
||||
compatibility_minimum = 4.1
|
||||
reloadable = true
|
||||
|
||||
[libraries]
|
||||
linux.debug.x86_64 = "res://../rust/target/debug/libopen_strike_2.so"
|
||||
linux.release.x86_64 = "res://../rust/target/release/libopen_strike_2.so"
|
||||
windows.debug.x86_64 = "res://../rust/target/debug/open_strike_2.dll"
|
||||
windows.release.x86_64 = "res://../rust/target/release/open_strike_2.dll"
|
||||
macos.debug = "res://../rust/target/debug/libopen_strike_2.dylib"
|
||||
macos.release = "res://../rust/target/release/libopen_strike_2.dylib"
|
||||
macos.debug.arm64 = "res://../rust/target/debug/libopen_strike_2.dylib"
|
||||
macos.release.arm64 = "res://../rust/target/release/libopen_strike_2.dylib"
|
33
godot/scenes/characters/character_wrapper.gd
Normal file
33
godot/scenes/characters/character_wrapper.gd
Normal file
@ -0,0 +1,33 @@
|
||||
extends Node
|
||||
class_name CharacterWrapper
|
||||
|
||||
@export var die_script: GDScript = null
|
||||
var owner_placeholder: Node3D = null
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# Characters should be always controlled by the server and synced accross client
|
||||
# The owner should be responsible for the syncronization, since this node is
|
||||
# just a dummy that is following the controller
|
||||
set_multiplayer_authority(1)
|
||||
|
||||
pass # Replace with function body.
|
||||
|
||||
# Set the owner placeholder, so the characters can send the requests to a node
|
||||
# it depends on
|
||||
func set_owner_placeholder(owner: Node3D):
|
||||
owner_placeholder = owner
|
||||
|
||||
func die():
|
||||
push_warning("TODO: Implement ragdoll kind of dying and respawn character as an object")
|
||||
queue_free()
|
||||
|
||||
|
||||
func _on_area_body_part_hit(damage: int) -> void:
|
||||
# The owner node should be aware of how to take damage, so we need to
|
||||
# pass the value.
|
||||
if owner_placeholder:
|
||||
if owner_placeholder.has_method("take_damage"):
|
||||
owner_placeholder.take_damage(damage)
|
||||
else:
|
||||
push_warning("Node doesn't know how to take the damage")
|
13
godot/scenes/characters/hit_detected.gd
Normal file
13
godot/scenes/characters/hit_detected.gd
Normal file
@ -0,0 +1,13 @@
|
||||
extends Area3D
|
||||
|
||||
@export var damage_multiplexer: float = 1.0
|
||||
@export var body_part: String = ""
|
||||
|
||||
signal body_part_hit(damage: int)
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group("target")
|
||||
|
||||
func hit(base_damage: int):
|
||||
var final_damage = round(base_damage * damage_multiplexer)
|
||||
body_part_hit.emit(final_damage)
|
3031
godot/scenes/characters/y-bot/character.tscn
Normal file
3031
godot/scenes/characters/y-bot/character.tscn
Normal file
File diff suppressed because one or more lines are too long
78
godot/scenes/game_root/game_root.gd
Normal file
78
godot/scenes/game_root/game_root.gd
Normal file
@ -0,0 +1,78 @@
|
||||
extends Node
|
||||
class_name GameRoot
|
||||
|
||||
signal load_map(name: String)
|
||||
|
||||
# -- config from args
|
||||
var config_file: String = ""
|
||||
|
||||
const MAIN_MENU_SCENE := "res://scenes/menus/main/main_menu.tscn"
|
||||
|
||||
@onready var level_root: Node3D = $LevelLoader/Level
|
||||
@onready var level_spawner: MultiplayerSpawner = $LevelLoader/MultiplayerSpawner
|
||||
|
||||
func _parse_args() -> void:
|
||||
var args := Array(OS.get_cmdline_args())
|
||||
|
||||
var config_arg: String = "--config"
|
||||
if args.has(config_arg):
|
||||
var index := args.find(config_arg)
|
||||
config_file = args[index + 1]
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
_parse_args()
|
||||
|
||||
if OS.has_feature("dedicated_server") or DisplayServer.get_name() == "headless":
|
||||
var err := _start_dedicated_server()
|
||||
if err != OK:
|
||||
logger.error("couldn't start the server, err is " + str(err))
|
||||
else:
|
||||
var err := _start_game()
|
||||
if err != OK:
|
||||
logger.error("couldn't start the game, err is " + str(err))
|
||||
|
||||
func _start_dedicated_server() -> Error:
|
||||
if config_file != "":
|
||||
logger.info("reading config from the file: " + config_file)
|
||||
logger.info("starting in the dedicated server mode")
|
||||
return OK
|
||||
|
||||
|
||||
func _start_game() -> Error:
|
||||
logger.info("starting in the game mode")
|
||||
|
||||
if not ResourceLoader.exists(MAIN_MENU_SCENE):
|
||||
return ERR_DOES_NOT_EXIST
|
||||
var scene: PackedScene = ResourceLoader.load(MAIN_MENU_SCENE)
|
||||
if not scene.can_instantiate():
|
||||
return ERR_CANT_OPEN
|
||||
|
||||
var node: MainMenu = scene.instantiate()
|
||||
add_child(node)
|
||||
return OK
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _on_load_map(map_name: String) -> void:
|
||||
for c in level_root.get_children():
|
||||
level_root.remove_child(c)
|
||||
c.queue_free()
|
||||
|
||||
var path_tmpl := "res://scenes/maps/maps/%s"
|
||||
var path := path_tmpl % map_name
|
||||
|
||||
if not ResourceLoader.exists(path):
|
||||
logger.error("map " + map_name + " doesn't exist")
|
||||
|
||||
var scene: PackedScene = ResourceLoader.load(path)
|
||||
if scene.can_instantiate():
|
||||
var node: Node3D = scene.instantiate()
|
||||
logger.info("loading map: " + map_name)
|
||||
level_root.add_child(node)
|
||||
else:
|
||||
logger.error("Can't initialize")
|
||||
|
18
godot/scenes/game_root/game_root.tscn
Normal file
18
godot/scenes/game_root/game_root.tscn
Normal file
@ -0,0 +1,18 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://d3qjxw4rk4yn4"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/game_root/game_root.gd" id="1_eb14f"]
|
||||
|
||||
[node name="GameRoot" type="Node"]
|
||||
editor_description = "This node serves a starting point for the game. When the game is running as a dedicated server it's supposed to read the config file and start the server, when the game is running in a default mode, it should render the main menu"
|
||||
script = ExtResource("1_eb14f")
|
||||
|
||||
[node name="LevelLoader" type="Node" parent="."]
|
||||
editor_description = "This node is supposed to make it possible to sync the server data across all the possible players"
|
||||
|
||||
[node name="Level" type="Node3D" parent="LevelLoader"]
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="LevelLoader"]
|
||||
_spawnable_scenes = PackedStringArray("res://scenes/maps/maps/lowpoly_tdm_1.tscn")
|
||||
spawn_path = NodePath("../Level")
|
||||
|
||||
[connection signal="load_map" from="." to="." method="_on_load_map"]
|
21
godot/scenes/maps/base/bullet_spawner/bullet_controller.gd
Normal file
21
godot/scenes/maps/base/bullet_spawner/bullet_controller.gd
Normal file
@ -0,0 +1,21 @@
|
||||
extends Node
|
||||
class_name BulletSpawnerController
|
||||
# This script shoud be able to find the player
|
||||
|
||||
func _get_spawner() -> MultiplayerSpawner:
|
||||
return $MultiplayerSpawner
|
||||
|
||||
func _get_root() -> Node3D:
|
||||
return $Bullets
|
||||
|
||||
# -- TODO: Better bullet naming handler
|
||||
var bullet_amount: int = -2147483647
|
||||
func spawn_bullet(starting_point: Node3D, speed: int, damage: int):
|
||||
var node: Node3D = ResourceLoader.load("res://scenes/weapon/bullet.tscn").instantiate()
|
||||
node.position = starting_point.global_position
|
||||
node.transform.basis = starting_point.global_transform.basis
|
||||
node.name = str(bullet_amount)
|
||||
node.speed = speed
|
||||
node.damage = damage
|
||||
bullet_amount += 1
|
||||
_get_root().add_child(node)
|
11
godot/scenes/maps/base/bullet_spawner/bullet_spawner.tscn
Normal file
11
godot/scenes/maps/base/bullet_spawner/bullet_spawner.tscn
Normal file
@ -0,0 +1,11 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dp1lcbwr7vaq1"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/maps/base/bullet_spawner/bullet_controller.gd" id="1_ohxtg"]
|
||||
|
||||
[node name="BulletSpawner" type="Node3D"]
|
||||
script = ExtResource("1_ohxtg")
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."]
|
||||
spawn_path = NodePath("../Bullets")
|
||||
|
||||
[node name="Bullets" type="Node3D" parent="."]
|
92
godot/scenes/maps/base/map_controller.gd
Normal file
92
godot/scenes/maps/base/map_controller.gd
Normal file
@ -0,0 +1,92 @@
|
||||
extends Node
|
||||
class_name MapController
|
||||
|
||||
const PLAYER_SPAWNER: String = "res://scenes/maps/base/player_spawner/player_spawner.tscn"
|
||||
const BULLET_SPAWNER: String = "res://scenes/maps/base/bullet_spawner/bullet_spawner.tscn"
|
||||
|
||||
var player_spawner: PlayerSpawnerController
|
||||
var bullet_spawner: BulletSpawnerController
|
||||
var client_node: Node3D
|
||||
|
||||
@onready var spawn_locations: SpawnController = $SpawnLocations
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
# add player spawner
|
||||
var err: Error = OK
|
||||
|
||||
err = _add_player_spawner()
|
||||
if err != OK:
|
||||
push_error("Couldn't load player spawner")
|
||||
|
||||
err = _add_bullet_spawner()
|
||||
if err != OK:
|
||||
push_error("Couldn't load bullet spawner")
|
||||
|
||||
# Adding a node that should be used by the clients
|
||||
client_node = Node3D.new()
|
||||
client_node.name = "ClientNode"
|
||||
add_child(client_node)
|
||||
# add objects spawner
|
||||
if not OS.has_feature("dedicated_server"):
|
||||
_request_spawn.rpc_id(1)
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
if multiplayer.is_server():
|
||||
pass
|
||||
#var active_players = player_spawner._get_root().get_children()
|
||||
#for n in active_players:
|
||||
#if not Server.players.has(n.owner_id):
|
||||
#_remove_player(n.owner_id)
|
||||
|
||||
@rpc("call_local", "reliable", "any_peer")
|
||||
func _request_spawn():
|
||||
var id: int = multiplayer.get_remote_sender_id()
|
||||
_spawn_player(id)
|
||||
_spawn_player_controller_node.rpc_id(id)
|
||||
|
||||
func _spawn_player(id: int):
|
||||
player_spawner.spawn_players(spawn_locations, id)
|
||||
|
||||
@rpc("call_local", "reliable", "any_peer")
|
||||
func _spawn_player_controller_node():
|
||||
var path := "res://scenes/player/player_input.tscn"
|
||||
var scene: PackedScene = ResourceLoader.load(path)
|
||||
var controller_scene: PlayerPlaceholder = player_spawner.get_player_node(multiplayer.get_unique_id())
|
||||
var player_node: PlayerInputController = scene.instantiate()
|
||||
player_node.controlled_node = controller_scene
|
||||
client_node.add_child(player_node)
|
||||
|
||||
|
||||
func _remove_player(id: int):
|
||||
player_spawner.remove_player(id)
|
||||
|
||||
func _add_player_spawner() -> Error :
|
||||
if not ResourceLoader.exists(PLAYER_SPAWNER):
|
||||
return ERR_DOES_NOT_EXIST
|
||||
var scene: PackedScene = ResourceLoader.load(PLAYER_SPAWNER)
|
||||
if not scene.can_instantiate():
|
||||
return ERR_CANT_OPEN
|
||||
|
||||
var node: Node3D = scene.instantiate()
|
||||
add_child(node)
|
||||
player_spawner = node
|
||||
return OK
|
||||
|
||||
func _add_bullet_spawner() -> Error :
|
||||
if not ResourceLoader.exists(BULLET_SPAWNER):
|
||||
return ERR_DOES_NOT_EXIST
|
||||
var scene: PackedScene = ResourceLoader.load(BULLET_SPAWNER)
|
||||
if not scene.can_instantiate():
|
||||
return ERR_CANT_OPEN
|
||||
var node: BulletSpawnerController = scene.instantiate()
|
||||
add_child(node)
|
||||
bullet_spawner = node
|
||||
return OK
|
||||
|
||||
# -- TODO: Better bullet naming handler
|
||||
var bullet_amount: int = -2147483647
|
||||
func spawn_bullet(starting_point: Node3D, speed: int, damage: int):
|
||||
bullet_spawner.spawn_bullet(starting_point, speed, damage)
|
38
godot/scenes/maps/base/player_spawner/player_spawner.gd
Normal file
38
godot/scenes/maps/base/player_spawner/player_spawner.gd
Normal file
@ -0,0 +1,38 @@
|
||||
class_name PlayerSpawnerController extends Node3D
|
||||
|
||||
|
||||
func _get_spawner() -> MultiplayerSpawner:
|
||||
return $MultiplayerSpawner
|
||||
|
||||
func _get_root() -> Node3D:
|
||||
return $Players
|
||||
|
||||
# -- Spawn a player node and sync it across all peers
|
||||
func spawn_players(spawn_location: SpawnController, id: int) -> Error:
|
||||
if multiplayer.is_server():
|
||||
var char : PlayerPlaceholder = null
|
||||
var player_data: PlayerData = GameServerAutoload.players[id]
|
||||
char = ResourceLoader.load("res://scenes/player/placeholder.tscn").instantiate()
|
||||
char.name = "PlayerPlaceholder_" + str(player_data.id)
|
||||
var new_position: Vector3 = spawn_location.get_spawner(SpawnController.Sides.BLUE)
|
||||
char.global_position = new_position
|
||||
char.owner_id = id
|
||||
_get_root().add_child(char)
|
||||
return OK
|
||||
return ERR_UNAUTHORIZED
|
||||
|
||||
func remove_player(id: int) -> Error:
|
||||
if multiplayer.is_server():
|
||||
var found_childen: Array[Node] =_get_root().get_children()
|
||||
for found_child in found_childen:
|
||||
if found_child.owner_id:
|
||||
if found_child.owner_id == id:
|
||||
found_child.queue_free()
|
||||
return OK
|
||||
return ERR_UNAUTHORIZED
|
||||
|
||||
func get_player_node(id: int) -> PlayerPlaceholder:
|
||||
var nodes: Array[Node] = _get_root().get_children().filter(func(x: PlayerPlaceholder): return x.owner_id == id)
|
||||
if nodes.size() > 0:
|
||||
return nodes[0]
|
||||
return null
|
13
godot/scenes/maps/base/player_spawner/player_spawner.tscn
Normal file
13
godot/scenes/maps/base/player_spawner/player_spawner.tscn
Normal file
@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://xh710fr73bid"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/maps/base/player_spawner/player_spawner.gd" id="1_2hsyd"]
|
||||
|
||||
[node name="PlayerSpawner" type="Node3D"]
|
||||
script = ExtResource("1_2hsyd")
|
||||
|
||||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."]
|
||||
_spawnable_scenes = PackedStringArray("res://scenes/player/placeholder.tscn")
|
||||
spawn_path = NodePath("../Players")
|
||||
spawn_limit = 100
|
||||
|
||||
[node name="Players" type="Node3D" parent="."]
|
7
godot/scenes/maps/base/single_spawn_controller.gd
Normal file
7
godot/scenes/maps/base/single_spawn_controller.gd
Normal file
@ -0,0 +1,7 @@
|
||||
extends Node3D
|
||||
|
||||
var busy: bool = false
|
||||
|
||||
func choose_spawn_location() -> Vector3:
|
||||
busy = true
|
||||
return global_position
|
49
godot/scenes/maps/base/spawn_controller.gd
Normal file
49
godot/scenes/maps/base/spawn_controller.gd
Normal file
@ -0,0 +1,49 @@
|
||||
class_name SpawnController extends Node3D
|
||||
|
||||
@export_category("SpawnController")
|
||||
|
||||
@onready var blue_spawners: Node3D = $Blue
|
||||
@onready var red_spawners: Node3D = $Red
|
||||
|
||||
const SINGLE_SPAWN_CONTROLLER_PATH = "res://scenes/maps/base/single_spawn_controller.gd"
|
||||
enum Sides {BLUE, RED, UNDEFINED}
|
||||
|
||||
@export var side: Sides = Sides.UNDEFINED
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
var single_spawn_controller: GDScript = ResourceLoader.load(SINGLE_SPAWN_CONTROLLER_PATH)
|
||||
for spawn: Node3D in blue_spawners.get_children():
|
||||
spawn.set_script(single_spawn_controller)
|
||||
for spawn: Node3D in red_spawners.get_children():
|
||||
spawn.set_script(single_spawn_controller)
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _get_available_spawn(spawn_set: Node3D) -> Node3D:
|
||||
if multiplayer.is_server():
|
||||
var spawns: Array[Node3D] = []
|
||||
for spawn: Node3D in spawn_set.get_children():
|
||||
if not spawn.busy:
|
||||
spawns.push_back(spawn)
|
||||
var random_index: int = randi_range(0, spawns.size() - 1)
|
||||
return spawns[random_index]
|
||||
return null
|
||||
|
||||
|
||||
func get_spawner(team: Sides) -> Vector3:
|
||||
match team:
|
||||
Sides.BLUE:
|
||||
var spawn := _get_available_spawn(blue_spawners)
|
||||
return spawn.choose_spawn_location()
|
||||
Sides.RED:
|
||||
print("red")
|
||||
return Vector3(0,0,0)
|
||||
_:
|
||||
return Vector3(0,0,0)
|
||||
# Get all spawners for each team
|
954
godot/scenes/maps/maps/lowpoly_tdm_1.tscn
Normal file
954
godot/scenes/maps/maps/lowpoly_tdm_1.tscn
Normal file
File diff suppressed because one or more lines are too long
65
godot/scenes/menus/main/main_menu.gd
Normal file
65
godot/scenes/menus/main/main_menu.gd
Normal file
@ -0,0 +1,65 @@
|
||||
extends Control
|
||||
class_name MainMenu
|
||||
|
||||
const MAP_DIR := "res://scenes/maps/maps/"
|
||||
|
||||
@onready var map_list: ItemList = $CreateServerMenu/MapList
|
||||
@onready var create_server_panel: VBoxContainer = $CreateServerMenu
|
||||
@onready var join_server_panel: VBoxContainer = $JoinServerMenu
|
||||
|
||||
func _get_game_root() -> GameRoot:
|
||||
var game_root: GameRoot = find_parent("GameRoot")
|
||||
return game_root
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
var map_dir := DirAccess.open(MAP_DIR)
|
||||
if map_dir:
|
||||
map_dir.list_dir_begin()
|
||||
var file_name = map_dir.get_next()
|
||||
while file_name != "":
|
||||
map_list.add_item(file_name)
|
||||
file_name = map_dir.get_next()
|
||||
GameServerAutoload.current_map = map_list.get_item_text(0)
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _on_join_pressed() -> void:
|
||||
if create_server_panel.visible:
|
||||
create_server_panel.visible = false
|
||||
join_server_panel.visible = true
|
||||
|
||||
|
||||
func _on_create_server_pressed() -> void:
|
||||
if join_server_panel.visible:
|
||||
join_server_panel.visible = false
|
||||
create_server_panel.visible = true
|
||||
|
||||
|
||||
func _on_close_join_pressed() -> void:
|
||||
join_server_panel.visible = false
|
||||
|
||||
|
||||
func _on_close_create_pressed() -> void:
|
||||
create_server_panel.visible = false
|
||||
|
||||
func _on_map_list_item_selected(index: int) -> void:
|
||||
GameServerAutoload.current_map = map_list.get_item_text(index)
|
||||
|
||||
|
||||
func _on_create_pressed() -> void:
|
||||
GameServerAutoload.create_server(false)
|
||||
_get_game_root().load_map.emit(GameServerAutoload.current_map)
|
||||
visible = false
|
||||
|
||||
|
||||
func _on_join_server_pressed() -> void:
|
||||
var ip: String = $JoinServerMenu/Host/TextEdit.text
|
||||
var port: int = $JoinServerMenu/Port/TextEdit.text.to_int()
|
||||
GameServerAutoload.join_server(ip, port)
|
||||
visible = false
|
||||
|
126
godot/scenes/menus/main/main_menu.tscn
Normal file
126
godot/scenes/menus/main/main_menu.tscn
Normal file
@ -0,0 +1,126 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dnqi0ih2hcpym"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/menus/main/main_menu.gd" id="1_mns85"]
|
||||
|
||||
[node name="MainMenu" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 4
|
||||
script = ExtResource("1_mns85")
|
||||
|
||||
[node name="Buttons" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 4
|
||||
anchor_top = 0.5
|
||||
anchor_bottom = 0.5
|
||||
offset_top = -21.5
|
||||
offset_right = 38.0
|
||||
offset_bottom = 21.5
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="CreateServer" type="Button" parent="Buttons"]
|
||||
layout_mode = 2
|
||||
text = "Create server"
|
||||
|
||||
[node name="Join" type="Button" parent="Buttons"]
|
||||
layout_mode = 2
|
||||
text = "Join"
|
||||
|
||||
[node name="CreateServerMenu" type="VBoxContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 11
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 0
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Port" type="HBoxContainer" parent="CreateServerMenu"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="CreateServerMenu/Port"]
|
||||
layout_mode = 2
|
||||
text = "Port"
|
||||
|
||||
[node name="TextEdit" type="TextEdit" parent="CreateServerMenu/Port"]
|
||||
clip_contents = false
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
layout_mode = 2
|
||||
tooltip_text = "On which port to run the server
|
||||
"
|
||||
text = "27015"
|
||||
|
||||
[node name="MapList" type="ItemList" parent="CreateServerMenu"]
|
||||
custom_minimum_size = Vector2(200, 200)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Create" type="Button" parent="CreateServerMenu"]
|
||||
layout_mode = 2
|
||||
text = "Create"
|
||||
|
||||
[node name="Close" type="Button" parent="CreateServerMenu"]
|
||||
layout_mode = 2
|
||||
text = "Close
|
||||
"
|
||||
|
||||
[node name="JoinServerMenu" type="VBoxContainer" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -200.0
|
||||
offset_bottom = 120.0
|
||||
grow_horizontal = 0
|
||||
|
||||
[node name="Host" type="HBoxContainer" parent="JoinServerMenu"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="JoinServerMenu/Host"]
|
||||
layout_mode = 2
|
||||
text = "Host"
|
||||
|
||||
[node name="TextEdit" type="TextEdit" parent="JoinServerMenu/Host"]
|
||||
clip_contents = false
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
layout_mode = 2
|
||||
tooltip_text = "On which port to run the server
|
||||
"
|
||||
text = "127.0.0.1"
|
||||
|
||||
[node name="Port" type="HBoxContainer" parent="JoinServerMenu"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="JoinServerMenu/Port"]
|
||||
layout_mode = 2
|
||||
text = "Port"
|
||||
|
||||
[node name="TextEdit" type="TextEdit" parent="JoinServerMenu/Port"]
|
||||
clip_contents = false
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
layout_mode = 2
|
||||
tooltip_text = "On which port to run the server
|
||||
"
|
||||
text = "27015"
|
||||
|
||||
[node name="Join" type="Button" parent="JoinServerMenu"]
|
||||
layout_mode = 2
|
||||
text = "Join"
|
||||
|
||||
[node name="Close" type="Button" parent="JoinServerMenu"]
|
||||
layout_mode = 2
|
||||
text = "Close
|
||||
"
|
||||
|
||||
[connection signal="pressed" from="Buttons/CreateServer" to="." method="_on_create_server_pressed"]
|
||||
[connection signal="pressed" from="Buttons/Join" to="." method="_on_join_pressed"]
|
||||
[connection signal="item_selected" from="CreateServerMenu/MapList" to="." method="_on_map_list_item_selected"]
|
||||
[connection signal="pressed" from="CreateServerMenu/Create" to="." method="_on_create_pressed"]
|
||||
[connection signal="pressed" from="CreateServerMenu/Close" to="." method="_on_close_create_pressed"]
|
||||
[connection signal="pressed" from="JoinServerMenu/Join" to="." method="_on_join_server_pressed"]
|
||||
[connection signal="pressed" from="JoinServerMenu/Close" to="." method="_on_close_join_pressed"]
|
28
godot/scenes/player/placeholder.gd
Normal file
28
godot/scenes/player/placeholder.gd
Normal file
@ -0,0 +1,28 @@
|
||||
extends CharacterBody3D
|
||||
class_name ServerNode
|
||||
|
||||
var jumping := false
|
||||
var input_direction: Vector2 = null
|
||||
var owner_id: int = 0
|
||||
|
||||
func _ready() -> void:
|
||||
pass
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
if is_on_floor() && jumping:
|
||||
velocity.y = const .
|
||||
|
||||
#if shooting:
|
||||
jumping = false
|
||||
|
||||
var direction := (transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized()
|
||||
if is_on_floor():
|
||||
if direction:
|
||||
#first_view_legs_anim.play("Run Forward")
|
||||
velocity.x = direction.x * character_speed
|
||||
velocity.z = direction.z * character_speed
|
||||
else:
|
||||
velocity.x = move_toward(velocity.x, 0, character_speed)
|
||||
velocity.z = move_toward(velocity.z, 0, character_speed)
|
32
godot/scenes/player/placeholder.tscn
Normal file
32
godot/scenes/player/placeholder.tscn
Normal file
@ -0,0 +1,32 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://3m22sdln5238"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/player/placeholder.gd" id="1_djt0m"]
|
||||
[ext_resource type="PackedScene" uid="uid://ddwrs0so7swxn" path="res://scenes/characters/y-bot/character.tscn" id="2_a22jl"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1v0rt"]
|
||||
height = 1.8
|
||||
|
||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_43f22"]
|
||||
properties/0/path = NodePath(".:owner_id")
|
||||
properties/0/spawn = true
|
||||
properties/0/replication_mode = 1
|
||||
properties/1/path = NodePath(".:position")
|
||||
properties/1/spawn = true
|
||||
properties/1/replication_mode = 1
|
||||
|
||||
[node name="PlayerPlaceholder" type="PlayerPlaceholder"]
|
||||
collision_layer = 4
|
||||
collision_mask = 5
|
||||
script = ExtResource("1_djt0m")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.9, 0)
|
||||
shape = SubResource("CapsuleShape3D_1v0rt")
|
||||
|
||||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||
replication_config = SubResource("SceneReplicationConfig_43f22")
|
||||
|
||||
[node name="BulletStartingPoint" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.76042, -0.28729)
|
||||
|
||||
[node name="Character" parent="." instance=ExtResource("2_a22jl")]
|
22
godot/scenes/player/player_input.tscn
Normal file
22
godot/scenes/player/player_input.tscn
Normal file
@ -0,0 +1,22 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://dqp551myngaey"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/player/player_input_controller.gd" id="1_5vm0e"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_uacs5"]
|
||||
|
||||
[node name="PlayerInput" type="CharacterBody3D"]
|
||||
collision_layer = 2
|
||||
collision_mask = 3
|
||||
script = ExtResource("1_5vm0e")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("CapsuleShape3D_uacs5")
|
||||
|
||||
[node name="CameraMount" type="Node3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.70665, -0.197926)
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="CameraMount"]
|
||||
|
||||
[node name="CSGBox3D" type="CSGBox3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.70817, 0)
|
72
godot/scenes/player/player_input_controller.gd
Normal file
72
godot/scenes/player/player_input_controller.gd
Normal file
@ -0,0 +1,72 @@
|
||||
# ---------------------------------------------------------------------
|
||||
# This script is supposed to control the node that is rendered on the
|
||||
# client side, and send the changes to the server node
|
||||
# ---------------------------------------------------------------------
|
||||
extends CharacterBody3D
|
||||
class_name PlayerInputController
|
||||
|
||||
var jumping: bool = false
|
||||
var shooting: bool = false
|
||||
var moving: bool = false
|
||||
var look_dir: Vector2
|
||||
var input_direction := Vector2()
|
||||
var camera_sens: float = 0.002
|
||||
|
||||
const JUMP_VELOCITY = 4.5
|
||||
var character_speed: int = 5
|
||||
|
||||
var controlled_node: PlayerPlaceholder = null
|
||||
@export var owner_id: int = 0
|
||||
|
||||
@onready var camera_mount = $CameraMount
|
||||
func _ready() -> void:
|
||||
set_multiplayer_authority(multiplayer.get_unique_id())
|
||||
global_position = controlled_node.global_position
|
||||
rotation = controlled_node.rotation
|
||||
|
||||
func _input(event):
|
||||
if multiplayer.get_unique_id() == get_multiplayer_authority():
|
||||
if Input.is_action_just_pressed("jump"): jump()
|
||||
if Input.is_action_just_released("shoot"): shooting = false
|
||||
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
|
||||
look_dir = event.relative * 1
|
||||
rotation.y -= look_dir.x * camera_sens * 1.0
|
||||
camera_mount.rotation.x = clamp(camera_mount.rotation.x - look_dir.y * camera_sens * 1.0, -1.5, 1.5)
|
||||
controlled_node.set_rotation_x.rpc_id(1, rotation.x)
|
||||
controlled_node.set_rotation_y.rpc_id(1, rotation.y)
|
||||
if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right") or Input.is_action_pressed("move_forward") or Input.is_action_pressed("move_backwards"):
|
||||
moving = true
|
||||
else:
|
||||
moving = false
|
||||
|
||||
func jump():
|
||||
jumping = true
|
||||
controlled_node.jump.rpc_id(1)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if multiplayer.get_unique_id() == get_multiplayer_authority():
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||
input_direction = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
|
||||
controlled_node.set_input_direction.rpc_id(1, input_direction)
|
||||
if not is_on_floor():
|
||||
velocity += get_gravity() * delta
|
||||
if is_on_floor() && jumping:
|
||||
velocity.y = JUMP_VELOCITY
|
||||
|
||||
#if shooting:
|
||||
jumping = false
|
||||
|
||||
var direction := (transform.basis * Vector3(input_direction.x, 0, input_direction.y)).normalized()
|
||||
if is_on_floor():
|
||||
if direction:
|
||||
#first_view_legs_anim.play("Run Forward")
|
||||
velocity.x = direction.x * character_speed
|
||||
velocity.z = direction.z * character_speed
|
||||
else:
|
||||
velocity.x = move_toward(velocity.x, 0, character_speed)
|
||||
velocity.z = move_toward(velocity.z, 0, character_speed)
|
||||
#controlled_node.sync_velocity.rpc_id(1, velocity.x, velocity.y, velocity.z)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
move_and_slide()
|
12
godot/scenes/player/server_node.tscn
Normal file
12
godot/scenes/player/server_node.tscn
Normal file
@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://cse87uxvcvhee"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/player/placeholder.gd" id="1_cs2mj"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_82tpl"]
|
||||
|
||||
[node name="ServerNode" type="CharacterBody3D"]
|
||||
script = ExtResource("1_cs2mj")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
shape = SubResource("CapsuleShape3D_82tpl")
|
5
godot/scenes/server/player_data.gd
Normal file
5
godot/scenes/server/player_data.gd
Normal file
@ -0,0 +1,5 @@
|
||||
extends Resource
|
||||
class_name PlayerData
|
||||
|
||||
@export var id: int = 0
|
||||
@export var username: String = ""
|
69
godot/scenes/server/server.gd
Normal file
69
godot/scenes/server/server.gd
Normal file
@ -0,0 +1,69 @@
|
||||
extends Node
|
||||
class_name GameServer
|
||||
|
||||
@export var port: int = 27015
|
||||
@export var player_limit: int = 30
|
||||
@export var current_map: String = "lowpoly_tdm_2"
|
||||
|
||||
@export var current_player_data := PlayerData.new()
|
||||
|
||||
# -- This variable should store all the active players
|
||||
var players: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
multiplayer.peer_connected.connect(_on_player_connected)
|
||||
multiplayer.peer_disconnected.connect(_on_player_disconnected)
|
||||
multiplayer.connected_to_server.connect(_on_connected_to_server)
|
||||
|
||||
|
||||
func _on_player_disconnected(id) -> void:
|
||||
logger.info("player is disconnected with id: " + str(id))
|
||||
|
||||
|
||||
func _on_player_connected(id) -> void:
|
||||
if multiplayer.is_server():
|
||||
logger.info("player is connected with id: " + str(id))
|
||||
|
||||
func _on_connected_to_server() -> void:
|
||||
logger.info("connection is successful, sending info")
|
||||
register_player.rpc_id(1, multiplayer.get_unique_id(), current_player_data.username)
|
||||
|
||||
func create_server(server_only: bool = false) -> Error:
|
||||
var peer := ENetMultiplayerPeer.new()
|
||||
logger.info("starting a server the port: " + str(port))
|
||||
var err := peer.create_server(port, player_limit)
|
||||
multiplayer.multiplayer_peer = peer
|
||||
if err:
|
||||
return err
|
||||
if !server_only:
|
||||
var player_data := PlayerData.new()
|
||||
player_data.id = 1
|
||||
logger.warning("TODO: player name is not yet implemented")
|
||||
player_data.username = "dummy"
|
||||
players[1] = player_data
|
||||
return OK
|
||||
|
||||
func join_server(ip: String, port: int) -> Error:
|
||||
var peer = ENetMultiplayerPeer.new()
|
||||
logger.info("trying to connect to: " + ip + ":" + str(port))
|
||||
var err = peer.create_client(ip, port)
|
||||
if err != OK:
|
||||
return err
|
||||
multiplayer.multiplayer_peer = peer
|
||||
return OK
|
||||
|
||||
@rpc("any_peer", "reliable", "call_remote")
|
||||
func register_player(id: int, name: String):
|
||||
if multiplayer.is_server():
|
||||
logger.info("registering player: " + str(id))
|
||||
var player_data := PlayerData.new()
|
||||
player_data.id = id
|
||||
player_data.username = name
|
||||
players[multiplayer.get_remote_sender_id()] = player_data
|
||||
logger.info("player " + str(id) + " is registered")
|
||||
else:
|
||||
logger.debug("register player is supposed to be executed on the server")
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
4
godot/scenes/utils/consts.gd
Normal file
4
godot/scenes/utils/consts.gd
Normal file
@ -0,0 +1,4 @@
|
||||
extends Resource
|
||||
|
||||
const DEFAULT_JUMP_VELOCITY: float = 4.5
|
||||
const DEFAULT_CHARACTER_SPEED: float = 5.0
|
50
godot/scenes/utils/logger.gd
Normal file
50
godot/scenes/utils/logger.gd
Normal file
@ -0,0 +1,50 @@
|
||||
extends Node
|
||||
class_name Logger
|
||||
|
||||
|
||||
var thread: Thread = Thread.new()
|
||||
var mutex: Mutex = Mutex.new()
|
||||
var log_queue: Array[String] = []
|
||||
var running: bool = true
|
||||
|
||||
|
||||
func _ready():
|
||||
thread.start(log_writer)
|
||||
|
||||
func info(msg: Variant):
|
||||
mutex.lock()
|
||||
log_queue.append("[color=white][b]INFO:[/b] [/color]" + msg)
|
||||
mutex.unlock()
|
||||
|
||||
func debug(msg: Variant):
|
||||
mutex.lock()
|
||||
log_queue.append("[color=cyan][b]DEBUG:[/b] [/color]" + msg)
|
||||
mutex.unlock()
|
||||
|
||||
func warning(msg: Variant):
|
||||
mutex.lock()
|
||||
log_queue.append("[color=yellow][b]WARN:[/b] [/color]" + msg)
|
||||
push_warning(msg)
|
||||
mutex.unlock()
|
||||
|
||||
|
||||
func error(msg: Variant):
|
||||
mutex.lock()
|
||||
log_queue.append("[color=red][b]ERROR:[/b] [/color]" + msg)
|
||||
push_error(msg)
|
||||
mutex.unlock()
|
||||
|
||||
func log_writer():
|
||||
while running:
|
||||
mutex.lock()
|
||||
while log_queue.size() > 0:
|
||||
var log_message = log_queue.pop_front()
|
||||
print_rich(log_message)
|
||||
mutex.unlock()
|
||||
|
||||
# Prevent high CPU usage
|
||||
await get_tree().create_timer(0.1).timeout
|
||||
|
||||
func _exit_tree():
|
||||
running = false
|
||||
thread.wait_to_finish()
|
Reference in New Issue
Block a user