refactored InvManager and State

This commit is contained in:
Niklas Kapelle 2024-04-25 00:36:48 +02:00
parent 5c71ab1c30
commit 9353ccba8a
Signed by: niklas
GPG Key ID: 4EB651B36D841D16
2 changed files with 106 additions and 101 deletions

View File

@ -9,123 +9,28 @@ import kernel.turtle.Turtle;
using Lambda; using Lambda;
using tink.CoreApi; using tink.CoreApi;
typedef InvState = Map<TurtleSlot, {count:Int, name:Item, max:Int}>;
/** /**
A wrapper for the native turtle inventory functions. Adds usefullt helper functions. A wrapper for the native turtle inventory functions. Adds usefullt helper functions.
**/ **/
class InvManager { class InvManager {
public function new() {}
private static function getInvState() {
var invState:InvState = new Map();
for (i in 0...Turtle.MAX_SLOTS) {
var detail = Turtle.getItemDetail(i);
var spaceLeft = Turtle.getItemSpace(i);
switch detail {
case Some(v):
invState.set(i, {
count: v.count,
name: v.name,
max: spaceLeft + v.count
});
case None:
invState.remove(i);
}
}
return invState;
}
public static function getItemCountInfo():Map<Item, Int> {
var invState = getInvState();
var rtn:Map<Item, Int> = new Map();
for (slot in invState) {
if (!rtn.exists(slot.name)) {
rtn.set(slot.name, slot.count);
continue;
}
var count = rtn.get(slot.name);
rtn.set(slot.name, count + slot.count);
}
return rtn;
}
private static function getSlotWithMinCountForItem(item:Item, invState:InvState):Null<TurtleSlot> {
var min:Int = 99; // TODO: is there something like MAX_INT ???
var minSlot:TurtleSlot = -1;
for (k => slot in invState) {
if (slot.name != item) {
continue;
}
if (slot.count < min) {
min = slot.count;
minSlot = k;
}
};
return minSlot == -1 ? null : minSlot;
}
public static function place(item:Item, dir:InteractDirections):Outcome<Noise, String> { public static function place(item:Item, dir:InteractDirections):Outcome<Noise, String> {
var invState = getInvState(); var invState = new InvState();
var slot = getSlotWithMinCountForItem(item, invState); var slot = invState.getSlotWithMinCountForItem(item);
if (slot == null) { if (slot == null) {
return Failure("Item not in inventory"); return Failure("Item not in inventory");
} }
return placeSlot(slot, dir); Turtle.selectSlot(slot);
}
private static function placeSlot(slot:TurtleSlot, dir:InteractDirections):Outcome<Noise, String> {
Turtle.selectSlot(slot); // TODO: handle error
return Turtle.place(dir); return Turtle.place(dir);
} }
private static function getSlotsForItems(invState:InvState):Map<Item, Array<TurtleSlot>> {
var rtn:Map<Item, Array<TurtleSlot>> = 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;
}
/**
Returns the first slot that contains this item.
**/
public static function findItemSlot(item:Item):Null<TurtleSlot> {
var invState = getInvState();
for (k => slot in invState) {
if (slot.name == item) {
return k;
}
}
return null;
}
/** /**
Cleans up turtle inventory. Moves items together. Cleans up turtle inventory. Moves items together.
This should be run in a turtle thread. This should be run in a turtle thread.
**/ **/
public static function defrag() { public static function defrag() {
var invState = getInvState(); var invState = new InvState();
var items = getSlotsForItems(invState); var items = invState.getSlotsForItems();
for (item in items) { for (item in items) {
defragItem(invState, item); defragItem(invState, item);
@ -198,7 +103,8 @@ class InvManager {
} }
public static function equipTool(item:Item, side:ToolSide):Outcome<TurtleSlot, String> { public static function equipTool(item:Item, side:ToolSide):Outcome<TurtleSlot, String> {
var toolSlot = findItemSlot(item); var invState = new InvState();
var toolSlot = invState.findItemSlot(item);
if (toolSlot == null) { if (toolSlot == null) {
return Failure("Item not found"); return Failure("Item not found");

View File

@ -0,0 +1,99 @@
package lib.turtle;
import kernel.turtle.Turtle;
import kernel.turtle.TurtleSlot;
@:forward(get, set, iterator, keyValueIterator)
abstract InvState(Map<TurtleSlot, {count:Int, name:Item, max:Int}>) {
public function new() {
this = new Map();
for (i in 0...Turtle.MAX_SLOTS) {
var detail = Turtle.getItemDetail(i);
var spaceLeft = Turtle.getItemSpace(i);
switch detail {
case Some(v):
this.set(i, {
count: v.count,
name: v.name,
max: spaceLeft + v.count
});
case None:
this.remove(i);
}
}
}
/**
Count items.
**/
public function getItemCountInfo():Map<Item, Int> {
var rtn:Map<Item, Int> = new Map();
for (slot in this) {
if (!rtn.exists(slot.name)) {
rtn.set(slot.name, slot.count);
continue;
}
var count = rtn.get(slot.name);
rtn.set(slot.name, count + slot.count);
}
return rtn;
}
/**
Return the slot with with the minimal count for an item.
**/
public function getSlotWithMinCountForItem(item:Item):Null<TurtleSlot> {
var min:Int = 99; // TODO: is there something like MAX_INT ???
var minSlot:TurtleSlot = -1;
for (k => slot in this) {
if (slot.name != item) {
continue;
}
if (slot.count < min) {
min = slot.count;
minSlot = k;
}
};
return minSlot == -1 ? null : minSlot;
}
/**
Get all slots for an Item.
**/
public function getSlotsForItems():Map<Item, Array<TurtleSlot>> {
var rtn:Map<Item, Array<TurtleSlot>> = new Map();
for (k => slot in this) {
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;
}
/**
Returns the first slot that contains this item.
**/
public function findItemSlot(item:Item):Null<TurtleSlot> {
for (k => slot in this) {
if (slot.name == item) {
return k;
}
}
return null;
}
}