Skip to content

Commit e64dd06

Browse files
authored
Merge pull request #10 from Code-Fixxers/fix/network-example-cleanup-101370867382778011
Fix example network client disconnect cleanup & CN_NetworkIdentity typo
2 parents 29004f2 + 8af4cd0 commit e64dd06

9 files changed

Lines changed: 29 additions & 30 deletions

File tree

PR_DESCRIPTION.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ func _init() -> void:
7575

7676
### Components
7777
- `C_NetworkIdentity` - Authority and ownership tracking
78-
- `C_SyncEntity` - Enables continuous synchronization
79-
- `C_LocalAuthority` - Marker for locally controlled entities
78+
- `CN_SyncEntity` - Enables continuous synchronization
79+
- `CN_LocalAuthority` - Marker for locally controlled entities
8080
- `C_RemoteEntity` - Marker for remotely controlled entities
8181
- `C_ServerOwned` - Marker for server-owned entities
8282

example_network/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@ A minimal multiplayer example demonstrating the GECS Network addon's two synchro
55
## Features Demonstrated
66

77
### 1. Continuous Sync (Players)
8-
Players use `C_SyncEntity` which enables Godot's native `MultiplayerSynchronizer` for real-time position updates.
8+
Players use `CN_SyncEntity` which enables Godot's native `MultiplayerSynchronizer` for real-time position updates.
99

1010
```gdscript
1111
# e_player.gd
1212
func define_components() -> Array:
1313
return [
1414
C_NetVelocity.new(),
1515
C_PlayerInput.new(),
16-
C_SyncEntity.new(true, true, false), # sync position + rotation
16+
CN_SyncEntity.new(true, true, false), # sync position + rotation
1717
]
1818
```
1919

2020
### 2. Spawn-Only Sync (Projectiles)
21-
Projectiles do NOT have `C_SyncEntity`. The server spawns them and broadcasts component values once - then all clients simulate locally.
21+
Projectiles do NOT have `CN_SyncEntity`. The server spawns them and broadcasts component values once - then all clients simulate locally.
2222

2323
```gdscript
2424
# e_projectile.gd
2525
func define_components() -> Array:
2626
return [
27-
C_NetworkIdentity.new(0), # Server-owned
27+
CN_NetworkIdentity.new(0), # Server-owned
2828
C_Projectile.new(),
2929
C_NetVelocity.new(),
3030
C_NetPosition.new(), # Position synced at spawn
31-
# NO C_SyncEntity - spawn-only pattern
31+
# NO CN_SyncEntity - spawn-only pattern
3232
]
3333
```
3434

@@ -89,9 +89,9 @@ projectile.get_component(C_Projectile).projectile_color = color
8989

9090
### Local-Only Movement (Continuous Sync)
9191
```gdscript
92-
# s_movement.gd - Query with C_LocalAuthority
92+
# s_movement.gd - Query with CN_LocalAuthority
9393
func query() -> QueryBuilder:
94-
return q.with_all([C_NetVelocity, C_PlayerInput, C_LocalAuthority])...
94+
return q.with_all([C_NetVelocity, C_PlayerInput, CN_LocalAuthority])...
9595
```
9696

9797
### Middleware Visual Setup

example_network/config/example_sync_config.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@ func _init() -> void:
1313
# Not using a separate transform component
1414
transform_component = ""
1515

16-
# CRITICAL: Trigger native sync (MultiplayerSynchronizer) setup when C_NetworkIdentity is added
16+
# CRITICAL: Trigger native sync (MultiplayerSynchronizer) setup when CN_NetworkIdentity is added
1717
# This enables continuous position sync for players via Godot's native replication
18-
model_ready_component = "C_NetworkIdentity"
18+
model_ready_component = "CN_NetworkIdentity"

example_network/entities/e_player.gd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class_name E_NetworkPlayer
22
extends Entity
33
## Player entity for the network example.
4-
## Demonstrates continuous sync via C_SyncEntity.
4+
## Demonstrates continuous sync via CN_SyncEntity.
55

66
## Peer ID that owns this player (set by main.gd when spawning)
77
@export var owner_peer_id: int = 0
@@ -17,14 +17,14 @@ func _enter_tree() -> void:
1717

1818
func on_ready() -> void:
1919
# Add network identity based on owner_peer_id
20-
add_component(C_NetworkIdentity.new(owner_peer_id))
20+
add_component(CN_NetworkIdentity.new(owner_peer_id))
2121

2222

