Live log mod
Example apps / list-mod / v0.1.0
Node mod
A Node mod window built around a scrolling list: a live log that keeps its newest lines.
// Live log mod: a window built around ui.list, a list of lines that scrolls on its own.
// It keeps the newest 300 lines, follows the newest one unless you scroll up, and fills
// the window's free height, so the window itself never scrolls.
import { game, ui } from 'rednode';
const time = () => new Date().toLocaleTimeString();
const log = ui.list({ keep: 300 });
let lines = 0;
const count = ui.text('No lines yet.', { tone: 'dim' });
function add(text) {
log.push(`${time()} ${text}`);
lines++;
count.set({ text: `${lines} lines so far; the list keeps the newest 300.` });
}
ui.window({
title: 'Live log',
width: 440,
height: 380,
children: [
count,
log,
ui.row(
ui.button('Add a line', () => add('A line from the button')),
ui.button('Clear', () => log.clear(), { variant: 'ghost' }),
),
],
});
setInterval(async () => {
try {
const p = await game.player.position();
add(`V at ${p.x.toFixed(1)}, ${p.y.toFixed(1)}, ${p.z.toFixed(1)}`);
} catch (err) {
add(`No position: ${err.message}`);
}
}, 2000);
game.on('PlayerPuppet.OnGameAttached', (e) => add(`Game event ${e.name}`));
game.onState((s) => add(`State: ${Object.entries(s).filter(([, v]) => v === true).map(([k]) => k).join(', ') || 'gameplay'}`));
REDnode runs JavaScript. The rednode package also has TypeScript types, so an editor checks these calls; compile TypeScript to .mjs first.
{
"id": "list-mod",
"name": "Live log mod",
"version": "0.1.0",
"author": "Edgemodders",
"description": "A Node mod with a scrolling list (ui.list): V's position every two seconds, game events and state changes, newest at the bottom. The window never scrolls; the list does.",
"main": "mod.mjs",
"open": false
}
The manifest names the package and says how REDnode runs it. Its fields are in Overlay apps.
How it works
ui.list makes a list of lines that scrolls on its own. push adds lines at the bottom; only the new lines travel to the window, so feeding it often stays cheap.
It keeps the newest lines only (keep, here 300) and follows the newest line unless the player has scrolled up.
Without a height, the list fills the space the other nodes leave, so the window keeps its size and never scrolls: give it a height in pixels to fix it instead.
What it uses
ui.list list.push list.clear game.onState
Try this
- Watch a line arrive every two seconds.
- Scroll the list up: it stays put while lines arrive; scroll back down and it follows again.
- Press Clear.
Use it
Copy the files into red4ext/plugins/REDnode/apps/list-mod/ in the game folder, or start your own package from them: change id and name in the manifest first. The whole folder is on GitHub.