Add hud functionality, decomposition of Networking.gd

This commit is contained in:
leca 2024-03-05 18:58:11 +03:00
parent 6b2f1db9f9
commit eb1ba01812
12 changed files with 503 additions and 299 deletions

View File

@ -21,6 +21,8 @@ config/icon="res://icon.svg"
Networking="*res://scripts/Networking.gd"
GameData="*res://scripts/GameData.gd"
Anticheat="*res://scripts/Anticheat.gd"
ServerUtils="*res://scripts/utils/ServerUtils.gd"
NetUtils="*res://scripts/utils/NetUtils.gd"
[input]

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=15 format=3 uid="uid://gxfhitfre2fj"]
[gd_scene load_steps=17 format=3 uid="uid://gxfhitfre2fj"]
[ext_resource type="Texture2D" uid="uid://vnk3r1p4ao3n" path="res://textures/prototype-textures/Prototype_symbol_cross_32x32px.png" id="1_g1v70"]
[ext_resource type="Texture2D" uid="uid://c4pah1vj0aa4x" path="res://textures/prototype-textures/Prototype_symbol_cross_32x32px.png" id="1_g1v70"]
[ext_resource type="Texture2D" uid="uid://na1y6c7osyj2" path="res://textures/logo/health.svg" id="1_ts1uf"]
[ext_resource type="Texture2D" uid="uid://cxpljra1na1p8" path="res://textures/logo/shield.svg" id="2_ijndi"]
[ext_resource type="Texture2D" uid="uid://d1i1fgjbpwped" path="res://textures/logo/magazine.svg" id="3_ssnuf"]
@ -34,6 +34,15 @@ border_width_right = 1
border_width_bottom = 1
border_blend = true
[sub_resource type="LabelSettings" id="LabelSettings_l41k6"]
font_size = 30
[sub_resource type="LabelSettings" id="LabelSettings_ky32e"]
font_size = 64
font_color = Color(0.992157, 0.415686, 0.631373, 1)
shadow_size = 9
shadow_color = Color(0, 0, 0, 0.772549)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ouyds"]
bg_color = Color(0.117647, 0.117647, 0.117647, 0.368627)
border_width_left = 1
@ -287,29 +296,70 @@ offset_right = 20.0
offset_bottom = 30.0
grow_horizontal = 2
[node name="cs_won" type="Label" parent="round_status"]
[node name="bg" type="Panel" parent="round_status"]
layout_mode = 0
offset_top = 3.0
offset_right = 40.0
offset_bottom = 26.0
[node name="Panel" type="Panel" parent="round_status"]
layout_mode = 0
offset_right = 40.0
offset_bottom = 30.0
offset_left = -66.0
offset_right = 106.0
offset_bottom = 66.0
theme_override_styles/panel = SubResource("StyleBoxFlat_pxi8e")
[node name="os_won" type="Label" parent="round_status"]
[node name="cs_score_game" type="Label" parent="round_status"]
offset_left = -52.0
offset_top = -2.0
offset_right = -35.0
offset_bottom = 37.0
text = "0"
label_settings = SubResource("LabelSettings_l41k6")
[node name="cs_score_round" type="Label" parent="round_status"]
offset_left = -48.0
offset_top = 39.0
offset_right = -38.0
offset_bottom = 62.0
text = "0"
[node name="os_score_round" type="Label" parent="round_status"]
offset_left = 83.0
offset_top = 39.0
offset_right = 93.0
offset_bottom = 62.0
text = "0"
[node name="os_score_game" type="Label" parent="round_status"]
offset_left = 79.0
offset_top = -2.0
offset_right = 96.0
offset_bottom = 40.0
text = "0"
label_settings = SubResource("LabelSettings_l41k6")
[node name="round_number" type="Label" parent="round_status"]
layout_mode = 0
offset_top = 3.0
offset_right = 40.0
offset_bottom = 26.0
offset_left = -13.0
offset_top = 5.0
offset_right = 53.0
offset_bottom = 28.0
text = "Round N"
[node name="time" type="Label" parent="round_status"]
layout_mode = 0
offset_top = 3.0
offset_right = 40.0
offset_bottom = 26.0
offset_left = -5.0
offset_top = 39.0
offset_right = 46.0
offset_bottom = 62.0
text = "mm:ss"
[node name="winner" type="Label" parent="round_status"]
visible = false
layout_mode = 0
offset_left = -104.0
offset_top = 46.0
offset_right = 159.0
offset_bottom = 135.0
text = "CS WON"
label_settings = SubResource("LabelSettings_ky32e")
horizontal_alignment = 1
vertical_alignment = 1
[node name="kill_log" type="Label" parent="."]
layout_mode = 0

View File

@ -1,6 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://cnu1vf8k5i3tv"]
[ext_resource type="PackedScene" uid="uid://hf47u08p80fo" path="res://scenes/models/pistoletto.dae" id="1_hdcb6"]
[ext_resource type="PackedScene" uid="uid://hf47u08p80fo" path="res://models/pistoletto.dae" id="1_hdcb6"]
[node name="pistol" type="Node3D"]

View File

