Merge pull request 'Merge multiplayer to dev branch' (#2) from multiplayer into develop

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2025-08-07 22:06:01 +00:00
87 changed files with 1557 additions and 7 deletions

View File

@@ -0,0 +1,22 @@
[configuration]
entry_symbol = "godotsteam_init"
compatibility_minimum = "4.4"
[libraries]
macos.debug = "res://addons/godotsteam/osx/libgodotsteam.macos.template_debug.framework"
macos.release = "res://addons/godotsteam/osx/libgodotsteam.macos.template_release.framework"
windows.debug.x86_64 = "res://addons/godotsteam/win64/libgodotsteam.windows.template_debug.x86_64.dll"
windows.debug.x86_32 = "res://addons/godotsteam/win32/libgodotsteam.windows.template_debug.x86_32.dll"
windows.release.x86_64 = "res://addons/godotsteam/win64/libgodotsteam.windows.template_release.x86_64.dll"
windows.release.x86_32 = "res://addons/godotsteam/win32/libgodotsteam.windows.template_release.x86_32.dll"
linux.debug.x86_64 = "res://addons/godotsteam/linux64/libgodotsteam.linux.template_debug.x86_64.so"
linux.debug.x86_32 = "res://addons/godotsteam/linux32/libgodotsteam.linux.template_debug.x86_32.so"
linux.release.x86_64 = "res://addons/godotsteam/linux64/libgodotsteam.linux.template_release.x86_64.so"
linux.release.x86_32 = "res://addons/godotsteam/linux32/libgodotsteam.linux.template_release.x86_32.so"
[dependencies]
macos.universal = { "res://addons/godotsteam/osx/libsteam_api.dylib": "" }
windows.x86_64 = { "res://addons/godotsteam/win64/steam_api64.dll": "" }
windows.x86_32 = { "res://addons/godotsteam/win32/steam_api.dll": "" }
linux.x86_64 = { "res://addons/godotsteam/linux64/libsteam_api.so": "" }
linux.x86_32 = { "res://addons/godotsteam/linux32/libsteam_api.so": "" }

View File

@@ -0,0 +1 @@
uid://b3p0yh6q3ajpd

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>libgodotsteam.debug</string>
<key>CFBundleIdentifier</key>
<string>org.godotsteam.godotsteam</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>libgodotsteam.debug</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.15</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>4.15</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
</dict>
</plist>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>libgodotsteam</string>
<key>CFBundleIdentifier</key>
<string>org.godotsteam.godotsteam</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>libgodotsteam</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.15</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>4.15</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
</dict>
</plist>

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
~*.dll

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Expresso Bits
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,87 @@
# <img src="https://raw.githubusercontent.com/expressobits/steam-multiplayer-peer/main/icon.png" alt= “icon” width="32" height="32"> Welcome to Expresso Steam Multiplayer Peer 👋
![Version](https://img.shields.io/badge/version-0.2.0-blue.svg?cacheSeconds=2592000)
[![Documentation](https://img.shields.io/badge/documentation-no-red.svg)](todo-doc)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](MIT)
See demos in:
Github: [Branch demos](https://github.com/expressobits/steam-multiplayer-peer/tree/demos)
Godot Asset Lib: https://godotengine.org/asset-library/asset/2258
## Tutorial and Learnings (How to use)
See post of Michael Macha
https://michaelmacha.wordpress.com/2024/04/08/godotsteam-and-steammultiplayerpeer/
See too on youtube videos
https://www.youtube.com/playlist?list=PLg_8mgEWE2p8ZA-AqUUJ3CYEtrRVFhl_v
Thank you Michael!
## Features
✔️ Change easy Enet peer to Steam Peer
✔️ Use Steam Sockets (Low level like enet).
✔️ GDExtension (Easy to add your project)
✔️ No dependency with GodotSteam, but demo use GodotSteam to handle connections with lobbies (See lobbies tutorial in Godot Steam [here](https://godotsteam.com/tutorials/lobbies/)).
## GodotSteam SteamMultiplayerPeer Differences
| Differences | This SteamMultiplayerPeer | GodotSteam SteamMultiplayerPeer |
|---|---|---|
| Lib Type | GDExtension, add on your project libs to use easy. | C++ module, you need to use the precompiled <br>ones from godotsteam or compile it yourself |
| Steam Connection | Steam Sockets [Steam Docs](https://partner.steamgames.com/doc/api/ISteamNetworkingSockets)<br>Steam's lowest connection level,<br>manages a connection <br>(It's very close to Enet, <br>that's why I chose this approach for the plugin) | Steam Messages [Steam Docs](https://partner.steamgames.com/doc/api/ISteamNetworkingMessages)<br>Without a connection idea,<br>the connection is managed by the lobby,<br>Need Steam lobbies. |
| TODO | | |
## Known issues
⚠️ Features No channel support currently
At some point I intend to integrate channels to be used in rpcs commands, but currently it is only necessary to use channel 0 or the default rpcs.
## In Progress
🔨 Bugs fixes
## Planneds
📅 No planned features.
<!-- ## Install
See in [Wiki](https://github.com/ExpressoBits/inventory-system/wiki) -->
## Authors
👤 **Rafael Correa**
* Twitter: [@ScriptsEngineer](https://twitter.com/ScriptsEngineer)
* Github: [@scriptsengineer](https://github.com/scriptsengineer)
👤 **Zennyth**
* Github: [@Zennyth](https://github.com/Zennyth)
👤 **greenfox1505**
* Github: [@greenfox1505](https://github.com/greenfox1505)
👤 **MichaelMacha**
* Github: [@MichaelMacha](https://github.com/MichaelMacha)
## 🤝 Contributing
Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/ExpressoBits/steam-multiplayer-peer/issues).
To suggest or discuss some project structure, feel free here [discussions page](https://github.com/expressobits/steam-multiplayer-peer/discussions)
## Show your support
Give a ⭐️ if this project helped you!
## 📝 License
This project is [MIT](MIT) licensed.

View File

@@ -0,0 +1,25 @@
[configuration]
entry_symbol = "steam_multiplayer_peer_init"
compatibility_minimum = 4.2
[libraries]
linux.debug.x86_64 = "./linux/libsteam-multiplayer-peer.linux.template_debug.x86_64.so"
linux.release.x86_64 = "./linux/libsteam-multiplayer-peer.linux.template_release.x86_64.so"
linux.debug.arm64 = "./linux/libsteam-multiplayer-peer.linux.template_debug.arm64.so"
linux.release.arm64 = "./linux/libsteam-multiplayer-peer.linux.template_release.arm64.so"
linux.debug.rv64 = "./linux/libsteam-multiplayer-peer.linux.template_debug.rv64.so"
linux.release.rv64 = "./linux/libsteam-multiplayer-peer.linux.template_release.rv64.so"
macos.debug = "./macos/libsteam-multiplayer-peer.macos.template_debug.universal.dylib"
macos.release = "./macos/libsteam-multiplayer-peer.macos.template_release.universal.dylib"
windows.debug.x86_32 = "./windows/steam-multiplayer-peer.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "./windows/steam-multiplayer-peer.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "./windows/steam-multiplayer-peer.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "./windows/steam-multiplayer-peer.windows.template_release.x86_64.dll"
[dependencies]
linux.x86_64 = { "linux/libsteam_api.so": "" }
linux.arm64 = { "linux/libsteam_api.so": "" }
linux.rv64 = { "linux/libsteam_api.so": "" }
macos.universal = { "macos/libsteam_api.dylib": "" }
windows.x86_64 = { "windows/steam_api64.dll": "" }
windows.x86_32 = { "windows/steam_api.dll": "" }

View File

@@ -0,0 +1 @@
uid://bift3vevfew3v

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,53 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ceovc780lyj1r"
path="res://.godot/imported/campfire.blend-0f4f394f7ed7f3b3e2d3c3ac81a19ebb.scn"
[deps]
source_file="res://levels/lobby-scene/campfire/campfire.blend"
dest_files=["res://.godot/imported/campfire.blend-0f4f394f7ed7f3b3e2d3c3ac81a19ebb.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
blender/nodes/visible=0
blender/nodes/active_collection_only=false
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/export_geometry_nodes_instances=false
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

View File

@@ -0,0 +1,22 @@
extends Node3D
@export var campfire_lit: bool = false
@export var fire_particles: GPUParticles3D
@export var smoke_particles: GPUParticles3D
@export var audio_stream_player_3d: AudioStreamPlayer3D
@export var sfx_files: Array[AudioStreamWAV] = []
func _ready() -> void:
audio_stream_player_3d.finished.connect(play_random_sfx)
play_random_sfx()
func light_campfire():
fire_particles.emitting = true
smoke_particles.emitting = true
func play_random_sfx():
audio_stream_player_3d.stream = sfx_files.pick_random()
audio_stream_player_3d.play()

View File

@@ -0,0 +1 @@
uid://mjtng3tgusx0

View File

@@ -0,0 +1,144 @@
[gd_scene load_steps=19 format=3 uid="uid://wcsd1tb0quj3"]
[ext_resource type="PackedScene" uid="uid://ceovc780lyj1r" path="res://levels/lobby-scene/campfire/campfire.blend" id="1_5k61m"]
[ext_resource type="Script" uid="uid://mjtng3tgusx0" path="res://levels/lobby-scene/campfire/campfire.gd" id="1_pgdjc"]
[ext_resource type="Texture2D" uid="uid://ciegdylo5csyt" path="res://levels/lobby-scene/campfire/textures/smoke-particle-texture.png" id="2_4swet"]
[ext_resource type="AudioStream" uid="uid://bx01sxorforuo" path="res://levels/lobby-scene/campfire/fire.wav" id="4_u2sse"]
[sub_resource type="Gradient" id="Gradient_5k61m"]
offsets = PackedFloat32Array(0.175439, 0.859649)
colors = PackedColorArray(0, 0, 0, 1, 0.52549, 0.180392, 0.0745098, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_4swet"]
gradient = SubResource("Gradient_5k61m")
[sub_resource type="Curve" id="Curve_pgdjc"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.25, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.393258), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_wwyeu"]
curve = SubResource("Curve_pgdjc")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_js7yv"]
angle_min = 1.07288e-05
angle_max = 360.0
direction = Vector3(0, 1, 0)
spread = 0.0
initial_velocity_min = 1.0
initial_velocity_max = 4.0
angular_velocity_min = -1.60933e-05
angular_velocity_max = 40.0
gravity = Vector3(0, 0, 0)
linear_accel_min = 0.999998
linear_accel_max = 5.0
scale_min = 0.1
scale_max = 0.6
scale_curve = SubResource("CurveTexture_wwyeu")
color_initial_ramp = SubResource("GradientTexture1D_4swet")
hue_variation_min = -1.0
hue_variation_max = -0.75
turbulence_enabled = true
turbulence_noise_strength = 0.1
turbulence_noise_scale = 10.0
turbulence_influence_min = 0.01
turbulence_influence_max = 0.03
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5k61m"]
transparency = 1
blend_mode = 1
shading_mode = 0
disable_fog = true
vertex_color_use_as_albedo = true
albedo_color = Color(0.352941, 0.117647, 0.0666667, 1)
billboard_mode = 3
billboard_keep_scale = true
particles_anim_h_frames = 1
particles_anim_v_frames = 1
particles_anim_loop = false
[sub_resource type="QuadMesh" id="QuadMesh_p40iq"]
material = SubResource("StandardMaterial3D_5k61m")
[sub_resource type="Gradient" id="Gradient_4swet"]
offsets = PackedFloat32Array(0.175439, 1)
[sub_resource type="GradientTexture1D" id="GradientTexture1D_pgdjc"]
gradient = SubResource("Gradient_4swet")
[sub_resource type="Curve" id="Curve_wwyeu"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.25, 1), 0.0, 0.0, 0, 0, Vector2(1, 0.393258), 0.0, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_js7yv"]
curve = SubResource("Curve_wwyeu")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_0feaq"]
angle_min = 1.07288e-05
angle_max = 360.0
direction = Vector3(0, 1, 0)
spread = 0.0
initial_velocity_min = 1.0
initial_velocity_max = 4.0
angular_velocity_min = -1.60933e-05
angular_velocity_max = 40.0
gravity = Vector3(0, 0, 0)
linear_accel_min = 0.999998
linear_accel_max = 2.0
scale_min = 0.1
scale_curve = SubResource("CurveTexture_js7yv")
color_initial_ramp = SubResource("GradientTexture1D_pgdjc")
hue_variation_min = -2.23517e-08
hue_variation_max = 0.03
turbulence_enabled = true
turbulence_noise_strength = 0.1
turbulence_noise_scale = 1.76
turbulence_influence_min = 0.01
turbulence_influence_max = 0.01
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_p40iq"]
transparency = 1
shading_mode = 0
vertex_color_use_as_albedo = true
albedo_texture = ExtResource("2_4swet")
billboard_mode = 3
billboard_keep_scale = true
particles_anim_h_frames = 1
particles_anim_v_frames = 1
particles_anim_loop = false
[sub_resource type="QuadMesh" id="QuadMesh_8eekk"]
material = SubResource("StandardMaterial3D_p40iq")
[node name="Campfire" type="Node3D" node_paths=PackedStringArray("fire_particles", "smoke_particles", "audio_stream_player_3d")]
script = ExtResource("1_pgdjc")
fire_particles = NodePath("FireParticles")
smoke_particles = NodePath("SmokeParticles")
audio_stream_player_3d = NodePath("AudioStreamPlayer3D")
sfx_files = Array[AudioStreamWAV]([ExtResource("4_u2sse")])
[node name="campfire" parent="." instance=ExtResource("1_5k61m")]
[node name="FireParticles" type="GPUParticles3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0211215, 0.220129, -0.0153611)
amount = 500
lifetime = 0.3
explosiveness = 0.08
randomness = 1.0
draw_order = 3
process_material = SubResource("ParticleProcessMaterial_js7yv")
draw_pass_1 = SubResource("QuadMesh_p40iq")
[node name="SmokeParticles" type="GPUParticles3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0211215, 0.220129, -0.0153611)
amount = 100
lifetime = 2.0
explosiveness = 0.06
randomness = 1.0
draw_order = 3
process_material = SubResource("ParticleProcessMaterial_0feaq")
draw_pass_1 = SubResource("QuadMesh_8eekk")
[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D" parent="."]
stream = ExtResource("4_u2sse")
volume_db = -15.0
unit_size = 5.0

Binary file not shown.

View File

@@ -0,0 +1,24 @@
[remap]
importer="wav"
type="AudioStreamWAV"
uid="uid://bx01sxorforuo"
path="res://.godot/imported/fire.wav-db183a1afec86c3f7b0347a0f68a8c78.sample"
[deps]
source_file="res://levels/lobby-scene/campfire/fire.wav"
dest_files=["res://.godot/imported/fire.wav-db183a1afec86c3f7b0347a0f68a8c78.sample"]
[params]
force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=2

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bjlwlqwdnhyqa"
path.s3tc="res://.godot/imported/ashes.png-e3ed397e6960eee2c0384b2e7628d89b.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/campfire/textures/ashes.png"
dest_files=["res://.godot/imported/ashes.png-e3ed397e6960eee2c0384b2e7628d89b.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.

After

Width:  |  Height:  |  Size: 226 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://mwhsj8t5w8u2"
path.s3tc="res://.godot/imported/log.png-dedb4a0d507c4374c4a0430aa0b04240.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/campfire/textures/log.png"
dest_files=["res://.godot/imported/log.png-dedb4a0d507c4374c4a0430aa0b04240.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.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://ciegdylo5csyt"
path.s3tc="res://.godot/imported/smoke-particle-texture.png-a6c9ad64e49d68633ab3bfabe9f168c2.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/campfire/textures/smoke-particle-texture.png"
dest_files=["res://.godot/imported/smoke-particle-texture.png-a6c9ad64e49d68633ab3bfabe9f168c2.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.

After

Width:  |  Height:  |  Size: 194 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cwwjn82mmy6oc"
path.s3tc="res://.godot/imported/stone.png-282edc18bd8fc87daf754e087f67344d.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/campfire/textures/stone.png"
dest_files=["res://.godot/imported/stone.png-282edc18bd8fc87daf754e087f67344d.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

View File

@@ -1,8 +1,10 @@
[gd_scene load_steps=7 format=3 uid="uid://bj52j4ew2lfr6"]
[gd_scene load_steps=9 format=3 uid="uid://bj52j4ew2lfr6"]
[ext_resource type="PackedScene" uid="uid://5vggmy1srgxb" path="res://tools/human-height-reference.tscn" id="1_yyu2g"]
[ext_resource type="PackedScene" uid="uid://daq1prwl8aaia" path="res://tools/debug.tscn" id="2_72fkp"]
[ext_resource type="PackedScene" uid="uid://b5xb0fsfpn7r3" path="res://levels/lobby-scene/lobby-terrain.blend" id="3_f73ky"]
[ext_resource type="PackedScene" uid="uid://csmfxg011xisf" path="res://player/Player.tscn" id="4_0aw1h"]
[ext_resource type="PackedScene" uid="uid://c4cew4af3h306" path="res://levels/lobby-scene/tent/tent.blend" id="4_qjimh"]
[ext_resource type="PackedScene" uid="uid://wcsd1tb0quj3" path="res://levels/lobby-scene/campfire/campfire.tscn" id="5_qjimh"]
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_f73ky"]
@@ -12,6 +14,12 @@ sky_material = SubResource("ProceduralSkyMaterial_f73ky")
[sub_resource type="Environment" id="Environment_72fkp"]
background_mode = 2
sky = SubResource("Sky_0aw1h")
ssao_enabled = true
ssil_enabled = true
sdfgi_use_occlusion = true
glow_enabled = true
volumetric_fog_enabled = true
volumetric_fog_density = 0.0
[node name="Lobby" type="Node3D"]
@@ -21,10 +29,45 @@ environment = SubResource("Environment_72fkp")
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="WorldEnvironment"]
transform = Transform3D(0.915754, 0.29917, -0.268128, 0.115653, 0.442845, 0.889108, 0.384733, -0.845214, 0.370937, 0, 0, 0)
shadow_enabled = true
shadow_transmittance_bias = 5.628
[node name="Human-height-reference" parent="." instance=ExtResource("1_yyu2g")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3.33741, 0.953, -5.00694)
[node name="Debug" parent="." instance=ExtResource("2_72fkp")]
[node name="lobby-terrain" parent="." instance=ExtResource("3_f73ky")]
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."]
_spawnable_scenes = PackedStringArray("uid://csmfxg011xisf")
spawn_path = NodePath("../Marker3D")
spawn_limit = 1
[node name="Marker3D" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.269072, -8.35164)
[node name="Player" parent="." instance=ExtResource("4_0aw1h")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.444747, 0.992996, -4.71496)
[node name="Campsite" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15.724, 0, -17.6721)
[node name="TentPlot1" type="Marker3D" parent="Campsite"]
transform = Transform3D(-0.998887, 0, -0.0471587, 0, 1, 0, 0.0471587, 0, -0.998887, -0.468871, 0, -6.31805)
[node name="tent" parent="Campsite/TentPlot1" instance=ExtResource("4_qjimh")]
[node name="TentPlot2" type="Marker3D" parent="Campsite"]
transform = Transform3D(-0.240973, 0, -0.970532, 0, 1, 0, 0.970532, 0, -0.240973, -6.46887, 0, -2.31805)
[node name="tent" parent="Campsite/TentPlot2" instance=ExtResource("4_qjimh")]
[node name="TentPlot3" type="Marker3D" parent="Campsite"]
transform = Transform3D(0.689594, 0, -0.724196, 0, 1, 0, 0.724196, 0, 0.689594, -4.46887, 0, 4.68195)
[node name="tent" parent="Campsite/TentPlot3" instance=ExtResource("4_qjimh")]
[node name="TentPlot4" type="Marker3D" parent="Campsite"]
transform = Transform3D(-0.0217975, 0, 0.999762, 0, 1, 0, -0.999762, 0, -0.0217975, 6.53113, 0, -2.31805)
[node name="tent" parent="Campsite/TentPlot4" instance=ExtResource("4_qjimh")]
[node name="Campfire" parent="Campsite" instance=ExtResource("5_qjimh")]

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,53 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://c4cew4af3h306"
path="res://.godot/imported/tent.blend-cfe1cab2c3640ecea475631183f479bf.scn"
[deps]
source_file="res://levels/lobby-scene/tent/tent.blend"
dest_files=["res://.godot/imported/tent.blend-cfe1cab2c3640ecea475631183f479bf.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=1.0
nodes/import_as_skeleton_bones=false
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={}
blender/nodes/visible=0
blender/nodes/active_collection_only=false
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/export_geometry_nodes_instances=false
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bj1old20eraxq"
path.s3tc="res://.godot/imported/line.png-f1d79c528b79a3f4f23586b0c1ab0a22.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/tent/textures/line.png"
dest_files=["res://.godot/imported/line.png-f1d79c528b79a3f4f23586b0c1ab0a22.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.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://4wydw131ad3q"
path.s3tc="res://.godot/imported/pins.png-be03801b8319596d167e68e302ab146f.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/tent/textures/pins.png"
dest_files=["res://.godot/imported/pins.png-be03801b8319596d167e68e302ab146f.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.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -0,0 +1,35 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://by6dlbdsfkf1c"
path.s3tc="res://.godot/imported/tent-canvas.png-22002e3ff42d8a628cf6a049cdff6002.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
[deps]
source_file="res://levels/lobby-scene/tent/textures/tent-canvas.png"
dest_files=["res://.godot/imported/tent-canvas.png-22002e3ff42d8a628cf6a049cdff6002.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.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://httteb3u35qr"
path.s3tc="res://.godot/imported/line.png-1b1fccbe8a0fdb9beb81829cbd429a35.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://levels/lobby-scene/textures/line.png"
dest_files=["res://.godot/imported/line.png-1b1fccbe8a0fdb9beb81829cbd429a35.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.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://dd8afqm2eo5tb"
path.s3tc="res://.godot/imported/pins.png-9e7d62b7100f3992201f360fd11b8753.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://levels/lobby-scene/textures/pins.png"
dest_files=["res://.godot/imported/pins.png-9e7d62b7100f3992201f360fd11b8753.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.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -0,0 +1,36 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://oemi5vymwrij"
path.s3tc="res://.godot/imported/tent-canvas.png-eb337bb8ec4691a22e92d3af49a9828d.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={}
[deps]
source_file="res://levels/lobby-scene/textures/tent-canvas.png"
dest_files=["res://.godot/imported/tent-canvas.png-eb337bb8ec4691a22e92d3af49a9828d.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

View File

@@ -0,0 +1 @@
extends Node

View File

@@ -0,0 +1 @@
uid://ckuxhcwgtsrsp

View File

@@ -0,0 +1,296 @@
extends Node
var is_owned: bool = false
var steam_app_id: int = 480
var steam_id: int = 0
var steam_username: String = ""
var lobby_id = 0
var lobby_max_members = 4
var lobby_members: Array = []
var steam_initialized: bool = false
var peer: SteamMultiplayerPeer
func _ready() -> void:
OS.set_environment("SteamAppId", str(steam_app_id))
OS.set_environment("SteamGameId", str(steam_app_id))
steam_initialized = init_steam()
if not steam_initialized:
print("!!! Steam did not initialize. Multiplayer will be disabled.")
return
# Connect Steam lobby signals
Steam.lobby_created.connect(_on_lobby_created)
Steam.lobby_joined.connect(_on_lobby_joined)
#Steam.lobby_match_list.connect(_on_lobby_match_list)
Steam.lobby_chat_update.connect(_on_lobby_chat_update)
Steam.lobby_data_update.connect(_on_lobby_data_update)
#Steam.join_requested.connect(_on_lobby_join_requested)
Steam.persona_state_change.connect(_on_persona_change)
# Setup multiplayer signals
multiplayer.peer_connected.connect(_on_peer_connected)
multiplayer.peer_disconnected.connect(_on_peer_disconnected)
multiplayer.connected_to_server.connect(_on_connected_to_server)
multiplayer.connection_failed.connect(_on_connection_failed)
multiplayer.server_disconnected.connect(_on_server_disconnected)
Steam.p2p_session_request.connect(_on_p2p_session_request)
check_command_line()
func _on_p2p_session_request(steam_id_remote: int) -> void:
## ADDED: More detailed logging to confirm P2P acceptance.
print("[P2P] ==> Session request from: %s. Accepting." % steam_id_remote)
var accepted = Steam.acceptP2PSessionWithUser(steam_id_remote)
if not accepted:
print("[P2P] !!! Failed to accept P2P session with %s." % steam_id_remote)
func _process(delta):
## ADDED: Guard clause in case Steam fails to initialize.
if not steam_initialized:
return
Steam.run_callbacks()
if Input.is_action_just_pressed("interact"):
## ADDED: Replaced simple print with a detailed diagnostic function.
log_multiplayer_info()
func check_command_line() -> void:
var args: Array = OS.get_cmdline_args()
if args.size() > 0:
if args[0] == "+connect_lobby":
if args.size() > 1 and int(args[1]) > 0:
print("Command line lobby ID: %s" % args[1])
join_lobby(int(args[1]))
func init_steam() -> bool:
var response: Dictionary = Steam.steamInitEx()
print("Steam init response: %s " % response)
if response['status'] > 0:
print("!!! Failed to init steam! Code: %s " % response)
return false
is_owned = Steam.isSubscribed()
steam_id = Steam.getSteamID()
steam_username = Steam.getPersonaName()
print("Steam initialized successfully for %s (ID: %s)." % [steam_username, steam_id])
if !is_owned:
print("!!! WARNING: Steam reports you do not own App ID %s." % steam_app_id)
# You might want to return false here in a real game
# return false
return true
func setup_multiplayer_peer(is_host: bool = false) -> void:
## ADDED: Check if a peer is already active before creating a new one.
if multiplayer.multiplayer_peer and multiplayer.multiplayer_peer.get_connection_status() != MultiplayerPeer.CONNECTION_DISCONNECTED:
print("[Multiplayer] Peer already exists. Disconnecting old one.")
multiplayer.multiplayer_peer.close()
peer = SteamMultiplayerPeer.new()
if is_host:
print("[Multiplayer] Creating Host...")
var err = peer.create_host(0) ## REMOVED: Channel is handled by the peer automatically now.
if err != OK:
print("[Multiplayer] !!! Failed to create host. Error: %s" % err)
return
multiplayer.multiplayer_peer = peer
print("[Multiplayer] Host created successfully. My Peer ID: %s" % multiplayer.get_unique_id())
else:
if lobby_id == 0:
print("[Multiplayer] !!! Cannot create client, not in a lobby.")
return
var host_id = Steam.getLobbyOwner(lobby_id)
print("[Multiplayer] Creating Client, attempting to connect to host: %s" % host_id)
var err = peer.create_client(host_id, 0) ## REMOVED: Channel is handled by the peer automatically.
if err != OK:
print("[Multiplayer] !!! Failed to create client. Error: %s" % err)
return
multiplayer.multiplayer_peer = peer
print("[Multiplayer] Client peer created. Waiting for connection...")
func create_lobby():
if lobby_id == 0:
print("Creating lobby...")
Steam.createLobby(Steam.LOBBY_TYPE_FRIENDS_ONLY, lobby_max_members)
func _on_lobby_created(connect: int, this_lobby_id: int):
if connect == 1:
lobby_id = this_lobby_id
print("Lobby created with id `%s`" % lobby_id)
Steam.setLobbyJoinable(lobby_id, true)
Steam.setLobbyData(lobby_id, "name", steam_username + "'s Lobby")
Steam.setLobbyData(lobby_id, "mode", "Splunk")
Steam.allowP2PPacketRelay(true)
setup_multiplayer_peer(true) # Setup as host
else :
print("!!! Failed to create lobby.")
func join_lobby(this_lobby_id: int):
print("Attempting to join lobby: %s" % this_lobby_id)
lobby_members.clear()
Steam.joinLobby(this_lobby_id)
func _on_lobby_joined(this_lobby_id: int, permissions: int, locked: bool, response: int):
if response == Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS:
lobby_id = this_lobby_id
print("Successfully joined lobby: %s" % lobby_id)
get_lobby_members()
# FIXED: Use Steam.getLobbyOwner() to determine if we should be host or client
var lobby_owner_id = Steam.getLobbyOwner(lobby_id)
var am_i_owner = (lobby_owner_id == steam_id)
print("[Multiplayer] Lobby Owner: %s, My Steam ID: %s, Am I Owner?: %s" % [lobby_owner_id, steam_id, am_i_owner])
if not am_i_owner:
print("[Multiplayer] I am not the lobby owner, setting up as client...")
setup_multiplayer_peer(false) # Setup as client
else:
print("[Multiplayer] I am the lobby owner, but multiplayer peer should already be set up as host.")
else:
## ADDED: Log the specific reason for the join failure.
print("!!! Failed to join lobby. Reason: %s" % get_join_fail_reason(response))
func get_lobby_members() -> void:
lobby_members.clear()
if lobby_id == 0: return
var num_members = Steam.getNumLobbyMembers(lobby_id)
print("--- Refreshing Lobby Members (%s) ---" % num_members)
for i in range(num_members):
var member_id = Steam.getLobbyMemberByIndex(lobby_id, i)
var member_name = Steam.getFriendPersonaName(member_id)
lobby_members.append({
"steam_id": member_id,
"steam_name": member_name
})
print(" - %s (%s)" % [member_name, member_id])
print("---------------------------------")
func _on_lobby_data_update(lobby: int, user: int, success: int) -> void:
if success:
if lobby == user:
print("Lobby data for lobby %s has been updated." % lobby)
var lobby_name = Steam.getLobbyData(lobby, "name")
print(" > New lobby name: %s" % lobby_name)
else:
print("Data for member %s in lobby %s has been updated." % [user, lobby])
func _on_persona_change(steam_id_changed: int, flag: int) -> void:
# This can be spammy, but useful for debugging name changes.
# print("Persona state changed for %s. Refreshing lobby members." % steam_id_changed)
get_lobby_members()
func leave_lobby() -> void:
pass
func _on_lobby_chat_update(lobby_id_update: int, user_changed_id: int, user_making_change_id: int, chat_state: int):
var state_string = "UNKNOWN"
match chat_state:
Steam.CHAT_MEMBER_STATE_CHANGE_ENTERED: state_string = "ENTERED"
Steam.CHAT_MEMBER_STATE_CHANGE_LEFT: state_string = "LEFT"
Steam.CHAT_MEMBER_STATE_CHANGE_DISCONNECTED: state_string = "DISCONNECTED"
Steam.CHAT_MEMBER_STATE_CHANGE_KICKED: state_string = "KICKED"
Steam.CHAT_MEMBER_STATE_CHANGE_BANNED: state_string = "BANNED"
print("[Lobby] Chat Update: User %s has %s." % [user_changed_id, state_string])
# Any change in lobby membership should trigger a refresh.
get_lobby_members()
func _on_peer_connected(id: int) -> void:
print("[Multiplayer] ✅ Peer connected: %s" % id)
# It's good practice to re-check lobby members when a peer connects successfully.
get_lobby_members()
func _on_peer_disconnected(id: int) -> void:
print("[Multiplayer] ❌ Peer disconnected: %s" % id)
func _on_connected_to_server() -> void:
print("[Multiplayer] ✅ Successfully connected to the host.")
print("[Multiplayer] - My Peer ID is now: %s" % multiplayer.get_unique_id())
func _on_connection_failed() -> void:
print("[Multiplayer] ❌ Connection to the host failed.")
func _on_server_disconnected() -> void:
print("[Multiplayer] ❌ Disconnected from the host.")
## ADDED: New function to log all relevant multiplayer and lobby information.
func log_multiplayer_info():
print("\n--- DIAGNOSTIC INFO ---")
print("## Multiplayer Status:")
if multiplayer.multiplayer_peer:
print(" - Peer State: Active")
print(" - Connection Status: %s" % get_connection_status_string(multiplayer.multiplayer_peer.get_connection_status()))
print(" - Is Server?: %s" % multiplayer.is_server())
print(" - My Peer ID: %s" % multiplayer.get_unique_id())
print(" - Connected Peer IDs: %s" % multiplayer.get_peers())
else:
print(" - Peer State: Inactive (null)")
print("\n## Steam Lobby Info:")
print(" - In Lobby?: %s" % (lobby_id != 0))
print(" - Lobby ID: %s" % lobby_id)
if lobby_id != 0:
print(" - Lobby Owner Steam ID: %s" % Steam.getLobbyOwner(lobby_id))
print(" - My Steam ID: %s" % steam_id)
print(" - Lobby Members Array (%s):" % lobby_members.size())
for member in lobby_members:
print(" - %s (%s)" % [member.steam_name, member.steam_id])
print("-------------------------\n")
## ADDED: Helper function to get a human-readable string for connection status.
func get_connection_status_string(status: int) -> String:
match status:
MultiplayerPeer.CONNECTION_DISCONNECTED: return "Disconnected"
MultiplayerPeer.CONNECTION_CONNECTING: return "Connecting"
MultiplayerPeer.CONNECTION_CONNECTED: return "Connected"
_: return "Unknown Status"
func get_join_fail_reason(response: int) -> String:
match response:
Steam.CHAT_ROOM_ENTER_RESPONSE_DOESNT_EXIST: return "Lobby no longer exists"
Steam.CHAT_ROOM_ENTER_RESPONSE_NOT_ALLOWED: return "Not allowed to join"
Steam.CHAT_ROOM_ENTER_RESPONSE_FULL: return "Lobby is full"
Steam.CHAT_ROOM_ENTER_RESPONSE_ERROR: return "Unknown error"
Steam.CHAT_ROOM_ENTER_RESPONSE_BANNED: return "You are banned"
Steam.CHAT_ROOM_ENTER_RESPONSE_LIMITED: return "Limited account"
Steam.CHAT_ROOM_ENTER_RESPONSE_CLAN_DISABLED: return "Lobby is locked"
Steam.CHAT_ROOM_ENTER_RESPONSE_COMMUNITY_BAN: return "Community locked"
Steam.CHAT_ROOM_ENTER_RESPONSE_MEMBER_BLOCKED_YOU: return "A member blocked you"
Steam.CHAT_ROOM_ENTER_RESPONSE_YOU_BLOCKED_MEMBER: return "You blocked a member"
_: return "Unknown reason"

View File

@@ -0,0 +1 @@
uid://bhsxbic5qkkmg

View File

@@ -1,3 +1,78 @@
[gd_scene format=3 uid="uid://csmfxg011xisf"]
[gd_scene load_steps=8 format=3 uid="uid://csmfxg011xisf"]
[node name="Player" type="Node3D"]
[ext_resource type="Script" uid="uid://dopyfulbw2mx5" path="res://player/player.gd" id="1_ulp21"]
[ext_resource type="PackedScene" uid="uid://8phs2e161db1" path="res://ui/multiplayer-debug-ui/multiplayer-debug-ui.tscn" id="2_3c3w1"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_ehsmr"]
[sub_resource type="CapsuleMesh" id="CapsuleMesh_ulp21"]
radius = 0.3
height = 1.5
[sub_resource type="PrismMesh" id="PrismMesh_3c3w1"]
size = Vector3(0.5, 0.5, 0.5)
[sub_resource type="SphereMesh" id="SphereMesh_wnvi2"]
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_ulp21"]
properties/0/path = NodePath(".:position")
properties/0/spawn = true
properties/0/replication_mode = 2
properties/1/path = NodePath(".:rotation")
properties/1/spawn = true
properties/1/replication_mode = 2
properties/2/path = NodePath("Label3D:text")
properties/2/spawn = true
properties/2/replication_mode = 1
[node name="Player" type="CharacterBody3D"]
collision_layer = 2
collision_mask = 3
script = ExtResource("1_ulp21")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.399442, 0.0644827)
cull_mask = 1048573
current = true
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("CapsuleShape3D_ehsmr")
[node name="Mesh" type="Node3D" parent="."]
transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, 0)
[node name="MeshInstance3D" type="MeshInstance3D" parent="Mesh"]
transform = Transform3D(1, 0, 0, 0, 0.89961, 0, 0, 0, 1, 0, -0.318288, 0)
layers = 2
mesh = SubResource("CapsuleMesh_ulp21")
skeleton = NodePath("../..")
[node name="MeshInstance3D2" type="MeshInstance3D" parent="Mesh"]
transform = Transform3D(1.41676, 0, 0, 0, 1.31718, 0, 0, 0, 1.22029, 0, 0.415995, 0)
layers = 2
mesh = SubResource("PrismMesh_3c3w1")
skeleton = NodePath("../..")
[node name="MeshInstance3D3" type="MeshInstance3D" parent="Mesh"]
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, -0.0855882, 0.409407, 0.293333)
layers = 2
mesh = SubResource("SphereMesh_wnvi2")
skeleton = NodePath("../..")
[node name="MeshInstance3D4" type="MeshInstance3D" parent="Mesh"]
transform = Transform3D(0.1, 0, 0, 0, 0.1, 0, 0, 0, 0.1, 0.0770122, 0.409407, 0.293333)
layers = 2
mesh = SubResource("SphereMesh_wnvi2")
skeleton = NodePath("../..")
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_ulp21")
[node name="Label3D" type="Label3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.887858, 0)
billboard = 1
text = "Username"
[node name="CanvasLayer" type="CanvasLayer" parent="."]
[node name="Multiplayer-debug-ui" parent="CanvasLayer" instance=ExtResource("2_3c3w1")]

60
splunk/player/player.gd Normal file
View File

@@ -0,0 +1,60 @@
extends CharacterBody3D
@export var speed = 5.0
@export var jump_velocity = 4.5
@export var mouse_sensitivity = 0.002
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var camera_node: Camera3D
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
camera_node = $Camera3D # Assuming Camera3D is a direct child
$Label3D.text = SteamManager.steam_username
func _physics_process(delta):
# Apply gravity
if not is_on_floor():
velocity.y -= gravity * delta
# Handle Jump
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
# Get the input direction and apply movement
var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if is_on_floor():
if direction:
velocity.x = direction.x * speed
velocity.z = direction.z * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
velocity.z = move_toward(velocity.z, 0, speed)
else:
# Air control
velocity.x = lerp(velocity.x, direction.x * speed, delta * 5.0)
velocity.z = lerp(velocity.z, direction.z * speed, delta * 5.0)
move_and_slide()
func _input(event):
if event is InputEventMouseMotion:
# Rotate the CharacterBody3D around the Y-axis for horizontal look
rotate_y(-event.relative.x * mouse_sensitivity)
# Rotate the Camera3D around its local X-axis for vertical look
var change = -event.relative.y * mouse_sensitivity
var new_x_rotation = camera_node.rotation.x + change
camera_node.rotation.x = clamp(new_x_rotation, deg_to_rad(-90), deg_to_rad(90))
if event.is_action_pressed("ui_cancel"): # Typically Escape key
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
if event.is_action_pressed("toggle_watch"):
$"CanvasLayer/Multiplayer-debug-ui".visible = !$"CanvasLayer/Multiplayer-debug-ui".visible

View File

@@ -0,0 +1 @@
uid://dopyfulbw2mx5

View File

@@ -15,6 +15,10 @@ run/main_scene="uid://bj52j4ew2lfr6"
config/features=PackedStringArray("4.4", "Forward Plus")
config/icon="res://icon.svg"
[autoload]
SteamManager="*res://networking/steam-manager.gd"
[editor_plugins]
enabled=PackedStringArray("res://addons/freecam_3D/plugin.cfg")
@@ -24,10 +28,80 @@ enabled=PackedStringArray("res://addons/freecam_3D/plugin.cfg")
folder_colors={
"res://items/": "yellow",
"res://levels/": "green",
"res://networking/": "teal",
"res://player/": "purple",
"res://tools/": "gray"
"res://tools/": "gray",
"res://ui/": "red"
}
[input]
move_left={
"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)
]
}
move_right={
"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)
]
}
move_forward={
"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":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
]
}
move_backward={
"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)
]
}
jump={
"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":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null)
]
}
toggle_watch={
"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":4194306,"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)
]
}
toggle_bag={
"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":66,"key_label":0,"unicode":98,"location":0,"echo":false,"script":null)
]
}
inv_slot_1={
"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":49,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)
]
}
inv_slot_2={
"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":50,"key_label":0,"unicode":50,"location":0,"echo":false,"script":null)
]
}
inv_slot_3={
"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":51,"key_label":0,"unicode":51,"location":0,"echo":false,"script":null)
]
}
inv_slot_4={
"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":52,"key_label":0,"unicode":52,"location":0,"echo":false,"script":null)
]
}
[layer_names]
3d_render/layer_2="player"
3d_physics/layer_2="player"
[physics]
3d/physics_engine="Jolt Physics"

View File

@@ -0,0 +1,96 @@
[gd_scene load_steps=3 format=3 uid="uid://8phs2e161db1"]
[ext_resource type="Script" uid="uid://cfkrrnsqwx0cv" path="res://ui/multiplayer-debug-ui/multiplayer_debug_ui.gd" id="1_h2vp3"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_c6gl5"]
bg_color = Color(0, 0, 0, 0.580392)
expand_margin_left = 5.0
expand_margin_right = 5.0
[node name="Multiplayer-debug-ui" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_h2vp3")
[node name="ColorRect" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0, 0, 0, 0.313726)
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 50
alignment = 1
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
theme_override_constants/separation = 10
alignment = 1
[node name="Host" type="Button" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "HOST"
[node name="InviteButton" type="Button" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "INVITE"
[node name="QuitButton" type="Button" parent="HBoxContainer/VBoxContainer"]
layout_mode = 2
text = "QUIT
"
[node name="VBoxContainer2" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
theme_override_constants/margin_top = 280
[node name="LobbyCountLabel" type="Label" parent="HBoxContainer/VBoxContainer2/MarginContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 20
text = "Players in lobby 0/4"
horizontal_alignment = 1
vertical_alignment = 1
[node name="Panel" type="Panel" parent="HBoxContainer/VBoxContainer2"]
layout_mode = 2
size_flags_vertical = 3
theme_override_styles/panel = SubResource("StyleBoxFlat_c6gl5")
[node name="PlayerNameContainer" type="VBoxContainer" parent="HBoxContainer/VBoxContainer2/Panel"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer3" type="VBoxContainer" parent="HBoxContainer"]
layout_mode = 2
alignment = 1
[node name="TextEdit" type="LineEdit" parent="HBoxContainer/VBoxContainer3"]
custom_minimum_size = Vector2(200, 20)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
placeholder_text = "Lobby ID"
[node name="Button" type="Button" parent="HBoxContainer/VBoxContainer3"]
layout_mode = 2
text = "Join"

View File

@@ -0,0 +1,41 @@
extends Control
@export var lobby_count_label: Label
@export var PlayerNameContainer: VBoxContainer
@export var playername_array: Array[String] = []
func _ready() -> void:
$HBoxContainer/VBoxContainer/Host.pressed.connect(host_game)
$HBoxContainer/VBoxContainer3/Button.pressed.connect(join_game)
func join_game():
var lobby_id = $HBoxContainer/VBoxContainer3/TextEdit.text
if int(lobby_id) > 0:
SteamManager.join_lobby(int(lobby_id))
func host_game():
SteamManager.create_lobby()
func add_new_player(playername: String, total_player_count: int):
var new_playername_label = Label.new()
new_playername_label.text = playername
new_playername_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
new_playername_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
new_playername_label.name = playername
playername_array.append(playername)
PlayerNameContainer.add_child(new_playername_label)
lobby_count_label.text = "Players in lobby " + str(total_player_count) + "/4"
func delete_player(playername: String, total_player_count: int):
for playername_index in playername_array:
if playername_index == playername:
playername_array.erase(playername_index)
var playername_node_for_deletion = PlayerNameContainer.find_child(playername)
playername_node_for_deletion.queue_free()
lobby_count_label.text = "Players in lobby " + str(total_player_count) + "/4"

View File

@@ -0,0 +1 @@
uid://cfkrrnsqwx0cv