refactor: enhance refueling logic and add file writing and inventory refresh methods in Turtle class
This commit is contained in:
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user