@ -3,17 +3,16 @@
[ext_resource type="Script" path="res://scripts/Player.gd" id="1_o6o4b"]
[ext_resource type="ArrayMesh" uid="uid://xh7mm0ldn6yw" path="res://models/knife.obj" id="2_7hcoq"]
[ext_resource type="PackedScene" uid="uid://cnu1vf8k5i3tv" path="res://scenes/models/pistol.tscn" id="2_nxbij"]
[ext_resource type="Texture2D" path="res://knife_texturesv3.png" id="3_8p34k"]
[ext_resource type="Texture2D" uid="uid://cbf6w7ativli8" path="res://textures/knife_textures.png" id="2_y1ydh"]
[ext_resource type="PackedScene" uid="uid://caos4gg5cd6f6" path="res://scenes/models/ak_47.tscn" id="3_r56e3"]
[ext_resource type="Material" uid="uid://btj7xxav4d6l0" path="res://textures/materials/orange.res" id="6_md2fv"]
[ext_resource type="Material" uid="uid://ojceh78w7jp0" path="res://textures/materials/black90%.res" id="7_2k5kn"]
[ext_resource type="Material" path="res://textures/materials/orange.res" id="6_md2fv"]
[ext_resource type="Material" uid="uid://bfvkovv6sevfw" path="res://textures/materials/black90%.res" id="7_2k5kn"]
[ext_resource type="ArrayMesh" uid="uid://dpdsmpuycacsx" path="res://models/playerv2.obj" id="7_jg2rj"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jqoeg"]
albedo_texture = ExtResource("3_8p34k")
albedo_texture = ExtResource("2_y1ydh")
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0suq1"]
albedo_texture = ExtResource("3_8p34k")
[sub_resource type="BoxShape3D" id="BoxShape3D_04dhp"]
size = Vector3(0.379028, 0.376923, 0.371674)

View File

@ -1,152 +1,16 @@
extends Node
var player_script := load("res://scripts/Player.gd")
var server_map
@onready var Weapons = GameData.Weapons
var player_model = load("res://scenes/models/player.tscn")
var peer = ENetMultiplayerPeer.new()
var settings
var clients:Dictionary = {}
var last_client_id = 1
var map_path
var map_root_name
var team_CS = {
"spawnpoints": [],
"members": [],
"round_score": 0,
"game_score": 0
}
var team_OS = {
"spawnpoints": [],
"members": [],
"round_score": 0,
"game_score": 0
}
var round_number = 0
var gamemode
func parse_arguments():
var arguments = {}
for argument in OS.get_cmdline_args():
if argument.find("=") > -1:
var key_value = argument.split("=")
arguments[key_value[0].lstrip("--")] = key_value[1]
else:
# Options without an argument will be present in the dictionary,
# with the value set to an empty string.
arguments[argument.lstrip("--")] = ""
return arguments
func check_map_availability(path):
var maps = DirAccess.open("res://scenes/maps").get_files()
var map_name = (path.split("/")[-1]).split(".")[0]
for map in maps:
var checking_map_name = str(map.split(".")[0])
if(checking_map_name == map_name):
return true
return false
func check_gamemode_availability(gamemode):
var gamemodes = settings["game"]["gamemodes"].keys()
for gm in gamemodes:
if gm == gamemode:
return true
return false
func _ready():
var arguments = parse_arguments()
if "--server" in OS.get_cmdline_args():
GameData.read_settings()
settings = GameData.server_settings
################ parsing map
var path = "res://scenes/maps/%s.tscn" % arguments["map"] if arguments.has("map") else "res://scenes/maps/%s.tscn" % settings["defaults"]["map"]
if (check_map_availability(path)):
map_path = path
else:
print("Unknown map %s Available maps:" % path)
for map in DirAccess.open("res://scenes/maps").get_files():
print(str(map.split(".")[0]))
get_tree().quit()
return
################ parsing gamemode
var gm = str(arguments["gamemode"]) if (arguments.has("gamemode")) else "TDM"
if(check_gamemode_availability(gm)):
print("Gamemode exists")
else:
print("No")
StartServer(map_path, gm)
#######################################SERVER####################################
func check_gamemode_end_conditions():
match gamemode:
"TDM":
var kills_amount_to_win = settings["game"]["gamemodes"]["TDM"]["kills"]
if team_OS["round_score"] >= kills_amount_to_win:
team_OS["game_score"] += 1
print("OS won")
send_everyone([find_playermodel_by_internal_id(clients[clients.keys().pick_random()]["internal_id"]).end_round, 1]) # 1 = os is win
new_round()
elif team_CS["round_score"] >= kills_amount_to_win:
team_CS["game_score"] += 1
send_everyone([find_playermodel_by_internal_id(clients[clients.keys().pick_random()]["internal_id"]).end_round, -1]) # -1 = cs is win
print("CS won")
new_round()
func switch_map(new_map_path):
print("Switching map to %s" % new_map_path)
if (not check_map_availability(new_map_path)):
var default_map = settings["defaults"]["map"]
print("Error. No map found. Loading default map %s" % default_map)
new_map_path = "res://scenes/maps/%s.tscn" % default_map
if (not check_map_availability(new_map_path)):
print("Error. Default map is not valid. Please, specify a valid map in a config file.")
return
map_path = new_map_path
get_tree().change_scene_to_file(map_path)
await get_tree().create_timer(0.1).timeout #I know that this isn't a good practice, but I didn't find anything better
map_root_name = (map_path.split("/")[-1]).split(".")[0]
server_map = get_tree().root.get_node(map_root_name)
var spawnpoints = server_map.find_children("spawnpoint*", "" ,true)
team_OS["spawnpoints"] = []
team_CS["spawnpoints"] = []
for spawnpoint in spawnpoints:
if spawnpoint.team == 0: # cs
team_CS["spawnpoints"].push_back(spawnpoint)
elif spawnpoint.team > 0: # os
team_OS["spawnpoints"].push_back(spawnpoint)
func switch_gamemode(new_gamemode):
if not check_gamemode_availability(new_gamemode):
print("No gamemode found")
return
gamemode = new_gamemode
func new_game(new_map_path, new_gamemode):
team_OS["game_score"] = 0
team_OS["round_score"] = 0
team_CS["game_score"] = 0
team_CS["round_score"] = 0
round_number = 0
await switch_map(new_map_path)
await switch_gamemode(new_gamemode)
func new_round():
round_number += 1
team_OS["round_score"] = 0
team_CS["round_score"] = 0
func find_playermodel_by_internal_id(internal_id):
return server_map.get_node("player" + str(internal_id))
func StartServer(map_path, gm):
await new_game(map_path, gm)
var port = int(settings["port"])
var maxclients = int(settings["maxclients"])
func StartServer():
var port = int(GameData.server_settings["port"])
var maxclients = int(GameData.server_settings["maxclients"])
if (peer.create_server(port, maxclients) != OK):
print("Couldn't create server. Check if another proccess binds port %s" % str(port))
return
@ -157,56 +21,6 @@ func StartServer(map_path, gm):
peer.connect("peer_connected", _Peer_Connected)
peer.connect("peer_disconnected", _Peer_Disconnected)
var spectator = preload("res://scenes/models/spectator.tscn").instantiate()
server_map.add_child(spectator)
func send_everyone(args):
if (typeof(args[0]) == 4): #string
for current_client_id in clients.keys():
if (args.size() == 1): rpc_id(int(current_client_id), args[0])
elif (args.size() == 2): rpc_id(int(current_client_id), args[0], args[1])
elif (args.size() == 3): rpc_id(int(current_client_id), args[0], args[1], args[2])
else: rpc_id(int(current_client_id), args[0], args[1], args[2], args[3])
else:
for current_client_id in clients.keys():
if (args.size() == 1): args[0].rpc_id(int(current_client_id))
elif (args.size() == 2): args[0].rpc_id(int(current_client_id), args[1])
elif (args.size() == 3): args[0].rpc_id(int(current_client_id), args[1], args[2])
else: args[0].rpc_id(int(current_client_id), args[1], args[2], args[3])
func send_everyone_except(client_id, args):
if (typeof(args[0]) == 4): #string
for current_client_id in clients.keys():
if (str(current_client_id) == str(client_id)): continue
if (args.size() == 1): rpc_id(int(current_client_id), args[0])
elif (args.size() == 2): rpc_id(int(current_client_id), args[0], args[1])
elif (args.size() == 3): rpc_id(int(current_client_id), args[0], args[1], args[2])
else: rpc_id(int(current_client_id), args[0], args[1], args[2], args[3])
else:
for current_client_id in clients.keys():
if (str(current_client_id) == str(client_id)): continue
if (args.size() == 1): args[0].rpc_id(int(current_client_id))
elif (args.size() == 2): args[0].rpc_id(int(current_client_id), args[1])
elif (args.size() == 3): args[0].rpc_id(int(current_client_id), args[1], args[2])
else: args[0].rpc_id(int(current_client_id), args[1], args[2], args[3])
func find_weapon_by_number(number):
var found_weapon
for weapon in settings["game"]["weapons"].keys():
if (settings["game"]["weapons"][weapon]["number"] == number):
found_weapon = settings["game"]["weapons"][weapon].duplicate()
break
return found_weapon
func find_class_type_by_number(number):
var found_class
var classtypes = settings["game"]["classTypes"]
for classtype in classtypes:
if classtypes[classtype]["number"] == number:
found_class = classtypes[classtype].duplicate()
break
return found_class
func _Peer_Connected(client_id):
print("User " + str(client_id) + " has conected")
var internal_id = last_client_id + 1
@ -217,31 +31,31 @@ func _Peer_Connected(client_id):
client["position"] = Vector3(0, 10, 0)
client["internal_id"] = internal_id
client["is_playable"] = false
client["current_weapon"] = settings["game"]["weapons"]["knife"].duplicate()
client["current_weapon"] = GameData.server_settings["game"]["weapons"]["knife"].duplicate()
var puppet = player_model.instantiate()
puppet.set_properties(clients[client_id])
server_map.add_child(puppet)
ServerUtils.server_map.add_child(puppet)
@rpc("any_peer", "reliable", "call_remote")
func client_ready(client_id):
var client = clients[client_id]
var internal_id = client["internal_id"]
send_everyone_except(client_id, ["spawn_puppet", clients[client_id]])
NetUtils.send_everyone_except(client_id, [Networking.spawn_puppet, clients[client_id]])
client["ready"] = true
var client_playermodel = find_playermodel_by_internal_id(internal_id)
var client_playermodel = ServerUtils.find_playermodel_by_internal_id(internal_id)
if (client["class_type"] == 0):
var class_spawnpoint = find_class_type_by_number(client["class_type"])["spawnpoint"]
var class_spawnpoint = ServerUtils.find_class_type_by_number(client["class_type"])["spawnpoint"]
client["position"] = Vector3(class_spawnpoint[0], class_spawnpoint[1], class_spawnpoint[2])
else:
var index = abs(client["class_type"])
if (client["class_type"] > 0):
client["position"] = team_OS["spawnpoints"].pick_random().get_class_spawnpoint(index)
client["position"] = ServerUtils.team_OS["spawnpoints"].pick_random().get_class_spawnpoint(index)
elif (client["class_type"] < 0):
client["position"] = team_CS["spawnpoints"].pick_random().get_class_spawnpoint(index)
client["position"] = ServerUtils.team_CS["spawnpoints"].pick_random().get_class_spawnpoint(index)
client_playermodel.set_properties(client)
client_playermodel.teleport.rpc_id(client_id, Vector3(client["position"].x, client["position"].y, client["position"].z))
@ -250,14 +64,16 @@ func _Peer_Disconnected(client_id):
var client = clients[client_id]
var internal_id = client["internal_id"]
if (client["class_type"] < 0):
team_CS["members"].erase(client)
ServerUtils.team_CS["members"].erase(client)
elif (client["class_type"] > 0):
team_OS["members"].erase(client)
ServerUtils.team_OS["members"].erase(client)
rpc("despawn_puppet", internal_id)
var puppet = server_map.get_node("player" + str(internal_id))
server_map.remove_child(puppet)
var puppet = ServerUtils.server_map.get_node("player" + str(internal_id))
ServerUtils.server_map.remove_child(puppet)
clients.erase(client_id)
if (clients.size() == 0):
ServerUtils.new_game(null, null) #Not changing anything
@rpc ("any_peer", "reliable", "call_remote")
func get_character_properties(client_id):
@ -270,26 +86,29 @@ func get_character_properties(client_id):
func sync_client(client_id, position, rotation):
var client = clients[client_id]
var internal_id = str(client["internal_id"])
var client_playermodel = find_playermodel_by_internal_id(internal_id)
var client_playermodel = ServerUtils.find_playermodel_by_internal_id(internal_id)
client_playermodel.position = position
client_playermodel.find_child("Head").rotation.y = rotation.y
client_playermodel.find_child("Head").find_child("Camera").rotation.x = rotation.x
client["position"] = position
client["rotation"] = rotation
send_everyone_except(client_id, [client_playermodel.sync_puppet, internal_id, position, rotation])
#NetUtils.send_everyone_except(client_id, ["sync_puppet", internal_id, position, rotation])
NetUtils.send_everyone_except(client_id, [client_playermodel.sync_puppet, internal_id, position, rotation])
@rpc ("any_peer", "call_remote", "reliable")
func get_client_list(client_id):
#var playermodel = ServerUtils.find_playermodel_by_internal_id(clients[client_id]["internal_id"])
for current_client_id in clients.keys():
if (current_client_id == client_id): continue
rpc_id(client_id, "spawn_puppet", clients[current_client_id])
#rpc_id(client_id, playermodel.spawn_puppet, clients[current_client_id])
@rpc ("any_peer", "call_remote", "reliable")
func get_server_settings(client_id):
var client = clients[client_id]
var internal_id = str(client["internal_id"])
var client_playermodel = find_playermodel_by_internal_id(internal_id)
client_playermodel.set_game_settings.rpc_id(client_id, settings["game"])
var client_playermodel = ServerUtils.find_playermodel_by_internal_id(internal_id)
client_playermodel.set_game_settings.rpc_id(client_id, GameData.server_settings["game"])
@rpc ("any_peer", "call_remote", "reliable")
func set_nickname(client_id, nickname):
@ -299,10 +118,10 @@ func set_nickname(client_id, nickname):
func shot(client_id):
var client = clients[client_id]
var internal_id = client["internal_id"]
var current_weapon = settings["game"]["weapons"].find_key(find_weapon_by_number(client["current_weapon"]["number"]))
var current_weapon_settings = settings["game"]["weapons"][current_weapon]
var current_weapon = GameData.server_settings["game"]["weapons"].find_key(ServerUtils.find_weapon_by_number(client["current_weapon"]["number"]))
var current_weapon_settings = GameData.server_settings["game"]["weapons"][current_weapon]
var client_playermodel = find_playermodel_by_internal_id(internal_id)
var client_playermodel = ServerUtils.find_playermodel_by_internal_id(internal_id)
var raycast:RayCast3D = client_playermodel.get_node("Head/Camera/viewRaycast")
var weapon_raycast:RayCast3D = client_playermodel.get_node("Head/Camera/Hand/" + str(current_weapon) + "/raycast")
raycast.target_position.z = -current_weapon_settings["range"]
@ -332,7 +151,7 @@ func shot(client_id):
var shape_num = weapon_raycast.get_collider_shape()
var shapes = ["head", "body", "hand", "leg"]
var shape = choose_collision_shape(target, shapes, shape_num)
var shape = ServerUtils.choose_collision_shape(target, shape_num)
var damage
for s in shapes:
if s in shape.name:
@ -351,7 +170,7 @@ func shot(client_id):
var client_team = 1 if client["class_type"] > 0 else -1
if (target_client_team == client_team):
if (settings["game"]["gamemodes"][gamemode]["firendlyfile"]):
if (GameData.server_settings["game"]["gamemodes"][ServerUtils.gamemode]["firendlyfile"]):
target_client["HP"] -= damage
else:
target_client["HP"] -= damage
@ -360,82 +179,53 @@ func shot(client_id):
var index = abs(client["class_type"])
var respawn = Vector3(0, 10 ,0)
if (target_client_team == 1):
team_CS["round_score"] += 1
respawn = team_OS["spawnpoints"].pick_random().get_class_spawnpoint(index)
ServerUtils.team_CS["round_score"] += 1
respawn = ServerUtils.team_OS["spawnpoints"].pick_random().get_class_spawnpoint(index)
elif (target_client_team == -1):
team_OS["round_score"] += 1
respawn = team_CS["spawnpoints"].pick_random().get_class_spawnpoint(index)
ServerUtils.team_OS["round_score"] += 1
respawn = ServerUtils.team_CS["spawnpoints"].pick_random().get_class_spawnpoint(index)
print("Score(OS-CS): %s - %s" % [str(team_OS["round_score"]), str(team_CS["round_score"])])
print("Score(OS-CS): %s - %s" % [str(ServerUtils.team_OS["round_score"]), str(ServerUtils.team_CS["round_score"])])
target_client["position"] = respawn
target_client["HP"] = 100
target.teleport.rpc_id(target_client_id, target_client["position"])
check_gamemode_end_conditions()
ServerUtils.check_gamemode_end_conditions()
target.set_hp.rpc_id(target_client_id, target_client["HP"])
elif (target is StaticBody3D):
var shapes = ["head", "body"]
var shape_num = weapon_raycast.get_collider_shape()
var shape = choose_collision_shape(target, shapes, shape_num)
#var shapes = ["head", "body"]
#var shape_num = weapon_raycast.get_collider_shape()
#var shape = ServerUtils.choose_collision_shape(target, shape_num)
target.shot.rpc_id(client_id, weapon_raycast.get_collision_point())
send_everyone_except(client_id, [target.shot, weapon_raycast.get_collision_point()])
func choose_collision_shape(target, shapes, shape_num):
var collision_shapes:Array
for s in target.get_children():
if s is CollisionShape3D:
collision_shapes.push_back(s)
var shape
for i in range(0, collision_shapes.size()):
if i == shape_num:
shape = collision_shapes[i]
break
return shape
NetUtils.send_everyone_except(client_id, [target.shot, weapon_raycast.get_collision_point()])
@rpc("reliable", "call_remote", "any_peer")
func change_weapon(client_id, new_weapon_number):
var client = clients[client_id]
client["reloading"] = false
var internal_id = str(client["internal_id"])
for weapon in Weapons.keys():
if (settings["game"]["weapons"][weapon]["number"] == new_weapon_number):
client["current_weapon"] = settings["game"]["weapons"][weapon].duplicate()
for weapon in GameData.Weapons.keys():
if (GameData.server_settings["game"]["weapons"][weapon]["number"] == new_weapon_number):
client["current_weapon"] = GameData.server_settings["game"]["weapons"][weapon].duplicate()
break
var client_playermodel = find_playermodel_by_internal_id(internal_id)
var client_playermodel = ServerUtils.find_playermodel_by_internal_id(internal_id)
client_playermodel.change_weapon(new_weapon_number)
send_everyone_except(client_id, [client_playermodel.change_weapon_puppet, internal_id, new_weapon_number])
#NetUtils.send_everyone_except(client_id, ["change_weapon_puppet", internal_id, new_weapon_number])
NetUtils.send_everyone_except(client_id, [client_playermodel.change_weapon_puppet, internal_id, new_weapon_number])
@rpc("any_peer", "call_remote", "reliable")
func client_reloading(client_id):
var client = clients[client_id]
var weapons_list = settings["game"]["weapons"]
var weapons_list = GameData.server_settings["game"]["weapons"]
var current_client_weapon = client["current_weapon"]
var current_weapon_example = weapons_list.find_key(find_weapon_by_number(current_client_weapon["number"]))
var current_weapon_example = weapons_list.find_key(ServerUtils.find_weapon_by_number(current_client_weapon["number"]))
var current_weapon_settings = weapons_list[current_weapon_example]
var reload_time = current_weapon_settings["reload"]
client["reloading"] = true
reloading_complete(client_id, reload_time)
func reloading_complete(client_id, reloading_time):
await get_tree().create_timer(reloading_time).timeout
var client = clients[client_id]
if (!client["reloading"]): # if a client has interrupted the reloading
return
var weapons_list = settings["game"]["weapons"]
var current_client_weapon = client["current_weapon"]
var current_weapon_example = weapons_list.find_key(find_weapon_by_number(current_client_weapon["number"]))
var current_weapon_settings = weapons_list[current_weapon_example]
var to_reload = current_weapon_settings["magazine"] - current_client_weapon["magazine"]
if (to_reload <= current_client_weapon["ammo"]):
current_client_weapon["magazine"] += to_reload
current_client_weapon["ammo"] -= to_reload
else:
current_client_weapon["magazine"] += current_client_weapon["ammo"]
current_client_weapon["ammo"] = 0
ServerUtils.reloading_complete(client_id, reload_time)
@rpc("reliable", "any_peer", "call_remote")
func get_map(client_id):
rpc_id(client_id, "receive_map", map_path)
rpc_id(client_id, "receive_map", ServerUtils.map_path)
@rpc("reliable", "any_peer", "call_remote")
func choose_class(client_id, class_id):
@ -443,9 +233,9 @@ func choose_class(client_id, class_id):
client["class_type"] = class_id
#here are must be checks if the teams are balanced. WIP.
if class_id > 0:
team_OS["members"].push_back(client)
ServerUtils.team_OS["members"].push_back(client)
elif class_id < 0:
team_CS["members"].push_back(client)
ServerUtils.team_CS["members"].push_back(client)
switch_class.rpc_id(client_id, class_id)
@ -456,6 +246,9 @@ var menu = preload("res://scenes/HUD/menu.tscn")
var current_map_instance
var choose_team_hud
var playermodel
var puppets_to_spawn = []
var map_path
var map_root_name
@rpc ("reliable", "call_remote")
func set_character_properties(p):
@ -463,6 +256,16 @@ func set_character_properties(p):
@rpc("authority", "reliable", "call_remote")
func spawn_puppet(properties):
if (current_map_instance == null): # Player's not ready
puppets_to_spawn.push_back(properties)
return
var puppet = player_model.instantiate()
properties["ready"] = true
puppet.set_properties(properties.duplicate())
current_map_instance.add_child(puppet)
func spawn_puppet_onready(properties):
var puppet = player_model.instantiate()
properties["ready"] = true
puppet.set_properties(properties.duplicate())
@ -471,6 +274,8 @@ func spawn_puppet(properties):
@rpc("authority", "reliable", "call_remote")
func despawn_puppet(internal_id):
if (current_map_instance == null):
return
var puppet = current_map_instance.get_node("player" + str(internal_id))
current_map_instance.remove_child(puppet)
@ -541,6 +346,9 @@ func _Connection_Succseeded():
choose_team_hud = preload("res://scenes/HUD/choose_team.tscn").instantiate()
current_map_instance.add_child(choose_team_hud)
for puppet in puppets_to_spawn:
spawn_puppet_onready(puppet)
func _Server_Disconnected():
print("Server has disconnected")

View File

@ -27,7 +27,7 @@ var properties = {
internal_id = 0,
nickname = "Unnamed",
ready = false,
current_weapon = null, #game_settings["weapons"]["knife"].duplicate(),
current_weapon = null,
current_weapon_number = 0,
last_shot = 0,
reloading = false,
@ -49,16 +49,31 @@ var client_settings
var can_shoot = true
var time_since_last_shot = 0
var round_status = {
"cs_round_score" = 0,
"os_round_score" = 0,
"os_game_score" = 0,
"cs_game_score" = 0,
"round_number" = 0,
}
@onready var head = $Head
@onready var camera: Camera3D = $Head/Camera
@onready var playerCharacterBody = $"."
var HUD
var HUD
var healthLabel
var armorLabel
var ammoLabel
var magazineLabel
var statusLabel
var csScoreRoundLabel
var csScoreGameLabel
var osScoreRoundLabel
var osScoreGameLabel
var roundNumberLabel
var timeLabel
var winnerLabel
func set_properties(props):
properties = props
@ -72,6 +87,24 @@ func set_property(key, value):
properties[key] = value
update_state()
func init_hud():
HUD = $HUD
healthLabel = $"HUD/health_and_ammo_display/healthdisplay/text"
armorLabel = $"HUD/health_and_ammo_display/armordisplay/text"
ammoLabel = $"HUD/health_and_ammo_display/ammodisplay/text"
magazineLabel = $"HUD/health_and_ammo_display/magazinedisplay/text"
statusLabel = $"HUD/Status"
csScoreRoundLabel = $"HUD/round_status/cs_score_round"
csScoreGameLabel = $"HUD/round_status/cs_score_game"
osScoreRoundLabel = $"HUD/round_status/os_score_round"
osScoreGameLabel = $"HUD/round_status/os_score_game"
roundNumberLabel = $"HUD/round_status/round_number"
timeLabel = $"HUD/round_status/time"
winnerLabel = $"HUD/round_status/winner"
func update_hud():
healthLabel.text = str(properties["HP"])
armorLabel.text = str(properties["AP"])
@ -82,6 +115,13 @@ func update_hud():
else:
statusLabel.text = "Reloaded"
csScoreRoundLabel.text = str(round_status["cs_round_score"])
csScoreGameLabel.text = str(round_status["cs_game_score"])
osScoreRoundLabel.text = str(round_status["os_round_score"])
osScoreGameLabel.text = str(round_status["os_game_score"])
roundNumberLabel.text = "Round " + str(round_status["round_number"])
func change_weapon(new_weapon_number):
properties["reloading"] = false
var weapons = $"Head/Camera/Hand".get_children()
@ -108,20 +148,14 @@ func find_current_weapon_by_number(number):
func update_state():
camera.set_current(false)
$"Head/Nickname".text = properties["nickname"]
if (!properties["is_playable"]): return
camera.set_current(true)
if (HUD == null):
var hud = load("res://scenes/HUD/hud.tscn").instantiate()
add_child(hud)
HUD = $"HUD"
var healthAndAmmoDisplay = HUD.get_node("health_and_ammo_display")
healthLabel = healthAndAmmoDisplay.get_node("healthdisplay/text")
armorLabel = healthAndAmmoDisplay.get_node("armordisplay/text")
ammoLabel = healthAndAmmoDisplay.get_node("ammodisplay/text")
magazineLabel = healthAndAmmoDisplay.get_node("magazinedisplay/text")
statusLabel = HUD.get_node("Status")
init_hud()
update_hud()
playerCharacterBody.up_direction = Vector3.UP;
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
@ -167,7 +201,8 @@ func reload():
current_weapon_instance["magazine"] += current_weapon_instance["ammo"]
current_weapon_instance["ammo"] = 0
properties["reloading"] = false
update_hud()
if (HUD != null):
update_hud()
func _unhandled_input(event):
if (!properties["is_playable"]): return
@ -189,6 +224,10 @@ func _unhandled_input(event):
camera.rotation.x = clamp(camera.rotation.x, deg_to_rad(-50), deg_to_rad(60))
func _physics_process(delta):
#var collision_shapes = find_children("collision*","",false)
#print(str(collision_shapes))
#for shape:CollisionShape3D in collision_shapes:
#shape.rotation = rotation
if (!properties["is_playable"]): return
if (game_settings == null): return
if (multiplayer.multiplayer_peer == null):
@ -197,7 +236,9 @@ func _physics_process(delta):
if Input.is_action_pressed("shoot"):
try_shoot()
update_hud()
if (HUD != null):
update_hud()
update_weapon_raycast()
if Input.is_action_just_pressed("reload"):
@ -280,6 +321,22 @@ func change_weapon_puppet(i_id, new_weapon_number):
if (int(i_id) == properties["internal_id"]):
change_weapon(new_weapon_number)
@rpc("authority", "call_remote", "reliable")
func update_round_status(s):
print("Updated round status: " + str(s))
round_status = s
if(HUD != null):
update_hud()
@rpc("authority", "call_remote", "reliable")
func end_round(result):
print("Result: %s" % str(result))
winnerLabel.visible = true
if (result > 0):
winnerLabel.text = "OS WON"
elif (result < 0 ):
winnerLabel.text = "CS WON"
await get_tree().create_timer(1).timeout
winnerLabel.visible = false
winnerLabel.text = ""

View File

@ -9,7 +9,6 @@ func _ready():
button.pressed.connect(self._button_pressed)
func _button_pressed():
var team
match name:
"Select_CS":
choose_class_cs.visible = true

40
scripts/utils/NetUtils.gd Normal file
View File

@ -0,0 +1,40 @@
extends Node
func send_everyone(args):
for current_client_id in Networking.clients.keys():
if (args.size() == 1):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0])
elif (args.size() == 2):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1])
elif (args.size() == 3):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1], args[2])
else:
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1], args[2], args[3])
func send_everyone_except(client_id, args):
if (typeof(args[0]) == 4): #string
for current_client_id in Networking.clients.keys():
if (str(current_client_id) == str(client_id)): continue
if (args.size() == 1):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0])
elif (args.size() == 2):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1])
elif (args.size() == 3):
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1], args[2])
else:
var playermodel = ServerUtils.find_playermodel_by_internal_id(Networking.clients[current_client_id]["internal_id"])
playermodel.rpc_id(int(current_client_id), args[0], args[1], args[2], args[3])
else:
for current_client_id in Networking.clients.keys():
if (str(current_client_id) == str(client_id)): continue
if (args.size() == 1): args[0].rpc_id(int(current_client_id))
elif (args.size() == 2): args[0].rpc_id(int(current_client_id), args[1])
elif (args.size() == 3): args[0].rpc_id(int(current_client_id), args[1], args[2])
else: args[0].rpc_id(int(current_client_id), args[1], args[2], args[3])

