diff --git a/src/lib/turtle/InvManager.hx b/src/lib/turtle/InvManager.hx index 0c50d0a..582dd0c 100644 --- a/src/lib/turtle/InvManager.hx +++ b/src/lib/turtle/InvManager.hx @@ -1,7 +1,5 @@ package lib.turtle; -import kernel.KernelEvents; -import tink.CoreApi.Outcome; import kernel.log.Log; import kernel.turtle.Types.TurtleSlot; import kernel.turtle.Types.InteractDirections; @@ -20,7 +18,7 @@ class InvManager { private static function getInvState() { var invState:InvState = new Map(); - for (i in 0...Turtle.MAX_SLOTS - 1) { + for (i in 0...Turtle.MAX_SLOTS) { var detail = Turtle.getItemDetail(i); var spaceLeft = Turtle.getItemSpace(i); @@ -87,4 +85,90 @@ class InvManager { Turtle.selectSlot(slot); // TODO: handle error return Turtle.place(dir); } + + private static function getSlotsForItems(invState:InvState):Map> { + var rtn:Map> = new Map(); + + for (k => slot in invState) { + if (!rtn.exists(slot.name)) { + rtn.set(slot.name, [k]); + continue; + } + + var value = rtn.get(slot.name); + value.push(k); + rtn.set(slot.name, value); + } + + return rtn; + } + + /** + Cleans up turtle inventory. Moves items together. + This should be run in a turtle thread. + **/ + public static function defrag() { + var invState = getInvState(); + var items = getSlotsForItems(invState); + + for (item in items) { + defragItem(invState, item); + } + } + + private static function defragItem(invState:InvState, slots:Array) { + // Sort slots by items inside. + slots.sort((a, b) -> { + return invState.get(a).count - invState.get(b).count; + }); + + var maxInSlot = invState.get(slots[0]).max; + + // Loop from both sides. Move the slots with the lowest count into the fullest. + var topIndex = slots.length - 1; + + for (k => slot in slots) { + if (topIndex <= k) { + return; + } + + var count = invState.get(slot).count; + + if (count == maxInSlot) { + return; + } + + while (true) { + if (topIndex <= k) { + return; + } + + var topCount = invState.get(slots[topIndex]).count; + var spaceInTop = maxInSlot - topCount; + + if (spaceInTop == 0) { + topIndex--; + continue; + } + + var transferCount = MathI.min(count, spaceInTop); + if (!Turtle.transfer(slot, slots[topIndex], transferCount).isSuccess()) { + Log.error("Failed to transfer items"); + } + + // Update invState + var topState = invState.get(slots[topIndex]); + topState.count += transferCount; + invState.set(topIndex, topState); + + var botState = invState.get(slot); + botState.count -= transferCount; + invState.set(slot, botState); + + if (count - transferCount <= 0) { + break; + } + } + } + } }