From 1b7c112fbe4af4bb866e5fb93c284e245dc923be Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Fri, 13 Feb 2026 16:44:31 +0000 Subject: [PATCH] feat: Enhance inventory management by preventing duplicate items and adding error handling --- .../break_escape/games_controller.rb | 51 +++++++++++-------- app/models/break_escape/game.rb | 21 +++++++- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/app/controllers/break_escape/games_controller.rb b/app/controllers/break_escape/games_controller.rb index 2ec4e05..f12cf61 100644 --- a/app/controllers/break_escape/games_controller.rb +++ b/app/controllers/break_escape/games_controller.rb @@ -416,27 +416,38 @@ module BreakEscape Rails.logger.info "[BreakEscape] inventory endpoint: action=#{action_type}, item=#{item.inspect}" - case action_type - when 'add' - # Validate item exists and is collectible - validation_error = validate_item_collectible(item) - if validation_error - Rails.logger.warn "[BreakEscape] inventory validation failed: #{validation_error}" - return render json: { success: false, message: validation_error }, - status: :unprocessable_entity + begin + case action_type + when 'add' + # Validate item exists and is collectible + validation_error = validate_item_collectible(item) + if validation_error + Rails.logger.warn "[BreakEscape] inventory validation failed: #{validation_error}" + return render json: { success: false, message: validation_error }, + status: :unprocessable_entity + end + + Rails.logger.info "[BreakEscape] Adding item to inventory: #{item['type']} / #{item['name']}" + @game.add_inventory_item!(item.to_unsafe_h) + Rails.logger.info "[BreakEscape] Item added successfully. Current inventory size: #{@game.player_state['inventory']&.length}" + render json: { success: true, inventory: @game.player_state['inventory'] } + + when 'remove' + @game.remove_inventory_item!(item['id']) + render json: { success: true, inventory: @game.player_state['inventory'] } + + else + render json: { success: false, message: 'Invalid action' }, status: :bad_request end - - Rails.logger.info "[BreakEscape] Adding item to inventory: #{item['type']} / #{item['name']}" - @game.add_inventory_item!(item.to_unsafe_h) - Rails.logger.info "[BreakEscape] Item added successfully. Current inventory: #{@game.player_state['inventory'].inspect}" - render json: { success: true, inventory: @game.player_state['inventory'] } - - when 'remove' - @game.remove_inventory_item!(item['id']) - render json: { success: true, inventory: @game.player_state['inventory'] } - - else - render json: { success: false, message: 'Invalid action' }, status: :bad_request + rescue ActiveRecord::RecordInvalid => e + Rails.logger.error "[BreakEscape] Inventory save failed: #{e.message}" + render json: { success: false, message: "Failed to save inventory: #{e.message}" }, + status: :unprocessable_entity + rescue => e + Rails.logger.error "[BreakEscape] Inventory error: #{e.class} - #{e.message}" + Rails.logger.error e.backtrace.join("\n") + render json: { success: false, message: "Inventory error: #{e.message}" }, + status: :internal_server_error end end diff --git a/app/models/break_escape/game.rb b/app/models/break_escape/game.rb index aaed714..ee80102 100644 --- a/app/models/break_escape/game.rb +++ b/app/models/break_escape/game.rb @@ -49,8 +49,25 @@ module BreakEscape # Inventory management def add_inventory_item!(item) player_state['inventory'] ||= [] - player_state['inventory'] << item - save! + + # Check if item already exists in inventory (by id or combination of type and name) + item_exists = player_state['inventory'].any? do |existing_item| + # Match by ID if both have IDs + if item['id'].present? && existing_item['id'].present? + existing_item['id'] == item['id'] + else + # Match by type and name as fallback + existing_item['type'] == item['type'] && + existing_item['name'] == item['name'] + end + end + + unless item_exists + player_state['inventory'] << item + save! + else + Rails.logger.info "[BreakEscape] Item already in inventory, skipping: #{item['type']} / #{item['name']}" + end end def remove_inventory_item!(item_id)