2323
func define_components() -> Array:
2424
return [
2525
C_NetVelocity.new(),
2626
C_PlayerInput.new(),
2727
C_PlayerNumber.new(), # Join order number (1-4) for color assignment
28-
# C_SyncEntity enables native MultiplayerSynchronizer for position/rotation
29-
C_SyncEntity.new(true, true, false), # sync_position=true, sync_rotation=true
28+
# CN_SyncEntity enables native MultiplayerSynchronizer for position/rotation
29+
CN_SyncEntity.new(true, true, false), # sync_position=true, sync_rotation=true
3030
]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
class_name E_NetworkProjectile
22
extends Entity
33
## Projectile entity for the network example.
4-
## Demonstrates spawn-only sync - NO C_SyncEntity means server broadcasts
4+
## Demonstrates spawn-only sync - NO CN_SyncEntity means server broadcasts
55
## spawn data once, then all clients simulate locally.
66

77

88
func define_components() -> Array:
99
return [
1010
# Server-owned (peer_id = 0)
11-
C_NetworkIdentity.new(0),
11+
CN_NetworkIdentity.new(0),
1212
C_Projectile.new(),
1313
C_NetVelocity.new(),
1414
C_NetPosition.new(), # Position synced at spawn
15-
# NOTE: No C_SyncEntity! This enables spawn-only sync pattern.
15+
# NOTE: No CN_SyncEntity! This enables spawn-only sync pattern.
1616
# Server spawns and broadcasts component values at spawn time.
1717
# Clients receive spawn RPC and simulate locally from there.
1818
]

example_network/main.gd

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,6 @@ func _setup_network_sync() -> void:
177177
func _cleanup_network() -> void:
178178
_is_connected = false
179179

180-
# Clear spawned players
181-
for peer_id in _spawned_peer_ids.keys():
182-
var entity_id = _spawned_peer_ids[peer_id]
183-
var entity = world.get_entity_by_id(entity_id)
184-
if entity:
185-
world.remove_entity(entity)
186-
entity.queue_free()
187180
_spawned_peer_ids.clear()
188181

189182
# Reset player number counter
@@ -198,6 +191,12 @@ func _cleanup_network() -> void:
198191
_network_sync = null
199192
_network_middleware = null
200193

194+
# Properly clean up all entities from the world
195+
for entity in world.entities.duplicate():
196+
world.remove_entity(entity)
197+
if is_instance_valid(entity):
198+
entity.queue_free()
199+
201200

202201
func _on_local_player_spawned(entity: Entity) -> void:
203202
print("[Main] Local player spawned: %s" % entity.name)

example_network/systems/s_input.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
class_name S_NetworkInput
22
extends System
33
## Input system - reads keyboard input, updates C_PlayerInput.
4-
## Only processes local player (entities with C_LocalAuthority).
4+
## Only processes local player (entities with CN_LocalAuthority).
55

66

77
func query() -> QueryBuilder:
88
# Only process entities we have local control over
9-
return q.with_all([C_PlayerInput, C_LocalAuthority]).iterate([C_PlayerInput])
9+
return q.with_all([C_PlayerInput, CN_LocalAuthority]).iterate([C_PlayerInput])
1010

1111

1212
func process(entities: Array[Entity], components: Array, delta: float) -> void:

example_network/systems/s_movement.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
class_name S_NetworkMovement
22
extends System
33
## Movement system - applies velocity to entity position.
4-
## Processes entities with C_LocalAuthority (local simulation).
4+
## Processes entities with CN_LocalAuthority (local simulation).
55
## Remote entities receive position updates via native MultiplayerSynchronizer.
66

77
const MOVE_SPEED := 5.0
@@ -10,7 +10,7 @@ const ARENA_BOUND := 4.5 # Half of 10x10 arena minus player size
1010

1111
func query() -> QueryBuilder:
1212
# Only move local entities - remote positions come from network sync
13-
return q.with_all([C_NetVelocity, C_PlayerInput, C_LocalAuthority]).iterate([C_NetVelocity, C_PlayerInput])
13+
return q.with_all([C_NetVelocity, C_PlayerInput, CN_LocalAuthority]).iterate([C_NetVelocity, C_PlayerInput])
1414

1515

1616
func process(entities: Array[Entity], components: Array, delta: float) -> void:

project.godot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ config/name="GECS"
1414
config/description="Godot Entity Component System - Example project and testing suite"
1515
config/version="5.0.0"
1616
run/main_scene="uid://x5ubiio43y7w"
17-
config/features=PackedStringArray("4.6", "Forward Plus")
17+
config/features=PackedStringArray("4.5", "Forward Plus")
1818

1919
[audio]
2020

0 commit comments

Comments
 (0)