extends Area2D

# Set by World._spawn_bullet() before this node enters the tree.
var velocity: Vector2 = Vector2.ZERO
var source_peer_id: int = 0
var damage: int = 100

var _spawn_pos: Vector2

# Only the server detects hits and despawns bullets — that's replicated to
# every client automatically since bullets are spawned via BulletSpawner.
# Movement itself stays local on every peer (deterministic constant-velocity
# simulation from the replicated spawn state, no further sync needed).
func _ready() -> void:
	_spawn_pos = global_position
	if multiplayer.is_server():
		body_entered.connect(_on_body_entered)

func _process(delta: float) -> void:
	global_position += velocity * delta
	if multiplayer.is_server():
		var bounds = GameConfig.world_bounds.grow(64.0)
		if not bounds.has_point(global_position):
			queue_free()
		elif global_position.distance_to(_spawn_pos) > GameConfig.bullet_max_range:
			queue_free()

func _on_body_entered(body: Node) -> void:
	var target_peer_id = body.get("peer_id")
	if target_peer_id == source_peer_id:
		return
	# Friendly fire is blocked, not ignored -- the bullet still stops dead on
	# a teammate's hull (queue_free below), it just deals no damage. Only a
	# real target (has take_damage, i.e. a Ship) is team-checked; hazards/
	# walls have neither peer_id nor take_damage and fall straight through
	# to queue_free(), same as before.
	if target_peer_id != null and body.has_method("take_damage"):
		var source_race: int = PlayerRegistry.get_info(source_peer_id).get("race", -1)
		var target_race: int = PlayerRegistry.get_info(target_peer_id).get("race", -2)
		if source_race != target_race:
			body.take_damage(damage, source_peer_id, global_position)
	queue_free()
