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