From 9c5f7fd8e98647d0b3b678e9b4064817e519f716 Mon Sep 17 00:00:00 2001 From: D4VID Date: Sun, 1 Dec 2024 20:17:12 +0100 Subject: [PATCH] Inserting into an item database --- storage_database.lua | 201 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 storage_database.lua diff --git a/storage_database.lua b/storage_database.lua new file mode 100644 index 0000000..0e611ee --- /dev/null +++ b/storage_database.lua @@ -0,0 +1,201 @@ +HEIGHT = 2 -- number of chests tall +DEPTH = 3 -- number of columns of chests +CONTAINER_SIZE = 10 -- size of a single double-chest + +local database = { + items = {}, -- item to amount and locations + containers = {}, -- location to item +} + +-- database.items = { +-- ["minecraft:stick;0"] = { +-- amount = 200, +-- max_stack = 64, +-- locations = { +-- {1,1,10,64}, -- x, y, slot, amount +-- {1,3,54,64}, +-- {10,2,2,20} +-- } +-- } +-- } + +-- database.containers = { -- array of columns in the storage wall +-- { -- array of containers in a column +-- { -- arrays of slots in the container +-- false, true, nil, nil, nil -- if the slot is occupied (true) or not (nil|false) +-- }, +-- { + +-- }, +-- }, +-- { + +-- } +-- } + +local function lookup(searched_item) + return database.items[searched_item] +end + +---find the first empty slot in storage +---return nil if inventory is full (no empty slots) +---@param begin_x integer start searching from this x +---@param begin_y integer start searching from this y +---@param begin_slot integer start searching from this slot +---@return integer|nil x +---@return integer|nil y +---@return integer|nil slot +local function find_empty_slot(begin_x, begin_y, begin_slot) + local x = begin_x + local y = begin_y + local slot = begin_slot + + while true do + if not database.containers[x] or not database.containers[x][y] or not database.containers[x][y][slot] then + return x, y, slot + end + slot = slot + 1 + if slot > CONTAINER_SIZE then + slot = 1 + y = y + 1 + + if y > HEIGHT then + y = 1 + x = x + 1 + + if x > DEPTH then + return nil + end + -- if not database.containers[x] then + -- return x, 1, 1 + -- end + end + + -- if not database.containers[x][y] then + -- return x, y, 1 + -- end + end + + -- if not database.containers[x][y][slot] then + -- return x, y, slot + -- end + end +end + +---mark the given slot as occupied or not +---@param x integer +---@param y integer +---@param slot integer +---@param occupied boolean +local function mark_slot(x, y, slot, occupied) + local column = database.containers[x] + if not column then + column = {} + database.containers[x] = column + end + local container = column[y] + if not container then + container = {} + column[y] = container + end + + -- flag the slot as occupied + container[slot] = occupied +end + +---@param item string +---@param amount integer +---@param max_stack integer +---@return table db_item +local function create_db_item(item, amount, max_stack) + local db_item = { + amount = amount, + max_stack = max_stack, + locations = {} + } + database.items[item] = db_item + + return db_item +end + +---@param db_item table +---@param amount integer +---@param location_index integer|nil +local function transfer_to_location(db_item, amount, location_index) + local location = db_item.locations[location_index] + print('Transfering ' .. amount .. ' to slot ' .. location[1] .. ',' .. location[2] .. ',' .. location[3]) + + db_item.amount = db_item.amount + amount + location[4] = location[4] + amount +end + +---@param db_item table +---@param amount integer +---@param x integer +---@param y integer +---@param slot integer +local function transfer_to_empty_slot(db_item, amount, x, y, slot) + print('Transfering ' .. amount .. ' to slot ' .. x .. ',' .. y .. ',' .. slot) + db_item.amount = db_item.amount + amount + db_item.locations[#db_item.locations + 1] = { + x, y, slot, amount + } + mark_slot(x, y, slot, true) +end + +---comment +---@param item string +---@param amount integer +---@param max_stack integer +---@return boolean success +local function insert(item, amount, max_stack) + print('\nInserting') + local db_item = lookup(item) + + if not db_item then + db_item = create_db_item(item, amount, max_stack) + end + + -- try to fill slots where the item already is + for location_index, location in ipairs(db_item.locations) do + if location[4] < db_item.max_stack then + local can_fit = math.min(amount, db_item.max_stack - location[4]) + -- print('Can fit ' .. can_fit .. ' into ', table.unpack(location)) + transfer_to_location(db_item, can_fit, location_index) + amount = amount - can_fit + if amount <= 0 then + break + end + end + end + + -- didn't fit to existing slots -> occupy an empty slot + local empty_x = 1 + local empty_y = 1 + local empty_slot = 1 + while amount > 0 do + empty_x, empty_y, empty_slot = find_empty_slot(empty_x, empty_y, empty_slot) + if not empty_x or not empty_y or not empty_slot then + print('Inventory full') + return false + end + local can_fit = math.min(amount, max_stack) + transfer_to_empty_slot(db_item, can_fit, empty_x, empty_y, empty_slot) + amount = amount - can_fit + end + if amount < 0 then + print('Something went horribly wrong - amount is ' .. amount) + end + return true +end + +print(find_empty_slot(1, 1, 1)) + +for _ = 1, 20 do + print(insert('stick', 61, 64)) + print('Next empty:', find_empty_slot(1, 1, 1)) +end + +-- return { +-- insert +-- }