You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
5.4 KiB
202 lines
5.4 KiB
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
|
|
-- }
|