feat: added create game

pull/10/head
Евгений Сугоняко 2024-05-20 19:54:16 +03:00
parent 7b74ea4890
commit d87ef6d968
10 changed files with 491 additions and 27 deletions

114
data/scenes/Game/game.gd Normal file
View File

@ -0,0 +1,114 @@
extends Node
#--------------------------------------------------------------------------------------------------#
# Properties
var gameId : int
var ownerName : String
var gameName : String
var players : Array
var players_info : Dictionary
var maxPlayers : int
var gamePassword : String
var isStarted : bool
#--------------------------------------------------------------------------------------------------#
# Signals
signal game_info_changed
signal game_created
#--------------------------------------------------------------------------------------------------#
# Methods
func get_game_info():
return {
gameId = self.gameId,
ownerName = self.ownerName,
gameName = self.gameName,
players = self.players,
players_info = self.players_info,
maxPlayers = self.maxPlayers,
gamePassword = self.gamePassword,
isStarted = self.isStarted
}
func set_game_info(_gameSettings:Dictionary, isLocal:bool = true):
self.gameId = _gameSettings.gameId
self.ownerName = _gameSettings.ownerName
self.gameName = _gameSettings.gameName
self.maxPlayers = _gameSettings.maxPlayers
self.gamePassword = _gameSettings.gamePassword
self.name = str(_gameSettings.gameId)
self.isStarted = false
_emmit_game_info_changed()
if isLocal:
self.rpc_id(1, "rpc_game_info_changed", get_game_info())
func connect_player(_clientId:int):
self.rpc_id(1, "rpc_set_player", _clientId)
func disconnect_player(_clientId:int):
self.rpc_id(1, "rpc_unset_player", _clientId)
func added_player(_player:Dictionary):
players.push_back(_player.id)
players_info[_player.id] = {
'login' = _player.login,
'name' = _player.name
}
_emmit_game_info_changed()
func delete_player(_clientId:int):
players.erase(_clientId)
players_info.erase(_clientId)
_emmit_game_info_changed()
#--------------------------------------------------------------------------------------------------#
# Signals
func _on_game_created():
self.connect_player(GATEWAY.clientId)
#--------------------------------------------------------------------------------------------------#
# Signals emmit
func _emmit_game_info_changed():
self.game_info_changed.emit(self.get_game_info())
#---------------------------------------------------------------------------------------------------
# RPC Client
@rpc("authority", "call_local", "reliable", 3)
func rpc_change_game_info(_gameSettings:Dictionary):
set_game_info(_gameSettings, false)
@rpc("authority", "call_local", "reliable", 3)
func rpc_set_player_info(_player:Dictionary):
added_player(_player)
@rpc("authority", "call_local", "reliable", 3)
func rpc_unset_player_info(_clientId:int):
delete_player(_clientId)
#---------------------------------------------------------------------------------------------------
# RPC Server
@rpc("any_peer", "call_local", "reliable", 3)
func rpc_game_info_changed(_gameSettings:Dictionary): pass
@rpc("any_peer", "call_local", "reliable", 3)
func rpc_set_player(_clientId:int): pass
@rpc("any_peer", "call_local", "reliable", 3)
func rpc_unset_player(_clientId:int): pass

View File

@ -0,0 +1,8 @@
[gd_scene load_steps=2 format=3 uid="uid://u3ht16dhk3iq"]
[ext_resource type="Script" path="res://data/scenes/Game/game.gd" id="1_2bjjo"]
[node name="Game" type="Node"]
script = ExtResource("1_2bjjo")
[connection signal="game_created" from="." to="." method="_on_game_created"]

View File

@ -0,0 +1,38 @@
extends Panel
@export var CreateBtn : Button
@export var BackBtn : Button
@export var GameSettings : VBoxContainer
@export var GameName : LineEdit
@export var MaxPlayers : OptionButton
@export var Password : LineEdit
signal create_pushed
signal back_pushed
func _on_create_game_create_game_btn_button_up():
CreateBtn.disabled = true
BackBtn.disabled = true
GameSettings.visible = false
var Name = GameName.text
if Name == "":
Name = str(round(GATEWAY.clientId + Time.get_unix_time_from_system()))
var data : Dictionary = {
gameName = Name,
maxPlayers = MaxPlayers.get_item_text(MaxPlayers.get_selected_id()).to_int(),
gamePassword = Password.text
}
create_pushed.emit(data)
func _on_create_game_back_btn_button_up():
back_pushed.emit()
func _on_back_pushed():
CreateBtn.disabled = false
BackBtn.disabled = false
GameSettings.visible = true

