Initial commit

This commit is contained in:
2026-01-21 23:51:53 +01:00
commit 60b208fee0
1703 changed files with 100223 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
extends Object
class_name GridCell
var spaceTaken: bool = false
var biome: int
var door: bool = false
var doorOrientation: int = 0

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,141 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Spacebots"
run/main_scene="uid://c240icwf4uov8"
config/use_custom_user_dir=true
config/features=PackedStringArray("4.5", "Forward Plus")
config/icon="res://icon.svg"
[audio]
driver/enable_input=true
[autoload]
Multiplayer="*res://script/multiplayer.gd"
Steamworks="*res://script/steamworks.gd"
Featuremanager="*res://script/featuremanager.gd"
AudioManager="*res://script/audioManager.gd"
Noray="*res://addons/netfox.noray/noray.gd"
PacketHandshake="*res://addons/netfox.noray/packet-handshake.gd"
[debug]
file_logging/enable_file_logging=true
gdscript/warnings/integer_division=0
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/size/mode=3
window/stretch/mode="viewport"
window/stretch/aspect="expand"
[editor_plugins]
enabled=PackedStringArray("res://addons/netfox.internals/plugin.cfg", "res://addons/netfox.noray/plugin.cfg")
[input]
moveUp={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
moveDown={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
]
}
moveRight={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
]
}
moveLeft={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
]
}
cameraUp={
"deadzone": 0.2,
"events": []
}
Sprint={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
pause={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
interact={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
]
}
drop={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":103,"location":0,"echo":false,"script":null)
]
}
flashlight={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
]
}
throw={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(191, 15),"global_position":Vector2(200, 63),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}
settings={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
debug={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null)
]
}
noise={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
]
}
[layer_names]
3d_physics/layer_1="Default"
3d_physics/layer_2="Player"
3d_physics/layer_3="Walls"
3d_physics/layer_5="Grabbing"
3d_physics/layer_6="Interact"
3d_physics/layer_7="hurtboxes Players"
3d_physics/layer_8="hurtboxes Enemies"
[physics]
3d/run_on_separate_thread=true
[rendering]
textures/canvas_textures/default_texture_filter=0
[steam]
initialization/app_id=480

View File

@@ -0,0 +1,41 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cbmd7tvr5nxah"
path.s3tc="res://.godot/imported/Sample1_Poliigon_MetalSteelBrushed_7174_BaseColor.jpg-b3defcd51d7a9246177ebcbf12964f81.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://assets/3D/Sample1_Poliigon_MetalSteelBrushed_7174_BaseColor.jpg"
dest_files=["res://.godot/imported/Sample1_Poliigon_MetalSteelBrushed_7174_BaseColor.jpg-b3defcd51d7a9246177ebcbf12964f81.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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

View File

@@ -0,0 +1,159 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[Fmod]
General/auto_initialize=true
General/channel_count=1024
General/is_live_update_enabled=true
General/is_memory_tracking_enabled=false
"Software Format/sample_rate"=48000
"Software Format/speaker_mode"=3
"Software Format/raw_speaker_count"=0
General/default_listener_count=1
General/banks_path="res://assets/FmodBanks/Desktop"
General/should_load_by_name=false
DSP/dsp_buffer_size=512
DSP/dsp_buffer_count=4
"3D Settings/doppler_scale"=1.0
"3D Settings/distance_factor"=1.0
"3D Settings/rolloff_scale"=1.0
[application]
config/name="Spacebots"
run/main_scene="uid://c240icwf4uov8"
config/use_custom_user_dir=true
config/features=PackedStringArray("4.4", "Forward Plus")
config/icon="res://icon.svg"
[audio]
driver/enable_input=true
[autoload]
Noray="*res://addons/netfox.noray/noray.gd"
PacketHandshake="*res://addons/netfox.noray/packet-handshake.gd"
Multiplayer="*res://script/multiplayer.gd"
Steamworks="*res://script/steamworks.gd"
FmodManager="*res://addons/fmod/FmodManager.gd"
Featuremanager="*res://script/featuremanager.gd"
AudioManager="*res://script/audioManager.gd"
[debug]
file_logging/enable_file_logging=true
[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/size/mode=3
window/stretch/mode="viewport"
window/stretch/aspect="expand"
[editor_plugins]
enabled=PackedStringArray("res://addons/fmod/plugin.cfg", "res://addons/netfox.internals/plugin.cfg", "res://addons/netfox.noray/plugin.cfg")
[input]
moveUp={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
moveDown={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
]
}
moveRight={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
]
}
moveLeft={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
]
}
cameraUp={
"deadzone": 0.2,
"events": []
}
Sprint={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194325,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
pause={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
interact={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
]
}
drop={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":71,"key_label":0,"unicode":103,"location":0,"echo":false,"script":null)
]
}
flashlight={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
]
}
throw={
"deadzone": 0.2,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(191, 15),"global_position":Vector2(200, 63),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":false,"script":null)
]
}
settings={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
debug={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null)
]
}
noise={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
]
}
[layer_names]
3d_physics/layer_1="Default"
3d_physics/layer_2="Player"
3d_physics/layer_3="Walls"
3d_physics/layer_5="Grabbing"
3d_physics/layer_6="Interact"
3d_physics/layer_7="hurtboxes Players"
3d_physics/layer_8="hurtboxes Enemies"
[physics]
3d/run_on_separate_thread=true
[rendering]
textures/canvas_textures/default_texture_filter=0
[steam]
initialization/app_id=480

