From 0bd79ee9921fbb31bde6e5b553d06055de0c28c1 Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Sun, 30 Mar 2025 16:51:10 -0400
Subject: [PATCH] Disallow placing blocks where player is located

---
 scenes/player/player.gd        |  5 +++--
 scenes/player/player.tscn      |  3 ++-
 scenes/player/ray_cast_look.gd | 28 +++++++++++++++++++++++++++-
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/scenes/player/player.gd b/scenes/player/player.gd
index 3ef9d0d..c7777f4 100644
--- a/scenes/player/player.gd
+++ b/scenes/player/player.gd
@@ -25,6 +25,7 @@ extends CharacterBody3D
 @onready var collision_shape_crouching: CollisionShape3D = $CollisionShapeCrouching
 @onready var ray_cast_crouch: RayCast3D = $RayCastCrouch
 
+var current_height: float = 0.0
 var current_jump_count: int = 0
 var current_speed: float = walk_speed
 var direction: Vector3 = Vector3.ZERO
@@ -74,8 +75,8 @@ func _handle_crouching(delta: float) -> void:
 	collision_shape_crouching.disabled = !is_crouching
 	collision_shape_standing.disabled = is_crouching
 
-	var height: float = crouch_height if is_crouching else standing_height
-	head.position.y = lerp(head.position.y, height, camera_acceleration * delta)
+	current_height = crouch_height if is_crouching else standing_height
+	head.position.y = lerp(head.position.y, current_height, camera_acceleration * delta)
 
 func _handle_jumping() -> void:
 	if is_on_floor():
diff --git a/scenes/player/player.tscn b/scenes/player/player.tscn
index 11c710d..942fdff 100644
--- a/scenes/player/player.tscn
+++ b/scenes/player/player.tscn
@@ -37,10 +37,11 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.8, 0)
 [node name="BlockMesh" parent="Head/Camera3D" instance=ExtResource("2_p47bc")]
 transform = Transform3D(1, 0, 0, 0, 0.965926, -0.258819, 0, 0.258819, 0.965926, 0, -0.680035, -1.7196)
 
-[node name="RayCastLook" type="RayCast3D" parent="Head"]
+[node name="RayCastLook" type="RayCast3D" parent="Head" node_paths=PackedStringArray("player")]
 target_position = Vector3(0, 0, -10)
 debug_shape_custom_color = Color(0.753415, 4.77457e-05, 0.578804, 1)
 script = ExtResource("2_dovo2")
+player = NodePath("../..")
 
 [node name="RayCastCrouch" type="RayCast3D" parent="."]
 editor_description = "Y should be just slightly higher than the height of the standing collision shape"
diff --git a/scenes/player/ray_cast_look.gd b/scenes/player/ray_cast_look.gd
index 0f46061..88e91d1 100644
--- a/scenes/player/ray_cast_look.gd
+++ b/scenes/player/ray_cast_look.gd
@@ -1,6 +1,9 @@
 extends RayCast3D
 
 
+@export var player: Player
+
+
 func _process(_delta: float) -> void:
 	if is_colliding():
 		var collider: Object = get_collider()
@@ -9,9 +12,14 @@ func _process(_delta: float) -> void:
 			if Input.is_action_just_pressed("right_click_interact"):
 				(collider as Block).destroy_block()
 			if Input.is_action_just_pressed("left_click_interact"):
+				var new_block_pos: Vector3i = Vector3i(collider.position + get_collision_normal())
+
+				if !is_valid_placement_target(new_block_pos):
+					return
+
 				EntityManager.create_block.emit(
 					InventoryManager.quick_slot_item_id,
-					collider.position + get_collision_normal()
+					new_block_pos
 				)
 
 			if Waila.ref.get_target() == collider:
@@ -25,6 +33,24 @@ func _process(_delta: float) -> void:
 			release_target()
 
 
+func is_valid_placement_target(new_block_pos: Vector3i) -> bool:
+	# This could probably use some work
+	var collision_shape_radius: float = player.collision_shape_standing.shape.radius
+
+	var maximums: Vector3 = Vector3(collision_shape_radius, player.current_height, collision_shape_radius)
+	var position_min: Vector3i = Vector3i(player.global_position - maximums)
+	var position_max: Vector3i = Vector3i(player.global_position + maximums)
+
+	if (
+		new_block_pos.x >= position_min.x and new_block_pos.x <= position_max.x and
+		new_block_pos.y >= position_min.y and new_block_pos.y <= position_max.y and
+		new_block_pos.z >= position_min.z and new_block_pos.z <= position_max.z
+	):
+		return false
+
+	return true
+
+
 func hook_block(target_block: Block) -> void:
 	target_block.hook()
 	Waila.ref.set_target(target_block)