refactor: enhance refueling logic and add file writing and inventory refresh methods in Turtle class

This commit is contained in:
MayaTheShy
2026-02-20 04:18:44 -05:00
parent 9a34f72178
commit 2e3d5b4b6b

View File

@@ -735,10 +735,15 @@ export class Turtle extends EventEmitter {
*/
async refuel(count) {
const cmd = count != null ? `return turtle.refuel(${count})` : 'return turtle.refuel()';
const fuelBefore = this._fuel;
const result = await this.exec(cmd);
// Update fuel level
const fuelLevel = await this.exec('return turtle.getFuelLevel()');
if (fuelLevel != null) this._fuel = fuelLevel;
if (fuelLevel != null) {
this._totalFuelUsed += (fuelLevel - fuelBefore);
this._fuel = fuelLevel;
this._stepsSinceLastRefuel = 0;
}
return result;
}
@@ -806,6 +811,83 @@ export class Turtle extends EventEmitter {
return this._position;
}
/**
* Write content to a file on the turtle's filesystem
* @param {string} path - The file path on the turtle (e.g., 'log.txt', 'scripts/miner.lua')
* @param {string} content - The content to write
* @param {boolean} append - Whether to append instead of overwrite
*/
async writeToFile(path, content, append = false) {
const safePath = path.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
// Encode content as base64-like hex to avoid Lua string escaping issues
const mode = append ? 'a' : 'w';
// Split content into chunks to avoid oversized eval commands
const chunkSize = 4000;
const chunks = [];
for (let i = 0; i < content.length; i += chunkSize) {
chunks.push(content.substring(i, i + chunkSize));
}
if (chunks.length <= 1) {
// Single write for small files
const safeContent = (chunks[0] || '').replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '');
return this.exec(`
local f = fs.open("${safePath}", "${mode}")
if f then
f.write("${safeContent}")
f.close()
return true
end
return false, "Cannot open file"
`);
}
// Multi-chunk write for large files
for (let i = 0; i < chunks.length; i++) {
const safeChunk = chunks[i].replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n').replace(/\r/g, '');
const writeMode = i === 0 ? mode : 'a';
const result = await this.exec(`
local f = fs.open("${safePath}", "${writeMode}")
if f then
f.write("${safeChunk}")
f.close()
return true
end
return false, "Cannot open file"
`);
if (result !== true) return result;
}
return true;
}
/**
* Refresh detailed inventory state for all 16 slots.
* Gets name, count, damage, and maxCount for each slot.
*/
async refreshInventoryState() {
const result = await this.exec(`
local inv = {}
for slot = 1, 16 do
local item = turtle.getItemDetail(slot)
if item then
inv[tostring(slot)] = {
name = item.name,
count = item.count,
damage = item.damage or 0,
maxCount = turtle.getItemSpace(slot) + item.count
}
end
end
return inv
`);
if (result && typeof result === 'object') {
this._inventory = result;
this._emitUpdate();
}
return result;
}
/**
* Connect to an adjacent inventory peripheral and read its contents
*/
@@ -1111,6 +1193,9 @@ export class Turtle extends EventEmitter {
peripherals: this._peripherals,
error: this._error,
warning: this._warning,
stepsSinceLastRefuel: this._stepsSinceLastRefuel,
totalSteps: this._totalSteps,
totalFuelUsed: this._totalFuelUsed,
};
}