Skip to content

An event-based Node.js wrapper for ravahn's Machina network capture library.

License

Notifications You must be signed in to change notification settings

karashiiro/node-machina-ffxiv

Repository files navigation

Please use ffxiv-teamcraft/pcap-ffxiv for all new projects. This package is no longer actively maintained.

node-machina-ffxiv

A WIP Node.js wrapper for revahn's Machina network capture library.

Many features are unimplemented, and chat-related messages aren't completely working, but besides that what is implemented is probably usable.

If you so choose, you can use it exclusively as a wrapper for Machina with minimal data processing by assigning the raw data event as shown below.

Event type names and all packet structures are taken from the Sapphire server project.

NOTE: Most features besides the raw data event will break after every patch release until the IPC opcodes are updated in the Sapphire repo.

Installation

npm install node-machina-ffxiv

If you don't trust the copy of MachinaWrapperJSON that is built in the Github Action, feel free to also install Visual Studio 2017 Community Edition to build MachinaWrapperJSON and place the output in the MachinaWrapper folder.

Usage

Installing WinPCap is highly recommended, as it reduces the amount of additional setup that needs to be done. Set monitorType to "WinPCap" to enable WinPCap mode.

Otherwise, your application must be run in Administrator mode, and the .exe needs firewall in/out privileges, since it operates on Windows sockets.

Please refer to the wiki for usage.

Example

const MachinaFFXIV = require('node-machina-ffxiv');
const Machina = new MachinaFFXIV({}); // An object must be provided, even if it is empty.
Machina.start(() => {
    console.log("Machina started!");
});

// Assign event handlers
Machina.on('cFCommence', (content) => {
    console.log(`[${getTime()}]Duty commenced!`);
});

Machina.on('cFRegistered', (content) => {
    console.log(`[${getTime()}]Duty registration complete.`);
});

Machina.on('examineSearchInfo', (content) => {
    console.log(`Viewing search info.
        FC: ${content.fc}
        Search Comment: ${content.searchComment}
        World: ${content.world}
    `);
});

Machina.on('freeCompanyMemberLogin', (content) => {
    console.log(`[${getTime()}][FC]${content.character} has logged in.`);
});

Machina.on('freeCompanyMemberLogout', (content) => {
    console.log(`[${getTime()}][FC]${content.character} has logged out.`);
});

Machina.on('initZone', (content) => {
    console.log(`[${getTime()}]Zone loaded.`);
});

Machina.on('marketBoardItemListing', (content) => {
    var output = "HQ\tMateria\tPrice\tQuantity\tTotal\tCity\t\tRetainer\n";
    for (let i = 0; i < content.prices.length; i++) {
        output += `${content.qualities[i]}\t${content.materiaCounts[i]}\t${content.prices[i]}\t${content.quantities[i]}\t\t${content.totals[i]}\t${content.cities[i] !== "Ul'dah" && content.cities[i] !== "Kugane" && content.cities[i] !== "Ishgard" ? content.cities[i] :
                    (content.cities[i] === "Kugane" ? "Kugane\t" : (content.cities[i] === "Ishgard" ? "Ishgard\t" : "Ul'dah\t"))}\t${content.retainers[i]}\n`;
        if (content.materia[i].length > 0) output += `Materia: ${content.materia[i].toString()}\n`;
    }
    console.log(output);
});

Machina.on('message', (content) => { // Using a supertype event to streamline code
    console.log(`[${getTime()}][${content.type.slice(7)}]<${content.character}> ${content.message}`);
});

About

An event-based Node.js wrapper for ravahn's Machina network capture library.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published