View File

@ -0,0 +1,147 @@
[gd_scene load_steps=3 format=3 uid="uid://viv2ljgyvg5m"]
[ext_resource type="Script" path="res://data/scenes/HELPERS/PopUps/game_panel.gd" id="1_0qnm0"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5v3b7"]
content_margin_left = 5.0
content_margin_top = 5.0
content_margin_right = 5.0
content_margin_bottom = 5.0
bg_color = Color(0.133196, 0.133196, 0.133196, 1)
border_width_left = 3
border_width_top = 3
border_width_right = 3
border_width_bottom = 3
border_color = Color(0.707602, 0.575264, 0, 1)
border_blend = true
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
expand_margin_left = 5.0
expand_margin_top = 5.0
expand_margin_right = 5.0
expand_margin_bottom = 5.0
[node name="GamePanel" type="Panel" node_paths=PackedStringArray("CreateBtn", "BackBtn", "GameSettings", "GameName", "MaxPlayers", "Password")]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_5v3b7")
script = ExtResource("1_0qnm0")
CreateBtn = NodePath("MarginContainer/GameVBoxContainer/GameButtonContainer/CreateGame_CreateGameBtn")
BackBtn = NodePath("MarginContainer/GameVBoxContainer/GameButtonContainer/CreateGame_BackBtn")
GameSettings = NodePath("MarginContainer/GameVBoxContainer/Game_SettingsContainer")
GameName = NodePath("MarginContainer/GameVBoxContainer/Game_SettingsContainer/GameNameBox/GameName")
MaxPlayers = NodePath("MarginContainer/GameVBoxContainer/Game_SettingsContainer/MaxPlayersBox/OptionButton")
Password = NodePath("MarginContainer/GameVBoxContainer/Game_SettingsContainer/PasswordBox/Password")
[node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/margin_left = 10
theme_override_constants/margin_top = 10
theme_override_constants/margin_right = 10
theme_override_constants/margin_bottom = 10
[node name="GameVBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="Game_Title" type="Label" parent="MarginContainer/GameVBoxContainer"]
layout_mode = 2
theme_override_colors/font_color = Color(0.707602, 0.575264, 0, 1)
text = "$CreateGame"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Game_SettingsContainer" type="VBoxContainer" parent="MarginContainer/GameVBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
[node name="GameNameBox" type="HBoxContainer" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer"]
layout_mode = 2
theme_override_constants/separation = 20
[node name="GameNameLabel" type="Label" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/GameNameBox"]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
text = "$GameName"
[node name="GameName" type="LineEdit" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/GameNameBox"]
layout_mode = 2
size_flags_horizontal = 3
alignment = 2
[node name="MaxPlayersBox" type="HBoxContainer" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer"]
layout_mode = 2
theme_override_constants/separation = 20
[node name="MaxPlayersLabel" type="Label" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/MaxPlayersBox"]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
text = "$MaxPlayers"
[node name="OptionButton" type="OptionButton" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/MaxPlayersBox"]
layout_mode = 2
size_flags_horizontal = 0
alignment = 1
item_count = 7
selected = 0
popup/item_0/text = "2"
popup/item_0/id = 0
popup/item_1/text = "3"
popup/item_1/id = 1
popup/item_2/text = "4"
popup/item_2/id = 2
popup/item_3/text = "5"
popup/item_3/id = 3
popup/item_4/text = "6"
popup/item_4/id = 4
popup/item_5/text = "7"
popup/item_5/id = 5
popup/item_6/text = "8"
popup/item_6/id = 6
[node name="PasswordBox" type="HBoxContainer" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer"]
layout_mode = 2
theme_override_constants/separation = 20
[node name="PasswordLabel" type="Label" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/PasswordBox"]
custom_minimum_size = Vector2(200, 0)
layout_mode = 2
text = "$Password"
[node name="Password" type="LineEdit" parent="MarginContainer/GameVBoxContainer/Game_SettingsContainer/PasswordBox"]
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "$leave_empty_for_open_game"
alignment = 1
secret = true
[node name="GameButtonContainer" type="HBoxContainer" parent="MarginContainer/GameVBoxContainer"]
layout_mode = 2
size_flags_vertical = 10
theme_override_constants/separation = 10
[node name="CreateGame_CreateGameBtn" type="Button" parent="MarginContainer/GameVBoxContainer/GameButtonContainer"]
layout_mode = 2
size_flags_horizontal = 2
text = "$CreateGame"
[node name="CreateGame_BackBtn" type="Button" parent="MarginContainer/GameVBoxContainer/GameButtonContainer"]
layout_mode = 2
size_flags_horizontal = 10
text = "$Back"
[connection signal="back_pushed" from="." to="." method="_on_back_pushed"]
[connection signal="button_up" from="MarginContainer/GameVBoxContainer/GameButtonContainer/CreateGame_CreateGameBtn" to="." method="_on_create_game_create_game_btn_button_up"]
[connection signal="button_up" from="MarginContainer/GameVBoxContainer/GameButtonContainer/CreateGame_BackBtn" to="." method="_on_create_game_back_btn_button_up"]

View File

@ -0,0 +1,17 @@
extends PopupPanel
@export var Title : Label
@export var Message : Label
signal user_push_ok
func _on_pop_up_button_button_up():
self.visible = false
self.user_push_ok.emit()
func _on_popup_hide():
self.visible = false
self.user_push_ok.emit()

View File

@ -0,0 +1,85 @@
[gd_scene load_steps=4 format=3 uid="uid://q87efncnaafy"]
[ext_resource type="Script" path="res://data/scenes/HELPERS/PopUps/popup_error.gd" id="1_2waig"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_8hj2h"]
bg_color = Color(0.129558, 0.129559, 0.129558, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.244776, 0.244776, 0.244776, 1)
border_blend = true
corner_radius_top_left = 3
corner_radius_top_right = 3
corner_radius_bottom_right = 3
corner_radius_bottom_left = 3
expand_margin_left = 5.0
expand_margin_top = 5.0
expand_margin_right = 5.0
expand_margin_bottom = 5.0
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_roii6"]
content_margin_left = 5.0
content_margin_top = 5.0
content_margin_right = 5.0
content_margin_bottom = 5.0
bg_color = Color(0.215902, 0.215902, 0.215902, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
expand_margin_left = 5.0
expand_margin_top = 5.0
expand_margin_right = 5.0
expand_margin_bottom = 5.0
[node name="PopupError" type="PopupPanel" node_paths=PackedStringArray("Title", "Message")]
disable_3d = true
title = "$game_not_created"
initial_position = 3
size = Vector2i(218, 106)
current_screen = 0
visible = true
always_on_top = true
keep_title_visible = true
script = ExtResource("1_2waig")
Title = NodePath("MarginContainer/VBoxContainer/Title")
Message = NodePath("MarginContainer/VBoxContainer/Message")
[node name="MarginContainer" type="MarginContainer" parent="."]
offset_left = 4.0
offset_top = 4.0
offset_right = 214.0
offset_bottom = 102.0
theme_override_constants/margin_left = 5
theme_override_constants/margin_top = 5
theme_override_constants/margin_right = 5
theme_override_constants/margin_bottom = 5
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
layout_mode = 2
[node name="Title" type="Label" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 2
theme_override_styles/normal = SubResource("StyleBoxFlat_8hj2h")
text = "$game_not_created"
horizontal_alignment = 1
[node name="Message" type="Label" parent="MarginContainer/VBoxContainer"]
custom_minimum_size = Vector2(200, 30)
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/normal = SubResource("StyleBoxFlat_roii6")
text = "Message"
horizontal_alignment = 1
vertical_alignment = 1
autowrap_mode = 3
[node name="PopUpButton" type="Button" parent="MarginContainer/VBoxContainer"]
layout_mode = 2
text = "OK"
[connection signal="popup_hide" from="." to="." method="_on_popup_hide"]
[connection signal="button_up" from="MarginContainer/VBoxContainer/PopUpButton" to="." method="_on_pop_up_button_button_up"]

View File

@ -8,10 +8,7 @@ var players : Array
var maxPlayers : int
var gamePassword : String
func connect_player(_client_id):
if players.size() < maxPlayers:
players.push_back(_client_id)
var isStarted : bool
func set_game_data(_data:Dictionary):
@ -21,6 +18,7 @@ func set_game_data(_data:Dictionary):
self.maxPlayers = _data.maxPlayers
self.gamePassword = _data.gamePassword
self.name = str(_data.gameId)
self.isStarted = _data.isStarted
self.text = "%s | %s | %s | " % [_data.gameName, _data.ownerName, _data.maxPlayers]
if _data.gamePassword != "":
self.text += "PASSWORD"
@ -34,5 +32,6 @@ func get_game_data() -> Dictionary:
ownerName = self.ownerName,
gameName = self.gameName,
maxPlayers = self.maxPlayers,
gamePassword = self.gamePassword
gamePassword = self.gamePassword,
isStarted = self.isStarted
}

View File

@ -3,6 +3,9 @@ extends Node
@export var GameBox : VBoxContainer
@export var SearchLine : LineEdit
@export var PopUpError : PopupPanel
@export var LobbieUI : Control
@export var GamePanel : Panel
func _ready():
@ -20,6 +23,33 @@ func _on_search_button_button_up():
rpc_id(1, "rpc_get_game", SearchLine.text)
func _on_create_game_button_up():
GamePanel.visible = true
func _on_popup_error_user_push_ok():
LobbieUI.visible = true
GamePanel.emit_signal("back_pushed")
func _on_game_panel_back_pushed():
GamePanel.visible = false
func _on_game_panel_create_pushed(_data):
var gameData : Dictionary = {
gameId = int(GATEWAY.clientId + Time.get_unix_time_from_system()),
ownerName = GATEWAY._get_player(GATEWAY.clientId).playerName,
players = Array(),
players_info = Dictionary(),
gameName = _data.gameName,
maxPlayers = _data.maxPlayers,
gamePassword = _data.gamePassword,
isStarted = false
}
create_game(gameData)
#---------------------------------------------------------------------------------------------------
# RPC Client
@rpc("authority", "call_local", "unreliable", 2)
@ -39,16 +69,20 @@ func rpc_set_games_list(_games:Array):
@rpc("authority", "call_local", "unreliable", 2)
func rpc_add_game_to_games_list(_game:Dictionary):
var gameLabel = preload("res://data/scenes/lobbies/GameLabel.tscn").instantiate()
gameLabel.set_game_data(_game)
GameBox.add_child(gameLabel)
func rpc_game_created(_game:Dictionary):
var game_instance = preload("res://data/scenes/Game/game.tscn").instantiate()
game_instance.set_game_info(_game, false)
get_tree().root.add_child(game_instance)
get_node("/root/%s" % [_game.gameId]).emit_signal("game_created")
if GATEWAY.debug:
print("Added game to games list")
print("Created new game")
get_node("/root/Lobbies").queue_free()
@rpc("authority", "call_local", "unreliable", 2)
func rpc_cant_create_game():
func rpc_cant_create_game(_message : String):
PopUpError.visible = true
PopUpError.Message.text = _message
if GATEWAY.debug:
print("Can`t create game")
@ -64,4 +98,4 @@ func rpc_get_games_list(): pass
@rpc("any_peer", "call_local", "unreliable", 2)
func rpc_get_game(_name): pass
func rpc_get_game(_name:String): pass

View File

@ -1,8 +1,10 @@
[gd_scene load_steps=6 format=3 uid="uid://d4nhi3k0agm2q"]
[gd_scene load_steps=8 format=3 uid="uid://d4nhi3k0agm2q"]
[ext_resource type="FontFile" uid="uid://dhvfket83gjln" path="res://data/styles/fonts/Roboto-Regular.ttf" id="1_qbt18"]
[ext_resource type="Script" path="res://data/scenes/lobbies/GamesSinhronizer.gd" id="2_a6k32"]
[ext_resource type="Script" path="res://data/scenes/lobbies/ChatSinhronizer.gd" id="2_cc8va"]
[ext_resource type="PackedScene" uid="uid://q87efncnaafy" path="res://data/scenes/HELPERS/PopUps/popup_error.tscn" id="3_pxlwg"]
[ext_resource type="PackedScene" uid="uid://viv2ljgyvg5m" path="res://data/scenes/HELPERS/PopUps/game_panel.tscn" id="5_quxq3"]
[sub_resource type="GDScript" id="GDScript_2o8xy"]
script/source = "extends LineEdit
@ -36,14 +38,29 @@ func _server_disconnect():
[node name="Lobbies" type="Node"]
[node name="GamesSinhronizer" type="Node" parent="." node_paths=PackedStringArray("GameBox", "SearchLine", "PopUpError", "LobbieUI", "GamePanel")]
script = ExtResource("2_a6k32")
GameBox = NodePath("../LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GamesBackground/GamesMarginContainer/GamesContainer/GamesScroll/GamesBox")
SearchLine = NodePath("../LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GamesBackground/GamesMarginContainer/GamesContainer/Search/GameSearch")
PopUpError = NodePath("../PopupError")
LobbieUI = NodePath("../LobbieUI")
GamePanel = NodePath("../LobbieUI/MainMarginContainer/GamePanel")
[node name="ChatSinhronizer" type="Node" parent="." node_paths=PackedStringArray("GlobalChat")]
script = ExtResource("2_cc8va")
GlobalChat = NodePath("../LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GlobalChatBackground/GlobalChatMarginContainer/GlobalChatContainer/Panel/GlobalChat")
[node name="GamesSinhronizer" type="Node" parent="." node_paths=PackedStringArray("GameBox", "SearchLine")]
script = ExtResource("2_a6k32")
GameBox = NodePath("../LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GamesBackground/GamesMarginContainer/GamesContainer/GamesScroll/GamesBox")
SearchLine = NodePath("../LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GamesBackground/GamesMarginContainer/GamesContainer/Search/GameSearch")
[node name="PopupError" parent="." instance=ExtResource("3_pxlwg")]
visible = false
keep_title_visible = false
[node name="Background" type="ColorRect" parent="."]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.125911, 0.125911, 0.125911, 1)
[node name="LobbieUI" type="Control" parent="."]
layout_mode = 3
@ -53,15 +70,6 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="Background" type="ColorRect" parent="LobbieUI"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.125911, 0.125911, 0.125911, 1)
[node name="MainMarginContainer" type="MarginContainer" parent="LobbieUI"]
layout_mode = 1
anchors_preset = 15
@ -212,5 +220,13 @@ theme_override_font_sizes/font_size = 15
text = "$Back"
script = SubResource("GDScript_4mwjp")
[node name="GamePanel" parent="LobbieUI/MainMarginContainer" instance=ExtResource("5_quxq3")]
visible = false
layout_mode = 2
[connection signal="user_push_ok" from="PopupError" to="GamesSinhronizer" method="_on_popup_error_user_push_ok"]
[connection signal="button_up" from="LobbieUI/MainMarginContainer/MainUIContainer/MainContainer/GamesBackground/GamesMarginContainer/GamesContainer/Search/SearchButton" to="GamesSinhronizer" method="_on_search_button_button_up"]
[connection signal="button_up" from="LobbieUI/MainMarginContainer/MainUIContainer/ButtonsContainer/CreateGame" to="GamesSinhronizer" method="_on_create_game_button_up"]
[connection signal="button_up" from="LobbieUI/MainMarginContainer/MainUIContainer/ButtonsContainer/Back" to="LobbieUI/MainMarginContainer/MainUIContainer/ButtonsContainer/Back" method="_on_button_up"]
[connection signal="back_pushed" from="LobbieUI/MainMarginContainer/GamePanel" to="GamesSinhronizer" method="_on_game_panel_back_pushed"]
[connection signal="create_pushed" from="LobbieUI/MainMarginContainer/GamePanel" to="GamesSinhronizer" method="_on_game_panel_create_pushed"]

View File

@ -24,4 +24,10 @@ $GlobalChat,Global chat,Глобальний чат,Общий чат
$your_message,Your message here (Enter),Ваше повідомлення (Enter),Ваше сообщение (Enter)
$CreateGame,Create game,Створити гру,Создать игру
$search_game,Searched game name),Ім`я гри для пошуку,Название игры для поиска
$Search,Search,Пошук,Поиск
$Search,Search,Пошук,Поиск
$game_not_created,Game not created,Гра не створена,Игра не создана
$only_one_game_for_one_player,Another game has already been created - Only one game can be created,Інша гра вже створена - Можна створити тільки одну гру,Другая игра уже создана - Можно создать только одну игру
$data_base_error,Data base error,Помилка бази даних,Ошибка базы данных
$GameName,Game name,Назва гри,Название игры
$MaxPlayers,Max players,Макс.гравців,Макс.игроков
$leave_empty_for_open_game,Leave blank for open play,Залиште поле порожнім для відкритої гри,Оставьте поле пустым для открытой игры
1 KEYS en uk ru
24 $your_message Your message here (Enter) Ваше повідомлення (Enter) Ваше сообщение (Enter)
25 $CreateGame Create game Створити гру Создать игру
26 $search_game Searched game name) Ім`я гри для пошуку Название игры для поиска
27 $Search Search Пошук Поиск
28 $game_not_created Game not created Гра не створена Игра не создана
29 $only_one_game_for_one_player Another game has already been created - Only one game can be created Інша гра вже створена - Можна створити тільки одну гру Другая игра уже создана - Можно создать только одну игру
30 $data_base_error Data base error Помилка бази даних Ошибка базы данных
31 $GameName Game name Назва гри Название игры
32 $MaxPlayers Max players Макс.гравців Макс.игроков
33 $leave_empty_for_open_game Leave blank for open play Залиште поле порожнім для відкритої гри Оставьте поле пустым для открытой игры