View File

@ -0,0 +1,214 @@
extends Node
var team_CS = {
"spawnpoints": [],
"members": [],
"round_score": 0,
"game_score": 0
}
var team_OS = {
"spawnpoints": [],
"members": [],
"round_score": 0,
"game_score": 0
}
var round_number = 0
var gamemode
var map_path
var map_root_name
var server_map
func find_class_type_by_number(number):
var found_class
var classtypes = GameData.server_settings["game"]["classTypes"]
for classtype in classtypes:
if classtypes[classtype]["number"] == number:
found_class = classtypes[classtype].duplicate()
break
return found_class
func check_map_availability(path):
var maps = DirAccess.open("res://scenes/maps").get_files()
var map_name = (path.split("/")[-1]).split(".")[0]
for map in maps:
var checking_map_name = str(map.split(".")[0])
if(checking_map_name == map_name):
return true
return false
func check_gamemode_availability(gm):
var gamemodes = GameData.server_settings["game"]["gamemodes"].keys()
for g in gamemodes:
if gm == g:
return true
return false
func find_weapon_by_number(number):
var found_weapon
for weapon in GameData.server_settings["game"]["weapons"].keys():
if (GameData.server_settings["game"]["weapons"][weapon]["number"] == number):
found_weapon = GameData.server_settings["game"]["weapons"][weapon].duplicate()
break
return found_weapon
func find_playermodel_by_internal_id(internal_id):
return server_map.get_node("player" + str(internal_id))
func reloading_complete(client_id, reloading_time):
await get_tree().create_timer(reloading_time).timeout
var client = Networking.clients[client_id]
if (!client["reloading"]): # if a client has interrupted the reloading
return
var weapons_list = GameData.server_settings["game"]["weapons"]
var current_client_weapon = client["current_weapon"]
var current_weapon_example = weapons_list.find_key(ServerUtils.find_weapon_by_number(current_client_weapon["number"]))
var current_weapon_settings = weapons_list[current_weapon_example]
var to_reload = current_weapon_settings["magazine"] - current_client_weapon["magazine"]
if (to_reload <= current_client_weapon["ammo"]):
current_client_weapon["magazine"] += to_reload
current_client_weapon["ammo"] -= to_reload
else:
current_client_weapon["magazine"] += current_client_weapon["ammo"]
current_client_weapon["ammo"] = 0
func choose_collision_shape(target, shape_num):
var collision_shapes:Array = []
for s in target.get_children():
if s is CollisionShape3D:
collision_shapes.push_back(s)
var shape
for i in range(0, collision_shapes.size()):
if i == shape_num:
shape = collision_shapes[i]
break
return shape
func new_round():
round_number += 1
team_OS["round_score"] = 0
team_CS["round_score"] = 0
print("CS members " + str(team_CS["members"]))
print("OS members " + str(team_OS["members"]))
for member in team_CS["members"]:
member["position"] = team_CS["spawnpoints"].pick_random().get_class_spawnpoint(abs(member["class_type"]))
ServerUtils.find_playermodel_by_internal_id(member["internal_id"]).teleport.rpc_id(Networking.clients.find_key(member), member["position"])
for member in team_OS["members"]:
member["position"] = team_OS["spawnpoints"].pick_random().get_class_spawnpoint(abs(member["class_type"]))
ServerUtils.find_playermodel_by_internal_id(member["internal_id"]).teleport.rpc_id(Networking.clients.find_key(member), member["position"])
send_scores()
func new_game(new_map_path, new_gamemode):
team_OS["game_score"] = 0
team_OS["round_score"] = 0
team_CS["game_score"] = 0
team_CS["round_score"] = 0
round_number = 0
send_scores()
new_map_path = map_path if (new_map_path == null) else new_map_path
new_gamemode = gamemode if (new_gamemode == null) else new_gamemode
await switch_map(new_map_path)
await switch_gamemode(new_gamemode)
func check_gamemode_end_conditions():
match gamemode:
"TDM":
var kills_amount_to_win = GameData.server_settings["game"]["gamemodes"]["TDM"]["kills"]
if team_OS["round_score"] >= kills_amount_to_win:
team_OS["game_score"] += 1
print("OS won")
NetUtils.send_everyone(["end_round", 1]) # 1 = os is win
new_round()
elif team_CS["round_score"] >= kills_amount_to_win:
team_CS["game_score"] += 1
NetUtils.send_everyone(["end_round", -1]) # -1 = cs is win
print("CS won")
new_round()
send_scores()
func switch_map(new_map_path):
print("Switching map to %s" % new_map_path)
if (not ServerUtils.check_map_availability(new_map_path)):
var default_map = GameData.server_settings["defaults"]["map"]
print("Error. No map found. Loading default map %s" % default_map)
new_map_path = "res://scenes/maps/%s.tscn" % default_map
if (not ServerUtils.check_map_availability(new_map_path)):
print("Error. Default map is not valid. Please, specify a valid map in a config file.")
return
map_path = new_map_path
get_tree().change_scene_to_file(map_path)
await get_tree().create_timer(0.1).timeout #I know that this isn't a good practice, but I didn't find anything better
map_root_name = (map_path.split("/")[-1]).split(".")[0]
server_map = get_tree().root.get_node(map_root_name)
var spawnpoints = server_map.find_children("spawnpoint*", "" ,true)
team_OS["spawnpoints"] = []
team_CS["spawnpoints"] = []
for spawnpoint in spawnpoints:
if spawnpoint.team == 0: # cs
team_CS["spawnpoints"].push_back(spawnpoint)
elif spawnpoint.team > 0: # os
team_OS["spawnpoints"].push_back(spawnpoint)
func send_scores():
NetUtils.send_everyone(["update_round_status", {
"cs_round_score" = team_CS["round_score"],
"os_round_score" = team_OS["round_score"],
"os_game_score" = team_OS["game_score"],
"cs_game_score" = team_CS["game_score"],
"round_number" = round_number,
}])
func switch_gamemode(new_gamemode):
if not ServerUtils.check_gamemode_availability(new_gamemode):
print("No gamemode found")
return
gamemode = new_gamemode
func parse_arguments():
var arguments = {}
for argument in OS.get_cmdline_args():
if argument.find("=") > -1:
var key_value = argument.split("=")
arguments[key_value[0].lstrip("--")] = key_value[1]
else:
# Options without an argument will be present in the dictionary,
# with the value set to an empty string.
arguments[argument.lstrip("--")] = ""
return arguments
func setup_server():
var arguments = parse_arguments()
GameData.read_settings()
################ parsing map
var path = "res://scenes/maps/%s.tscn" % arguments["map"] if arguments.has("map") else "res://scenes/maps/%s.tscn" % GameData.server_settings["defaults"]["map"]
if (ServerUtils.check_map_availability(path)):
map_path = path
else:
print("Unknown map %s Available maps:" % path)
for map in DirAccess.open("res://scenes/maps").get_files():
print(str(map.split(".")[0]))
get_tree().quit()
return
################ parsing gamemode
var gm = str(arguments["gamemode"]) if (arguments.has("gamemode")) else "TDM"
if (ServerUtils.check_gamemode_availability(gm)):
print("Gamemode exists")
else:
print("No")
await new_game(map_path, gm)
var spectator = preload("res://scenes/models/spectator.tscn").instantiate()
server_map.add_child(spectator)
Networking.StartServer()
func _ready():
if "--server" in OS.get_cmdline_args():
setup_server()

View File

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cbf6w7ativli8"
path.s3tc="res://.godot/imported/knife_textures.png-bfa45f2fa32fc252fea8eb5aaf3203bc.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://textures/knife_textures.png"
dest_files=["res://.godot/imported/knife_textures.png-bfa45f2fa32fc252fea8eb5aaf3203bc.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
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=0

Binary file not shown.

Binary file not shown.