class_name Player extends CharacterBody3D var selection_block: MeshInstance3D var selection_block_data: Block var previous_looked_at_block_position: Vector3 = Vector3.ZERO const SPEED = 5.0#10.0#20.0 const JUMP_VELOCITY = 5.0#10.0#20.0 var acc = 0 func _ready() -> void: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED selection_block = MeshInstance3D.new() selection_block.visible = false selection_block.top_level = true selection_block.rotation = Vector3.ZERO selection_block.scale = Vector3(1.0001, 1.0001, 1.0001) add_child(selection_block) selection_block_data = Block.new() selection_block_data.type = Block.Type.SELECTION #set_physics_process(false) #await get_tree().create_timer(3.0).timeout #set_physics_process(true) func _input(event: InputEvent) -> void: if event is InputEventMouse and event.is_pressed(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if event.is_action_pressed("mouse_exit"): Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if Input.mouse_mode != Input.MOUSE_MODE_CAPTURED: return if event is InputEventMouseMotion: $CameraAnchor.rotate_y(deg_to_rad(clamp(-event.relative.x * 0.25, -45, 45))) $CameraAnchor.rotate_object_local(Vector3(1,0,0), deg_to_rad(-event.relative.y * 0.25)) if event.is_action_pressed("right_click"): if selection_block.visible: var point = ( $CameraAnchor/Camera/RayCast3D.get_collision_point() + $CameraAnchor/Camera/RayCast3D.get_collision_normal() * (Block.BLOCK_SIZE * 0.5) ) var q := PhysicsShapeQueryParameters3D.new() q.shape = BoxShape3D.new() q.transform = Transform3D(Basis(Vector3.ZERO,Vector3.ZERO,Vector3.ZERO), point) var collision := get_world_3d().direct_space_state.intersect_shape(q) if collision.is_empty(): (get_tree().current_scene as World).add_block( $CameraAnchor/Camera/RayCast3D.get_collision_point(), $CameraAnchor/Camera/RayCast3D.get_collision_normal(), $CanvasLayer/MarginContainer.active_type ) if event.is_action_pressed("left_click"): if selection_block.visible: (get_tree().current_scene as World).remove_block( $CameraAnchor/Camera/RayCast3D.get_collision_point(), $CameraAnchor/Camera/RayCast3D.get_collision_normal() ) func _process(_delta: float) -> void: if $CameraAnchor/Camera/RayCast3D.is_colliding(): var collider = $CameraAnchor/Camera/RayCast3D.get_collider() if collider is not StaticBody3D: return var point = $CameraAnchor/Camera/RayCast3D.get_collision_point() maybe_update_selection_block(point) else: selection_block.visible = false func _physics_process(delta: float) -> void: # Add the gravity. if not is_on_floor(): velocity += get_gravity() * delta * 1.5 # Handle jump. if Input.is_action_just_pressed("ui_accept") and is_on_floor(): velocity.y = JUMP_VELOCITY # Get the input direction and handle the movement/deceleration. # As good practice, you should replace UI actions with custom gameplay actions. var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") var direction := ( (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() .rotated(Vector3(1, 0, 0), $CameraAnchor.rotation.x) .rotated(Vector3(0, 1, 0), $CameraAnchor.rotation.y) .rotated(Vector3(0, 0, 1), $CameraAnchor.rotation.z) ) if direction: velocity.x = direction.x * SPEED * (2.0 if Input.is_action_pressed("run") else 1.0) * (0.5 if not is_on_floor() else 1.0) velocity.z = direction.z * SPEED * (2.0 if Input.is_action_pressed("run") else 1.0) * (0.5 if not is_on_floor() else 1.0) else: velocity.x = move_toward(velocity.x, 0, SPEED) velocity.z = move_toward(velocity.z, 0, SPEED) move_and_slide() func maybe_update_selection_block(collision_point: Vector3) -> void: var chunk_idx := Chunk.global_to_chunk( collision_point, $CameraAnchor/Camera/RayCast3D.get_collision_normal() ) var block_chunk_idx := Chunk.global_to_chunk_block( collision_point, $CameraAnchor/Camera/RayCast3D.get_collision_normal() ) if Chunk.chunk_exists(chunk_idx): var chunk: Chunk = Global.chunks[chunk_idx] var block: Block = chunk.blocks[block_chunk_idx.x][block_chunk_idx.y][block_chunk_idx.z] selection_block.visible = true if previous_looked_at_block_position != block.position: update_selection_block(block.position) previous_looked_at_block_position = block.position func update_selection_block(new_position: Vector3): var material := preload("res://new_shader_material_selection.tres") var st = SurfaceTool.new() st.begin(Mesh.PRIMITIVE_TRIANGLES) st.set_material(material) for face in Block.Face.values(): selection_block_data.add_face(st, face) selection_block.global_position = new_position selection_block.mesh = st.commit() func print_debug_block(message: String, block: Block) -> void: print( message.rpad(6), " => ", block, " ", Block.Type.keys()[block.type].rpad(5), " ", block.generated_faces )