Inserting into an item database

master
D4VID 10 months ago
parent 37bcfea10d
commit 9c5f7fd8e9

@ -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
-- }
Loading…
Cancel
Save