Add players page and host moderation
This commit is contained in:
parent
fa996a6735
commit
141b54261d
23 changed files with 1166 additions and 31 deletions
|
|
@ -187,12 +187,19 @@ func _on_message(message: Dictionary) -> void:
|
|||
_speech[peer_id] = {
|
||||
"label": label,
|
||||
"expires": Time.get_ticks_msec() / 1000.0 + SPEECH_SECONDS,
|
||||
"fingerprint": str(message.get("sender_fingerprint", "")),
|
||||
}
|
||||
|
||||
|
||||
func _on_history(_messages: Array) -> void:
|
||||
if _messages.is_empty():
|
||||
for peer_id: int in _speech.keys():
|
||||
for peer_id: int in _speech.keys():
|
||||
var state: Dictionary = _speech[peer_id]
|
||||
if (
|
||||
_messages.is_empty()
|
||||
or _service.is_sender_filtered(
|
||||
str(state.get("fingerprint", ""))
|
||||
)
|
||||
):
|
||||
_on_peer_removed(peer_id)
|
||||
_refresh_history()
|
||||
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ func setup(
|
|||
network_mail_service: NetworkMailService,
|
||||
reservations: PlayerAssetReservationService,
|
||||
network_profile_service: NetworkProfileService,
|
||||
network_player_list: NetworkPlayerListService,
|
||||
) -> void:
|
||||
_fishing_spot = fishing_spot
|
||||
_item_effects = item_effects
|
||||
|
|
@ -155,7 +156,8 @@ func setup(
|
|||
network_sale_service,
|
||||
network_mail_service,
|
||||
reservations,
|
||||
network_profile_service
|
||||
network_profile_service,
|
||||
network_player_list,
|
||||
)
|
||||
_hotbar_ui.setup(hotbar, bag, item_catalog, fishing_spot)
|
||||
_fishing_shop.setup(
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ enum Section {
|
|||
LOGBOOK,
|
||||
MAIL,
|
||||
PROFILE,
|
||||
PLAYERS,
|
||||
}
|
||||
|
||||
enum SortMode {
|
||||
|
|
@ -158,6 +159,7 @@ enum CloseReason {
|
|||
@onready var _logbook_page: Control = %LogbookPage
|
||||
@onready var _mail_page: MailPage = %MailPage
|
||||
@onready var _profile_page: ProfilePage = %ProfilePage
|
||||
@onready var _players_page: PlayersPage = %PlayersPage
|
||||
@onready var _book_backing: PanelContainer = %BookBacking
|
||||
@onready var _book_spread: BoxContainer = %BookSpread
|
||||
@onready var _left_page: PanelContainer = %LeftPage
|
||||
|
|
@ -176,6 +178,7 @@ enum CloseReason {
|
|||
@onready var _logbook_tab: BubbleButtonType = %LogbookTab
|
||||
@onready var _mail_tab: BubbleButtonType = %MailTab
|
||||
@onready var _profile_tab: BubbleButtonType = %ProfileTab
|
||||
@onready var _players_tab: BubbleButtonType = %PlayersTab
|
||||
@onready var _mail_unread_badge: Label = %MailUnreadBadge
|
||||
@onready var _close_button: BubbleButtonType = %CloseButton
|
||||
@onready var _content_shell: BubbleContentShellType = %MenuPanel
|
||||
|
|
@ -237,6 +240,7 @@ var _network_session: NetworkSessionType
|
|||
var _network_sale_service: NetworkSaleService
|
||||
var _network_mail_service: NetworkMailService
|
||||
var _network_profile_service: NetworkProfileService
|
||||
var _network_player_list: NetworkPlayerListService
|
||||
var _default_buyer: FishBuyerProfileType
|
||||
var _catalog: FishPoolType
|
||||
var _fishing_spot: FishingSpotType
|
||||
|
|
@ -300,6 +304,7 @@ func _ready() -> void:
|
|||
)
|
||||
_mail_tab.pressed.connect(_show_section.bind(Section.MAIL))
|
||||
_profile_tab.pressed.connect(_show_section.bind(Section.PROFILE))
|
||||
_players_tab.pressed.connect(_show_section.bind(Section.PLAYERS))
|
||||
_close_button.pressed.connect(close_menu)
|
||||
_sort_option.item_selected.connect(_on_sort_selected.bind(_sort_option))
|
||||
_sort_direction.pressed.connect(_on_sort_direction_pressed)
|
||||
|
|
@ -327,6 +332,7 @@ func _ready() -> void:
|
|||
_logbook_tab,
|
||||
_mail_tab,
|
||||
_profile_tab,
|
||||
_players_tab,
|
||||
_close_button,
|
||||
])
|
||||
_configure_navigation_focus()
|
||||
|
|
@ -376,6 +382,7 @@ func setup(
|
|||
network_mail_service: NetworkMailService,
|
||||
reservations: PlayerAssetReservationService,
|
||||
network_profile_service: NetworkProfileService,
|
||||
network_player_list: NetworkPlayerListService,
|
||||
) -> void:
|
||||
_player = player
|
||||
_inventory = inventory
|
||||
|
|
@ -393,10 +400,12 @@ func setup(
|
|||
_network_sale_service = network_sale_service
|
||||
_network_mail_service = network_mail_service
|
||||
_network_profile_service = network_profile_service
|
||||
_network_player_list = network_player_list
|
||||
_mail_page.setup(
|
||||
network_mail_service, reservations, inventory, wallet, bag, item_catalog
|
||||
)
|
||||
_profile_page.setup(network_profile_service)
|
||||
_players_page.setup(network_player_list)
|
||||
_network_mail_service.unread_count_changed.connect(
|
||||
_on_mail_unread_count_changed
|
||||
)
|
||||
|
|
@ -608,6 +617,7 @@ func _show_section_immediate(section: Section) -> void:
|
|||
_logbook_page.visible = section == Section.LOGBOOK
|
||||
_mail_page.visible = section == Section.MAIL
|
||||
_profile_page.visible = section == Section.PROFILE
|
||||
_players_page.visible = section == Section.PLAYERS
|
||||
_content_shell.visible = false
|
||||
_inventory_section.visible = false
|
||||
_bag_section.visible = false
|
||||
|
|
@ -634,11 +644,16 @@ func _show_section_immediate(section: Section) -> void:
|
|||
_profile_page.activate()
|
||||
else:
|
||||
_profile_page.deactivate()
|
||||
if section == Section.PLAYERS:
|
||||
_players_page.activate()
|
||||
else:
|
||||
_players_page.deactivate()
|
||||
_inventory_tab.button_pressed = section == Section.COOLER
|
||||
_bag_tab.button_pressed = section == Section.BAG
|
||||
_logbook_tab.button_pressed = section == Section.LOGBOOK
|
||||
_mail_tab.button_pressed = section == Section.MAIL
|
||||
_profile_tab.button_pressed = section == Section.PROFILE
|
||||
_players_tab.button_pressed = section == Section.PLAYERS
|
||||
_update_navigation_selection()
|
||||
_configure_active_page_focus()
|
||||
|
||||
|
|
@ -652,6 +667,8 @@ func _focus_current_section() -> void:
|
|||
_logbook_tab.grab_focus()
|
||||
elif _current_section == Section.MAIL:
|
||||
_mail_tab.grab_focus()
|
||||
elif _current_section == Section.PLAYERS:
|
||||
_players_tab.grab_focus()
|
||||
else:
|
||||
_profile_tab.grab_focus()
|
||||
|
||||
|
|
@ -682,6 +699,7 @@ func _configure_navigation_focus() -> void:
|
|||
_logbook_tab,
|
||||
_mail_tab,
|
||||
_profile_tab,
|
||||
_players_tab,
|
||||
_close_button,
|
||||
]
|
||||
for index: int in navigation.size():
|
||||
|
|
@ -835,6 +853,7 @@ func _apply_navigation_styles() -> void:
|
|||
_logbook_tab,
|
||||
_mail_tab,
|
||||
_profile_tab,
|
||||
_players_tab,
|
||||
_close_button,
|
||||
]:
|
||||
bubble.add_theme_stylebox_override("normal", normal)
|
||||
|
|
@ -866,6 +885,7 @@ func _apply_navigation_selection_presentation() -> void:
|
|||
_logbook_tab,
|
||||
_mail_tab,
|
||||
_profile_tab,
|
||||
_players_tab,
|
||||
]:
|
||||
if not bubble.button_pressed:
|
||||
continue
|
||||
|
|
@ -975,6 +995,7 @@ func _set_navigation_target(section: Section) -> void:
|
|||
_logbook_tab.button_pressed = section == Section.LOGBOOK
|
||||
_mail_tab.button_pressed = section == Section.MAIL
|
||||
_profile_tab.button_pressed = section == Section.PROFILE
|
||||
_players_tab.button_pressed = section == Section.PLAYERS
|
||||
|
||||
|
||||
func _update_shell_layout() -> void:
|
||||
|
|
@ -1591,6 +1612,7 @@ func _set_shell_interactive(interactive: bool) -> void:
|
|||
_logbook_tab,
|
||||
_mail_tab,
|
||||
_profile_tab,
|
||||
_players_tab,
|
||||
_close_button,
|
||||
]:
|
||||
bubble.focus_mode = Control.FOCUS_ALL if interactive else Control.FOCUS_NONE
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=21 format=3]
|
||||
[gd_scene load_steps=22 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/player_menu.gd" id="1_menu"]
|
||||
[ext_resource type="Theme" path="res://ui/game_theme.tres" id="2_theme"]
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
[ext_resource type="Texture2D" path="res://ui/assets/title/bubbles/bubble3.png" id="17_bubble3"]
|
||||
[ext_resource type="Script" path="res://ui/mail_page.gd" id="18_mail_page"]
|
||||
[ext_resource type="PackedScene" path="res://ui/profile_page.tscn" id="19_profile_page"]
|
||||
[ext_resource type="Script" path="res://ui/players_page.gd" id="20_players_page"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_collection"]
|
||||
|
||||
|
|
@ -592,6 +593,15 @@ offset_top = 112.0
|
|||
offset_right = 1280.0
|
||||
offset_bottom = 710.0
|
||||
|
||||
[node name="PlayersPage" type="Control" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot"]
|
||||
visible = false
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_right = 1280.0
|
||||
offset_bottom = 720.0
|
||||
mouse_filter = 1
|
||||
script = ExtResource("20_players_page")
|
||||
|
||||
[node name="BookBacking" type="PanelContainer" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/LogbookPage"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
|
|
@ -1232,9 +1242,9 @@ toggle_mode = true
|
|||
text = "cooler"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(124, 120)
|
||||
desktop_anchor = Vector2(92, 60)
|
||||
compact_anchor = Vector2(92, 73.3333)
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(70, 60)
|
||||
compact_anchor = Vector2(70, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 25
|
||||
maximum_font_size = 25
|
||||
|
|
@ -1252,9 +1262,9 @@ toggle_mode = true
|
|||
text = "bag"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(124, 120)
|
||||
desktop_anchor = Vector2(220, 60)
|
||||
compact_anchor = Vector2(220, 73.3333)
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(182, 60)
|
||||
compact_anchor = Vector2(182, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 25
|
||||
maximum_font_size = 25
|
||||
|
|
@ -1272,9 +1282,9 @@ toggle_mode = true
|
|||
text = "logbook"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(124, 120)
|
||||
desktop_anchor = Vector2(348, 60)
|
||||
compact_anchor = Vector2(348, 73.3333)
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(294, 60)
|
||||
compact_anchor = Vector2(294, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 25
|
||||
maximum_font_size = 25
|
||||
|
|
@ -1292,9 +1302,9 @@ toggle_mode = true
|
|||
text = "mail"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(124, 120)
|
||||
desktop_anchor = Vector2(476, 60)
|
||||
compact_anchor = Vector2(476, 73.3333)
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(406, 60)
|
||||
compact_anchor = Vector2(406, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 25
|
||||
maximum_font_size = 25
|
||||
|
|
@ -1328,9 +1338,9 @@ toggle_mode = true
|
|||
text = "profile"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(124, 120)
|
||||
desktop_anchor = Vector2(604, 60)
|
||||
compact_anchor = Vector2(604, 73.3333)
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(518, 60)
|
||||
compact_anchor = Vector2(518, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 23
|
||||
maximum_font_size = 25
|
||||
|
|
@ -1341,6 +1351,26 @@ motion_phase = 4.05
|
|||
deformation_amplitude = 0.011
|
||||
deformation_period = 6.5
|
||||
|
||||
[node name="PlayersTab" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
toggle_mode = true
|
||||
text = "players"
|
||||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(112, 108)
|
||||
desktop_anchor = Vector2(630, 60)
|
||||
compact_anchor = Vector2(630, 73.3333)
|
||||
compact_minimum_size = Vector2(84, 82)
|
||||
minimum_font_size = 22
|
||||
maximum_font_size = 24
|
||||
horizontal_amplitude = 1.1
|
||||
vertical_amplitude = 2.2
|
||||
motion_period = 5.8
|
||||
motion_phase = 4.35
|
||||
deformation_amplitude = 0.011
|
||||
deformation_period = 6.4
|
||||
|
||||
[node name="CloseButton" type="Button" parent="ResponsivePlayerMenuStage/PlayerMenuPresentationScaleRoot/NavigationCluster"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
|
|
@ -1348,8 +1378,8 @@ text = "close"
|
|||
script = ExtResource("6_bubble")
|
||||
profile = ExtResource("4_profile")
|
||||
neutral_size = Vector2(96, 94)
|
||||
desktop_anchor = Vector2(744, 57)
|
||||
compact_anchor = Vector2(744, 73.3333)
|
||||
desktop_anchor = Vector2(770, 57)
|
||||
compact_anchor = Vector2(770, 73.3333)
|
||||
compact_minimum_size = Vector2(76, 74)
|
||||
minimum_font_size = 23
|
||||
maximum_font_size = 23
|
||||
|
|
|
|||
289
ui/players_page.gd
Normal file
289
ui/players_page.gd
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
class_name PlayersPage
|
||||
extends Control
|
||||
|
||||
var _service: NetworkPlayerListService
|
||||
var _header: Label
|
||||
var _tabs: HBoxContainer
|
||||
var _list: VBoxContainer
|
||||
var _status: Label
|
||||
var _current_tab := 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
_build()
|
||||
|
||||
|
||||
func setup(service: NetworkPlayerListService) -> void:
|
||||
_service = service
|
||||
_service.entries_changed.connect(_refresh)
|
||||
_service.moderation_finished.connect(func(_ok: bool, message: String) -> void:
|
||||
_status.text = message
|
||||
_refresh()
|
||||
)
|
||||
_refresh()
|
||||
|
||||
|
||||
func activate() -> void:
|
||||
_refresh()
|
||||
_focus_first()
|
||||
|
||||
|
||||
func deactivate() -> void:
|
||||
_status.text = ""
|
||||
|
||||
|
||||
func _build() -> void:
|
||||
var paper := PanelContainer.new()
|
||||
paper.position = Vector2(58, 128)
|
||||
paper.size = Vector2(1164, 476)
|
||||
add_child(paper)
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = Color("eee2bd")
|
||||
style.border_color = Color("473d2e")
|
||||
style.set_border_width_all(4)
|
||||
style.set_corner_radius_all(16)
|
||||
style.content_margin_left = 26
|
||||
style.content_margin_right = 26
|
||||
style.content_margin_top = 20
|
||||
style.content_margin_bottom = 20
|
||||
paper.add_theme_stylebox_override("panel", style)
|
||||
var root := VBoxContainer.new()
|
||||
root.add_theme_constant_override("separation", 10)
|
||||
paper.add_child(root)
|
||||
_header = Label.new()
|
||||
_header.add_theme_font_size_override("font_size", 27)
|
||||
_header.add_theme_color_override("font_color", Color("28251f"))
|
||||
root.add_child(_header)
|
||||
_tabs = HBoxContainer.new()
|
||||
_tabs.add_theme_constant_override("separation", 10)
|
||||
root.add_child(_tabs)
|
||||
for index: int in 3:
|
||||
var button := Button.new()
|
||||
button.text = ["players", "relationships", "banned"][index]
|
||||
button.toggle_mode = true
|
||||
button.pressed.connect(_select_tab.bind(index))
|
||||
_tabs.add_child(button)
|
||||
var scroll := ScrollContainer.new()
|
||||
scroll.custom_minimum_size = Vector2(0, 330)
|
||||
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||||
root.add_child(scroll)
|
||||
_list = VBoxContainer.new()
|
||||
_list.custom_minimum_size = Vector2(1080, 0)
|
||||
_list.add_theme_constant_override("separation", 7)
|
||||
scroll.add_child(_list)
|
||||
_status = Label.new()
|
||||
_status.add_theme_color_override("font_color", Color("514535"))
|
||||
root.add_child(_status)
|
||||
|
||||
|
||||
func _select_tab(index: int) -> void:
|
||||
if index == 2 and (_service == null or not _service.is_local_host()):
|
||||
return
|
||||
_current_tab = index
|
||||
_refresh()
|
||||
_focus_first()
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
if _service == null or _list == null:
|
||||
return
|
||||
_header.text = "players %d / %d connected" % [
|
||||
_service.get_connected_count(), _service.get_max_players(),
|
||||
]
|
||||
for index: int in _tabs.get_child_count():
|
||||
var button := _tabs.get_child(index) as Button
|
||||
button.button_pressed = index == _current_tab
|
||||
button.visible = index != 2 or _service.is_local_host()
|
||||
for child: Node in _list.get_children():
|
||||
child.queue_free()
|
||||
match _current_tab:
|
||||
0:
|
||||
_build_active_rows()
|
||||
1:
|
||||
_build_relationship_rows()
|
||||
2:
|
||||
_build_ban_rows()
|
||||
|
||||
|
||||
func _build_active_rows() -> void:
|
||||
var entries := _service.get_entries()
|
||||
if entries.is_empty():
|
||||
_add_empty("No authenticated players.")
|
||||
return
|
||||
for entry: PlayerListEntry in entries:
|
||||
var row := _make_row()
|
||||
var identity := Label.new()
|
||||
identity.custom_minimum_size.x = 515
|
||||
var markers: Array[String] = []
|
||||
if entry.is_host:
|
||||
markers.append("host")
|
||||
if entry.is_local_player:
|
||||
markers.append("You")
|
||||
identity.text = "%s%s · %s\n%s" % [
|
||||
entry.display_name,
|
||||
" [%s]" % ", ".join(markers) if not markers.is_empty() else "",
|
||||
entry.compact_fingerprint,
|
||||
entry.continuity_state,
|
||||
]
|
||||
identity.tooltip_text = NetworkIdentityCrypto.format_fingerprint(
|
||||
entry.full_fingerprint
|
||||
)
|
||||
row.add_child(identity)
|
||||
var ping := Label.new()
|
||||
ping.custom_minimum_size.x = 80
|
||||
ping.text = (
|
||||
"Local" if entry.is_host
|
||||
else "%d ms" % entry.ping_to_host_ms
|
||||
if entry.ping_to_host_ms >= 0 else "—"
|
||||
)
|
||||
row.add_child(ping)
|
||||
var mute := Button.new()
|
||||
mute.text = "unmute" if entry.muted else "mute"
|
||||
mute.disabled = entry.is_local_player
|
||||
mute.pressed.connect(_toggle_mute.bind(entry))
|
||||
row.add_child(mute)
|
||||
var block := Button.new()
|
||||
block.text = "block"
|
||||
block.disabled = entry.is_local_player
|
||||
block.pressed.connect(_confirm_block.bind(entry))
|
||||
row.add_child(block)
|
||||
var kick := Button.new()
|
||||
kick.text = "kick"
|
||||
kick.disabled = not entry.can_kick
|
||||
kick.pressed.connect(_confirm_kick.bind(entry))
|
||||
row.add_child(kick)
|
||||
var ban := Button.new()
|
||||
ban.text = "ban"
|
||||
ban.disabled = not entry.can_ban
|
||||
ban.pressed.connect(_confirm_ban.bind(entry))
|
||||
row.add_child(ban)
|
||||
_list.add_child(row)
|
||||
|
||||
|
||||
func _build_relationship_rows() -> void:
|
||||
var records := _service.get_relationships()
|
||||
if records.is_empty():
|
||||
_add_empty("No muted or blocked identities.")
|
||||
return
|
||||
for record: Dictionary in records:
|
||||
var row := _make_row()
|
||||
var label := Label.new()
|
||||
label.custom_minimum_size.x = 690
|
||||
var fingerprint := str(record["fingerprint"])
|
||||
label.text = "%s · %s %s" % [
|
||||
str(record.get("last_known_display_name", "Player")),
|
||||
NetworkIdentityCrypto.compact_suffix(fingerprint),
|
||||
"Blocked" if bool(record.get("blocked", false)) else "Muted",
|
||||
]
|
||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||
row.add_child(label)
|
||||
if bool(record.get("blocked", false)):
|
||||
var unblock := Button.new()
|
||||
unblock.text = "unblock"
|
||||
unblock.pressed.connect(func() -> void:
|
||||
_service.set_blocked(fingerprint, str(record["last_known_display_name"]), false)
|
||||
)
|
||||
row.add_child(unblock)
|
||||
var unmute := Button.new()
|
||||
unmute.text = "unmute"
|
||||
unmute.disabled = bool(record.get("blocked", false))
|
||||
unmute.pressed.connect(func() -> void:
|
||||
_service.set_muted(fingerprint, str(record["last_known_display_name"]), false)
|
||||
)
|
||||
row.add_child(unmute)
|
||||
_list.add_child(row)
|
||||
|
||||
|
||||
func _build_ban_rows() -> void:
|
||||
var records := _service.get_bans()
|
||||
if records.is_empty():
|
||||
_add_empty("No banned identities.")
|
||||
return
|
||||
for record: Dictionary in records:
|
||||
var row := _make_row()
|
||||
var fingerprint := str(record["target_fingerprint"])
|
||||
var label := Label.new()
|
||||
label.custom_minimum_size.x = 830
|
||||
label.text = "%s · %s banned %s" % [
|
||||
str(record.get("last_known_display_name", "Player")),
|
||||
NetworkIdentityCrypto.compact_suffix(fingerprint),
|
||||
Time.get_date_string_from_unix_time(int(record.get("banned_unix", 0))),
|
||||
]
|
||||
label.tooltip_text = NetworkIdentityCrypto.format_fingerprint(fingerprint)
|
||||
row.add_child(label)
|
||||
var unban := Button.new()
|
||||
unban.text = "unban"
|
||||
unban.pressed.connect(_confirm_unban.bind(fingerprint))
|
||||
row.add_child(unban)
|
||||
_list.add_child(row)
|
||||
|
||||
|
||||
func _make_row() -> HBoxContainer:
|
||||
var row := HBoxContainer.new()
|
||||
row.custom_minimum_size.y = 58
|
||||
row.add_theme_constant_override("separation", 8)
|
||||
return row
|
||||
|
||||
|
||||
func _add_empty(text: String) -> void:
|
||||
var label := Label.new()
|
||||
label.text = text
|
||||
label.custom_minimum_size.y = 100
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
_list.add_child(label)
|
||||
|
||||
|
||||
func _toggle_mute(entry: PlayerListEntry) -> void:
|
||||
_service.set_muted(entry.full_fingerprint, entry.display_name, not entry.muted)
|
||||
|
||||
|
||||
func _confirm_block(entry: PlayerListEntry) -> void:
|
||||
_confirm(
|
||||
"Block %s?\nTheir local social and visual presentation will be hidden."
|
||||
% entry.display_name,
|
||||
func() -> void:
|
||||
_service.set_blocked(entry.full_fingerprint, entry.display_name, true)
|
||||
)
|
||||
|
||||
|
||||
func _confirm_kick(entry: PlayerListEntry) -> void:
|
||||
_confirm("Remove %s from this session?" % entry.display_name, func() -> void:
|
||||
_service.kick(entry.peer_id, entry.full_fingerprint, entry.revision)
|
||||
)
|
||||
|
||||
|
||||
func _confirm_ban(entry: PlayerListEntry) -> void:
|
||||
_confirm("Ban %s · %s from this server?" % [
|
||||
entry.display_name, entry.compact_fingerprint,
|
||||
], func() -> void:
|
||||
_service.ban(
|
||||
entry.peer_id, entry.full_fingerprint, entry.display_name, entry.revision
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
func _confirm_unban(fingerprint: String) -> void:
|
||||
_confirm("Unban %s?" % NetworkIdentityCrypto.compact_suffix(fingerprint), func() -> void:
|
||||
_service.unban(fingerprint)
|
||||
)
|
||||
|
||||
|
||||
func _confirm(text: String, action: Callable) -> void:
|
||||
var dialog := ConfirmationDialog.new()
|
||||
dialog.dialog_text = text
|
||||
dialog.ok_button_text = "confirm"
|
||||
dialog.canceled.connect(dialog.queue_free)
|
||||
dialog.confirmed.connect(func() -> void:
|
||||
action.call()
|
||||
dialog.queue_free()
|
||||
)
|
||||
add_child(dialog)
|
||||
dialog.popup_centered(Vector2i(520, 220))
|
||||
|
||||
|
||||
func _focus_first() -> void:
|
||||
for child: Node in _tabs.get_children():
|
||||
if child is Button and child.visible and not child.disabled:
|
||||
child.grab_focus()
|
||||
return
|
||||
1
ui/players_page.gd.uid
Normal file
1
ui/players_page.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://c71playerspage0001
|
||||
Loading…
Add table
Add a link
Reference in a new issue