forked from xiangwang25/whale-town-front-v2
Initial WhaleTown V2 frontend
This commit is contained in:
150
_Core/managers/NotificationSoundManager.gd
Normal file
150
_Core/managers/NotificationSoundManager.gd
Normal file
@@ -0,0 +1,150 @@
|
||||
extends Node
|
||||
|
||||
# ============================================================================
|
||||
# NotificationSoundManager.gd - 提醒音效管理器
|
||||
# ============================================================================
|
||||
# 监听聊天和好友事件,播放项目内正式 UI 提醒音效资源。
|
||||
# ============================================================================
|
||||
|
||||
const MIN_PLAY_INTERVAL_SEC: float = 0.18
|
||||
const WORLD_NOTIFICATION_PATH: String = "res://assets/audio/ui/notify_world.wav"
|
||||
const PRIVATE_NOTIFICATION_PATH: String = "res://assets/audio/ui/notify_private.wav"
|
||||
const FRIEND_NOTIFICATION_PATH: String = "res://assets/audio/ui/notify_friend.wav"
|
||||
|
||||
var _player: AudioStreamPlayer
|
||||
var _worldStream: AudioStreamWAV
|
||||
var _privateStream: AudioStreamWAV
|
||||
var _friendStream: AudioStreamWAV
|
||||
var _lastPlayedAt: float = 0.0
|
||||
var _seenFriendRequestKeys: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
_build_player()
|
||||
_load_streams()
|
||||
_subscribe_to_events()
|
||||
|
||||
func _exit_tree() -> void:
|
||||
var eventSystem := _get_event_system()
|
||||
if eventSystem != null:
|
||||
eventSystem.call("disconnect_event", EventNames.CHAT_MESSAGE_RECEIVED, _on_chat_message_received, self)
|
||||
eventSystem.call("disconnect_event", EventNames.CHAT_FRIENDS_UPDATED, _on_friends_updated, self)
|
||||
eventSystem.call("disconnect_event", EventNames.CHAT_ERROR_OCCURRED, _on_chat_error, self)
|
||||
|
||||
func play_notification(kind: String = "world") -> void:
|
||||
if _settings_bool("mute_ui_sfx", false):
|
||||
return
|
||||
|
||||
var now := Time.get_unix_time_from_system()
|
||||
if now - _lastPlayedAt < MIN_PLAY_INTERVAL_SEC:
|
||||
return
|
||||
_lastPlayedAt = now
|
||||
|
||||
if not is_instance_valid(_player):
|
||||
return
|
||||
var stream := _stream_for_kind(kind)
|
||||
if stream == null:
|
||||
return
|
||||
_player.stream = stream
|
||||
_player.play()
|
||||
|
||||
func should_play_message_notification(data: Dictionary) -> bool:
|
||||
if bool(data.get("is_self", false)):
|
||||
return false
|
||||
|
||||
var scope := str(data.get("scope", "")).strip_edges().to_lower()
|
||||
var isPrivate := bool(data.get("is_private", false)) or scope == "private"
|
||||
if isPrivate:
|
||||
return _settings_bool("private_notifications", true)
|
||||
return _settings_bool("world_notifications", true)
|
||||
|
||||
func get_notification_asset_path(kind: String = "world") -> String:
|
||||
match kind:
|
||||
"private":
|
||||
return PRIVATE_NOTIFICATION_PATH
|
||||
"friend":
|
||||
return FRIEND_NOTIFICATION_PATH
|
||||
_:
|
||||
return WORLD_NOTIFICATION_PATH
|
||||
|
||||
func _build_player() -> void:
|
||||
_player = AudioStreamPlayer.new()
|
||||
_player.name = "NotificationAudioPlayer"
|
||||
_player.bus = "SFX"
|
||||
add_child(_player)
|
||||
|
||||
func _load_streams() -> void:
|
||||
_worldStream = _load_wav_stream(WORLD_NOTIFICATION_PATH)
|
||||
_privateStream = _load_wav_stream(PRIVATE_NOTIFICATION_PATH)
|
||||
_friendStream = _load_wav_stream(FRIEND_NOTIFICATION_PATH)
|
||||
|
||||
func _load_wav_stream(path: String) -> AudioStreamWAV:
|
||||
var stream := AudioStreamWAV.load_from_file(ProjectSettings.globalize_path(path))
|
||||
if stream == null:
|
||||
push_warning("NotificationSoundManager: 提醒音效加载失败: %s" % path)
|
||||
return stream
|
||||
|
||||
func _stream_for_kind(kind: String) -> AudioStream:
|
||||
match kind:
|
||||
"private":
|
||||
return _privateStream
|
||||
"friend":
|
||||
return _friendStream
|
||||
_:
|
||||
return _worldStream
|
||||
|
||||
func _subscribe_to_events() -> void:
|
||||
var eventSystem := _get_event_system()
|
||||
if eventSystem == null:
|
||||
push_warning("NotificationSoundManager: EventSystem autoload is not available.")
|
||||
return
|
||||
eventSystem.call("connect_event", EventNames.CHAT_MESSAGE_RECEIVED, _on_chat_message_received, self)
|
||||
eventSystem.call("connect_event", EventNames.CHAT_FRIENDS_UPDATED, _on_friends_updated, self)
|
||||
eventSystem.call("connect_event", EventNames.CHAT_ERROR_OCCURRED, _on_chat_error, self)
|
||||
|
||||
func _on_chat_message_received(data: Dictionary) -> void:
|
||||
if not should_play_message_notification(data):
|
||||
return
|
||||
var scope := str(data.get("scope", "")).strip_edges().to_lower()
|
||||
var isPrivate := bool(data.get("is_private", false)) or scope == "private"
|
||||
play_notification("private" if isPrivate else "world")
|
||||
|
||||
func _on_friends_updated(data: Dictionary) -> void:
|
||||
if not _settings_bool("friend_request_notifications", true):
|
||||
return
|
||||
|
||||
var requestsVariant: Variant = data.get("requests", [])
|
||||
if not (requestsVariant is Array):
|
||||
return
|
||||
|
||||
var shouldPlay := false
|
||||
for requestVariant in requestsVariant:
|
||||
if not (requestVariant is Dictionary):
|
||||
continue
|
||||
var key := _friend_request_key(requestVariant as Dictionary)
|
||||
if key.is_empty() or _seenFriendRequestKeys.has(key):
|
||||
continue
|
||||
_seenFriendRequestKeys[key] = true
|
||||
shouldPlay = true
|
||||
|
||||
if shouldPlay:
|
||||
play_notification("friend")
|
||||
|
||||
func _on_chat_error(data: Dictionary) -> void:
|
||||
var errorCode := str(data.get("error_code", ""))
|
||||
if errorCode == "FRIEND_REQUEST_SENT" and _settings_bool("friend_request_notifications", true):
|
||||
play_notification("friend")
|
||||
|
||||
func _friend_request_key(request: Dictionary) -> String:
|
||||
var userId := str(request.get("user_id", request.get("userId", ""))).strip_edges()
|
||||
if not userId.is_empty():
|
||||
return userId
|
||||
return str(request.get("username", "")).strip_edges()
|
||||
|
||||
func _settings_bool(key: String, defaultValue: bool) -> bool:
|
||||
var settingsManager := get_node_or_null("/root/SettingsManager")
|
||||
if settingsManager != null and settingsManager.has_method("get_bool"):
|
||||
return bool(settingsManager.call("get_bool", key))
|
||||
return defaultValue
|
||||
|
||||
func _get_event_system() -> Node:
|
||||
return get_node_or_null("/root/EventSystem")
|
||||
Reference in New Issue
Block a user