'use strict';
// Calls the two original route APIs on the player's FSD owning thread. No
// flight inputs, journal writes, custom graph search or fabricated route data.
const mod = Process.getModuleByName('EliteDangerous64.exe');
if (Process.id !== BINDINGS.pid || mod.path.toLowerCase() !== PROFILE.image.toLowerCase())
throw Error('Selected process image changed');
const base = mod.base, fsd = ptr(BINDINGS.fsd), life = ptr(BINDINGS.life);
const root = ptr(BINDINGS.root), route = ptr(BINDINGS.route);
const method = (object, offset) => object.readPointer().add(offset).readPointer();
for (const [offset, rva] of [[0x30, 0x26479C0], [0x38, 0x264BDF0], [0xB0, 0x2604E60]])
if (!method(route, offset).equals(base.add(rva))) throw Error('Original route interface changed');
const setDestination = new NativeFunction(method(route, 0x30), 'void',
['pointer', 'int', 'pointer', 'pointer', 'pointer', 'pointer', 'uchar', 'uchar']);
const calculate = new NativeFunction(method(route, 0x38), 'void', ['pointer', 'int']);
const destination = Memory.alloc(8), body = Memory.alloc(8), market = Memory.alloc(8), settlement = Memory.alloc(8);
destination.writeU64(uint64(BINDINGS.target));
body.writeU64(512); market.writeS64(int64('-1')); settlement.writeS64(int64('-1'));
let attempted = false;
const valid = () => Process.getCurrentThreadId() === BINDINGS.thread
&& life.add(0xB0).readU64().toString() === BINDINGS.entity && life.add(0xC0).readU32() === 8
&& root.add(0x18).readPointer().add(BINDINGS.slot * 8).readPointer().equals(route)
&& fsd.add(0x758).readU8() === 2 && fsd.add(0x759).readU8() === BINDINGS.mode;
Interceptor.attach(base.add(0x2C71500), {
onEnter(args) { this.selected = !attempted && args[0].equals(fsd) && valid(); },
onLeave() {
if (!this.selected || attempted) return;
attempted = true;
try {
if (!valid()) throw Error('The player route context changed before application');
const previous = route.add(0x148).readU64().toString();
setDestination(route, 0, destination, body, market, settlement, 0, 0);
if (route.add(0x148).readU64().toString() !== BINDINGS.target)
throw Error('The game did not accept the requested route destination');
calculate(route, 0);
send({kind:'original-route-request', at:new Date().toISOString(), previous,
destination:route.add(0x148).readU64().toString(), thread:Process.getCurrentThreadId(),
setMethodRva:'0x26479c0', calculateMethodRva:'0x264bdf0',
gameCalculated:true, flightInputsSent:0, journalWrites:0, screenUse:false});
} catch (error) { send({kind:'error', error:String(error)}); }
}
});
send({kind:'ready', pid:Process.id, flightInputsSent:0, screenUse:false});
'use strict';
// Calls the two original route APIs on the player's FSD owning thread. No
// flight inputs, journal writes, custom graph search or fabricated route data.
const mod = Process.getModuleByName('EliteDangerous64.exe');
if (Process.id !== BINDINGS.pid || mod.path.toLowerCase() !== PROFILE.image.toLowerCase())
throw Error('Selected process image changed');
const base = mod.base, fsd = ptr(BINDINGS.fsd), life = ptr(BINDINGS.life);
const root = ptr(BINDINGS.root), route = ptr(BINDINGS.route);
const method = (object, offset) => object.readPointer().add(offset).readPointer();
for (const [offset, rva] of [[0x30, 0x26479C0], [0x38, 0x264BDF0], [0xB0, 0x2604E60]])
if (!method(route, offset).equals(base.add(rva))) throw Error('Original route interface changed');
const setDestination = new NativeFunction(method(route, 0x30), 'void',
['pointer', 'int', 'pointer', 'pointer', 'pointer', 'pointer', 'uchar', 'uchar']);
const calculate = new NativeFunction(method(route, 0x38), 'void', ['pointer', 'int']);
const destination = Memory.alloc(8), body = Memory.alloc(8), market = Memory.alloc(8), settlement = Memory.alloc(8);
destination.writeU64(uint64(BINDINGS.target));
body.writeU64(512); market.writeS64(int64('-1')); settlement.writeS64(int64('-1'));
let attempted = false;
const valid = () => Process.getCurrentThreadId() === BINDINGS.thread
&& life.add(0xB0).readU64().toString() === BINDINGS.entity && life.add(0xC0).readU32() === 8
&& root.add(0x18).readPointer().add(BINDINGS.slot * 8).readPointer().equals(route)
&& fsd.add(0x758).readU8() === 2 && fsd.add(0x759).readU8() === BINDINGS.mode;
Interceptor.attach(base.add(0x2C71500), {
onEnter(args) { this.selected = !attempted && args[0].equals(fsd) && valid(); },
onLeave() {
if (!this.selected || attempted) return;
attempted = true;
try {
if (!valid()) throw Error('The player route context changed before application');
const previous = route.add(0x148).readU64().toString();
setDestination(route, 0, destination, body, market, settlement, 0, 0);
if (route.add(0x148).readU64().toString() !== BINDINGS.target)
throw Error('The game did not accept the requested route destination');
calculate(route, 0);
send({kind:'original-route-request', at:new Date().toISOString(), previous,
destination:route.add(0x148).readU64().toString(), thread:Process.getCurrentThreadId(),
setMethodRva:'0x26479c0', calculateMethodRva:'0x264bdf0',
gameCalculated:true, flightInputsSent:0, journalWrites:0, screenUse:false});
} catch (error) { send({kind:'error', error:String(error)}); }
}
});
send({kind:'ready', pid:Process.id, flightInputsSent:0, screenUse:false});