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…
Reference in new issue