View File

@@ -0,0 +1,258 @@
extends Node
#{
#var mic_capture : AudioEffectOpusChunked
#var audio_stats : Dictionary[int, Array] # id->[last_number, packetsreceived, packetslost]
#var packets_sent: int = 0
#
#var packet_queue: Dictionary[int, Array] # sender_id -> Array of PackedByteArrays
#
#
#func _ready():
#playstuff()
#var mic_bus = AudioServer.get_bus_index("Mic")
#mic_capture = AudioServer.get_bus_effect(mic_bus, 0)
#
#func _process(_delta: float):
#if !mic_capture or Multiplayer.playerDict.is_empty():
#return
#if Input.is_action_just_pressed("noise"):
#play_note(69)
#print("test")
#var t1 = Time.get_unix_time_from_system()
#for sender in packet_queue.keys():
#var VoiceChatPlayerOutputNode: AudioStreamPlayer3D = Multiplayer.playerDict.get(sender).VoiceChat
#var OpusStream : AudioStreamOpusChunked = VoiceChatPlayerOutputNode.stream
#while OpusStream.chunk_space_available() and packet_queue.get(sender).size() > 0:
#var pkt: PackedByteArray = packet_queue.get(sender).pop_front()
#print(packet_queue.get(sender).size())
#OpusStream.queue_length_frames()
#OpusStream.push_opus_packet(pkt, 8, 0)
#var t2 = Time.get_unix_time_from_system()
#print("Time 1: ", 1000*(t2-t1), "ms")
#var seq_num : PackedByteArray = PackedByteArray()
#seq_num.resize(8)
#while mic_capture.chunk_available():
#if multiplayer.multiplayer_peer.get_connection_status() != MultiplayerPeer.CONNECTION_CONNECTED:
#mic_capture.drop_chunk()
#continue
#seq_num.encode_u64(0,packets_sent+1)
#var packet = mic_capture.read_opus_packet(seq_num)
#mic_capture.drop_chunk()
#_voice_packet_received.rpc(packet)
#packets_sent += 1
#if (packets_sent % 500) == 0:
#print("Packets sent: ", packets_sent, " from id ", multiplayer.get_unique_id(), " ", hash(packet))
#print("Size before: ", packet.size())
#print("Hash send: ", hash(packet))
#var t3 = Time.get_unix_time_from_system()
#print("Time 2: ", 1000*(t3-t2), "ms")
#
#@rpc("any_peer", "call_remote" ,"unreliable_ordered", 1)
#func _voice_packet_received(packet: PackedByteArray):
#var sender_id = multiplayer.get_remote_sender_id()
#
##Stats for printing
#var sender_stats = audio_stats.get(sender_id, [0,0,0])
#if (sender_stats[0]+1 != packet.decode_u32(0)):
#sender_stats[2]+=1
#sender_stats[0]=packet.decode_u64(0)
#sender_stats[1]+=1
#audio_stats.set(sender_id, sender_stats)
#if (sender_stats[1] % 500) == 0:
#print("Packets received: ", sender_stats[1], " from id ", sender_id, " Lossrate: ", sender_stats[2], "/", sender_stats[1], "(" , str(100*(sender_stats[2]/sender_stats[1])), "%)")
#print("Size after: ", packet.size())
#print("Hash received: ", hash(packet))
#print("Packet no.: ", packet.decode_u64(0))
#var VoiceChatPlayerOutputNode: AudioStreamPlayer3D = Multiplayer.playerDict.get(sender_id).VoiceChat
#var _OpusStream : AudioStreamOpusChunked = VoiceChatPlayerOutputNode.stream
## OpusSteam
#if not packet_queue.has(sender_id):
#var x : Array[PackedByteArray] = []
#packet_queue.set(sender_id, x)
#if packet_queue.get(sender_id).size() > 250:
#push_error("VoiceChat buffer for user ", sender_id, " too large!")
#var x : Array[PackedByteArray] = []
#packet_queue.set(sender_id, x)
#packet_queue.get(sender_id).append(packet)
#
#var playback: AudioStreamGeneratorPlayback
#var player : AudioStreamPlayer
#
#func playstuff():
#var generator = AudioStreamGenerator.new()
#generator.mix_rate = 44100
#generator.buffer_length = 2
#player = AudioStreamPlayer.new()
#player.bus = "Mic"
#player.stream = generator
#add_child(player)
#player.play()
#playback = player.get_stream_playback()
#
#func play_note(midi_note: int):
#var freq = 440.0 * pow(2.0, (midi_note - 69) / 12.0) # MIDI ? Hz
#generate_sine_wave(freq)
#
#func generate_sine_wave(frequency: float):
#var sample_rate = 44100.0
#var increment = TAU * frequency / sample_rate
#var phase = 0.0
#var num_samples = int(sample_rate * 2) # 0.5 seconds
#var buffer = PackedVector2Array()
#for i in num_samples:
#var sample = sin(phase)
#buffer.append(Vector2(sample, sample)) # stereo
#phase += increment
#playback.push_buffer(buffer)
#}
var current_sample_rate: int = 48000
var has_loopback: bool = false
var local_playback: AudioStreamGeneratorPlayback = null
var local_voice_buffer: PackedByteArray = PackedByteArray()
var network_playback: Dictionary[int, AudioStreamGeneratorPlayback] = {}
var network_voice_buffer: Dictionary[int, PackedByteArray] = {}
var max_buffer_size: int = 1000
@onready var loopback_player : AudioStreamPlayer= $/root/Main/VoiceLoopback
func _ready() -> void:
if not Steamworks.is_initiallized:
push_warning("[VoiceChat] VoiceChat disabled due to SteamAPI.")
return
record_voice(true)
loopback_player.stream.mix_rate = current_sample_rate
loopback_player.play()
local_playback = loopback_player.get_stream_playback()
multiplayer.peer_disconnected.connect(remove_disconnected_peer)
multiplayer.peer_connected.connect(add_joined_peer)
func _process(_delta: float) -> void:
if not Steamworks.is_initiallized:
return
check_for_voice_local()
for player : int in network_voice_buffer:
process_voice_data(network_voice_buffer.get(player), str(player))
func add_joined_peer(id):
var remote_audio_stream_player : Node3D = get_node_or_null(^"/root/Main/Players/%s/VoiceChat_a" % id)
network_playback.set(id, remote_audio_stream_player)
network_voice_buffer.set(id,PackedByteArray())
func remove_disconnected_peer(id):
network_playback.erase(id)
network_voice_buffer.erase(id)
func check_for_voice_local() -> void:
var available_voice: Dictionary = Steam.getAvailableVoice()
if !available_voice:
return
# Seems there is voice data
if available_voice['result'] == Steam.VOICE_RESULT_OK and available_voice['buffer'] > 0:
# Valve's getVoice uses 1024 but GodotSteam's is set at 8192?
# Our sizes might be way off; internal GodotSteam notes that Valve suggests 8kb
# However, this is not mentioned in the header nor the SpaceWar example but -is- in Valve's docs which are usually wrong
var voice_data: Dictionary = Steam.getVoice()
if voice_data['result'] == Steam.VOICE_RESULT_OK and voice_data['written']:
print("Voice message has data: %s / %s" % [voice_data['result'], voice_data['written']])
# Here we can pass this voice data off on the network
send_voice.rpc(voice_data['buffer'])
# If loopback is enable, play it back at this point
if has_loopback:
print("Loopback on")
# Our sample rate function above without toggling
get_sample_rate()
process_voice_data(voice_data, "local")
@rpc("any_peer","call_remote","unreliable")
func send_voice(voice_buffer : PackedByteArray):
var sender_id : int = multiplayer.get_remote_sender_id()
if not network_playback.has(sender_id):
push_error("[VoiceChat] Received audio data, but there is no AudioStreamPlayer available for that user. Emitter: " + str(sender_id))
return
if not network_voice_buffer.has(sender_id):
push_error("[VoiceChat] Received audio data without allocated voice buffer for that user. Emitter: " + str(sender_id))
return
var local_peer_buffer : PackedByteArray = network_voice_buffer.get(sender_id)
if local_peer_buffer.size() >= max_buffer_size:
push_error("[VoiceChat] AudioBuffer exeeding size limit. Emitter: " + str(sender_id))
local_peer_buffer.append_array(voice_buffer)
print_debug("[VoiceChat] AudioBuffer size: " + str(local_peer_buffer.size()))
@rpc("any_peer","call_remote","reliable")
func send_sample_rate(sample_rate : int):
if sample_rate < 11025 || sample_rate > 48000:
return
var sender_id : int = multiplayer.get_remote_sender_id()
if network_playback.has(sender_id):
network_playback.get(sender_id).stream.mix_rate = sample_rate
network_playback.get(sender_id).clear_buffer()
network_voice_buffer.get(sender_id).clear()
func get_sample_rate() -> void:
current_sample_rate = Steam.getVoiceOptimalSampleRate()
if loopback_player.stream.mix_rate != current_sample_rate:
send_sample_rate.rpc(current_sample_rate)
loopback_player.stream.mix_rate = current_sample_rate
print("[VoiceChat] Changed own sample rate to: %s", current_sample_rate)
func process_voice_data(voice_data: Dictionary, voice_source: String) -> void:
var decompressed_voice: Dictionary = Steam.decompressVoice(voice_data['buffer'], current_sample_rate)
if decompressed_voice['result'] == Steam.VOICE_RESULT_OK and decompressed_voice['size'] > 0:
print("[VoiceChat] Decompressed voice: %s" % decompressed_voice['size'])
if voice_source == "local":
local_voice_buffer = decompressed_voice['uncompressed']
local_voice_buffer.resize(decompressed_voice['size'])
# We now iterate through the local_voice_buffer and push the samples to the audio generator
for i: int in local_playback.get_frames_available():
if local_voice_buffer.size() == 0: break
# Steam's audio data is represented as 16-bit single channel PCM audio, so we need to convert it to amplitudes
# Combine the low and high bits to get full 16-bit value
var raw_value: int = local_voice_buffer[0] | (local_voice_buffer[1] << 8)
# Make it a 16-bit signed integer
raw_value = (raw_value + 32768) & 0xffff
# Convert the 16-bit integer to a float on from -1 to 1
var amplitude: float = float(raw_value - 32768) / 32768.0
# push_frame() takes a Vector2. The x represents the left channel and the y represents the right channel
local_playback.push_frame(Vector2(amplitude, amplitude))
# Delete the used samples
local_voice_buffer.remove_at(0)
local_voice_buffer.remove_at(0)
else:
#TODO: Better naming
#Better explanation for 16-bit conversions
network_voice_buffer.set(voice_source, decompressed_voice['uncompressed'])
var _network_voice_buffer : PackedByteArray = network_voice_buffer.get(voice_source)
_network_voice_buffer.resize(decompressed_voice['size'])
var _network_playback : AudioStreamGenerator = network_playback.get(voice_source)
for i: int in _network_playback.get_frames_available():
if _network_playback.size() == 0: break
var raw_value: int = _network_voice_buffer[0] | (_network_voice_buffer[1] << 8)
# Make it a 16-bit signed integer
raw_value = (raw_value + 32768) & 0xffff
# Convert the 16-bit integer to a float on from -1 to 1
var amplitude: float = float(raw_value - 32768) / 32768.0
# push_frame() takes a Vector2. The x represents the left channel and the y represents the right channel
_network_playback.push_frame(Vector2(amplitude, amplitude))
# Delete the used samples
_network_playback.remove_at(0)
_network_playback.remove_at(0)
func record_voice(is_recording: bool) -> void:
# If talking, suppress all other audio or voice comms from the Steam UI
Steam.setInGameVoiceSpeaking(Steamworks.steam_id, is_recording)
if is_recording:
Steam.startVoiceRecording()
else:
Steam.stopVoiceRecording()