Skip to content

Commit bfa28d2

Browse files
committed
anti afk, resume flight, pause/resume out of bounds
1 parent 6310531 commit bfa28d2

File tree

2 files changed

+257
-3
lines changed

2 files changed

+257
-3
lines changed

src/skyblock/AntiAFK.ts

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
2+
import Config from '../libs/Config';
3+
import { Key } from '../libs/KeyManager';
4+
import { CommandManager } from '../libs/CommandBuilderWrapper';
5+
6+
interface AntiAFKConfig {
7+
enabled: boolean;
8+
}
9+
10+
export class AntiAFK {
11+
private readonly configPath = './config/jayc331-antiafk.json';
12+
private readonly scriptId = 'antiafk';
13+
private readonly defaultConfig: AntiAFKConfig = {
14+
enabled: true,
15+
};
16+
17+
private config: AntiAFKConfig;
18+
private readonly triggerSlot = 15;
19+
private isActive = false;
20+
private lastTitleTime = 0;
21+
22+
private readonly keys = {
23+
jump: new Key('key.keyboard.space'),
24+
sneak: new Key('key.keyboard.left.shift'),
25+
attack: new Key('key.mouse.left'),
26+
};
27+
28+
private onActivityChange?: (active: boolean) => void;
29+
30+
constructor(onActivityChange?: (active: boolean) => void) {
31+
this.onActivityChange = onActivityChange;
32+
this.config = Config.readConfig(this.configPath, this.defaultConfig, this.scriptId);
33+
this.registerListeners();
34+
this.registerCommands();
35+
}
36+
37+
private registerListeners() {
38+
JsMacros.on('OpenScreen', JavaWrapper.methodToJava((event) => this.onOpenScreen(event)));
39+
JsMacros.on('Title', JavaWrapper.methodToJava((event) => this.onTitle(event)));
40+
JsMacros.on('Tick', JavaWrapper.methodToJava(() => this.onTick()));
41+
}
42+
43+
private setActive(active: boolean) {
44+
if (this.isActive === active) return;
45+
this.isActive = active;
46+
if (this.onActivityChange) {
47+
this.onActivityChange(active);
48+
}
49+
if (!active) {
50+
Chat.log('§aAntiAFK: §7Check finished/timed out.');
51+
}
52+
}
53+
54+
private onTick() {
55+
if (!this.isActive) return;
56+
// 5 seconds timeout
57+
if (Date.now() - this.lastTitleTime > 5000) {
58+
this.setActive(false);
59+
}
60+
}
61+
62+
private saveConfig() {
63+
Config.writeConfig(this.configPath, this.config, this.scriptId);
64+
}
65+
66+
private onOpenScreen(event: Events.OpenScreen) {
67+
if (!this.config.enabled) return;
68+
69+
// We could add a check for specific GUI title if known, but for now rely on slot click
70+
// Use a small delay to ensure the GUI is fully ready and item is present
71+
const screen = event.screen;
72+
// Note: strict typings might be tricky with screen, check actual API if needed.
73+
// But usually we can access inventory from player context once screen is open.
74+
75+
// We wait a bit then click
76+
Client.waitTick(5);
77+
78+
// Check if screen is still open (user might have closed it quickly)
79+
if (!Hud.getOpenScreen()) return;
80+
81+
// Check player to avoid NPE
82+
if (!Player.getPlayer()) return;
83+
84+
const inv = Player.openInventory();
85+
if (!inv) return;
86+
87+
// Filter for "Activity Check" GUI
88+
if (!inv.getContainerTitle().includes('Activity Check')) return;
89+
90+
// We assume if the GUI opens and we are enabled, we try to start the check.
91+
// In a real scenario, we should probably check the container name or item name.
92+
// But based on prompt: "A gui is opened containing an item... click to begin"
93+
94+
// Double check if slot is valid for this inventory?
95+
// inv.getSlot(this.config.triggerSlot) might throw or return null?
96+
97+
try {
98+
inv.click(this.triggerSlot);
99+
this.lastTitleTime = Date.now(); // Set time before activating to avoid instant timeout
100+
this.setActive(true);
101+
Chat.log('§aAntiAFK: §7Clicking start slot...');
102+
} catch (e) {
103+
Chat.log('§cAntiAFK Error clicking slot: ' + e);
104+
}
105+
}
106+
107+
private onTitle(event: Events.Title) {
108+
if (!this.config.enabled) return;
109+
// If we haven't clicked start recently, maybe we shouldn't auto-react?
110+
// But the prompt implies "a series of titles appear... macro should follow".
111+
// So even if we didn't trigger the start (maybe user did), we should help if enabled.
112+
113+
if (!event.message) return;
114+
const text = event.message.getString().trim();
115+
const lowerText = text.toLowerCase();
116+
117+
// If we receive a title, and we are (or should be) active, update time
118+
if (this.isActive || lowerText.includes('look') || lowerText.includes('jump') || lowerText.includes('sneak') || lowerText.includes('punch')) {
119+
this.lastTitleTime = Date.now();
120+
if (!this.isActive) this.setActive(true);
121+
}
122+
123+
// Logging for debug
124+
// Chat.log('§7Title: ' + text);
125+
126+
const player = Player.getPlayer();
127+
if (!player) return;
128+
129+
if (lowerText.includes('look left')) {
130+
Chat.log('§aAntiAFK: §7Looking LEFT');
131+
const yaw = player.getYaw();
132+
player.lookAt(yaw - 90, player.getPitch());
133+
} else if (lowerText.includes('look right')) {
134+
Chat.log('§aAntiAFK: §7Looking RIGHT');
135+
const yaw = player.getYaw();
136+
player.lookAt(yaw + 90, player.getPitch());
137+
} else if (lowerText.includes('look down')) {
138+
Chat.log('§aAntiAFK: §7Looking DOWN');
139+
player.lookAt(player.getYaw(), 90);
140+
} else if (lowerText.includes('look up')) {
141+
Chat.log('§aAntiAFK: §7Looking UP');
142+
player.lookAt(player.getYaw(), -90);
143+
} else if (lowerText.includes('jump')) {
144+
Chat.log('§aAntiAFK: §7Jumping');
145+
this.keys.jump.click();
146+
} else if (lowerText.includes('sneak')) {
147+
Chat.log('§aAntiAFK: §7Sneaking');
148+
this.keys.sneak.set(true);
149+
Client.waitTick(10);
150+
this.keys.sneak.set(false);
151+
} else if (lowerText.includes('punch') || lowerText.includes('attack')) {
152+
Chat.log('§aAntiAFK: §7Punching');
153+
this.keys.attack.click();
154+
}
155+
}
156+
157+
private registerCommands() {
158+
const cmd = CommandManager.create('antiafk');
159+
160+
cmd.literal('toggle')
161+
.executes(() => {
162+
this.config.enabled = !this.config.enabled;
163+
this.saveConfig();
164+
Chat.log(`§7AntiAFK is now ${this.config.enabled ? '§aENABLED' : '§cDISABLED'}`);
165+
});
166+
167+
cmd.register();
168+
}
169+
}

src/skyblock/main.ts

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { updateScript } from '../libs/Updater';
22
updateScript(file.getAbsolutePath(), 'jayc331/JSMacros-Scripts', './config/jayc331-config.json');
33

44
import Config from '../libs/Config';
5+
import { AntiAFK } from './AntiAFK';
56
import { BaritoneAPI, BetterBlockPos } from '../libs/BaritoneAPIProvider';
67
import { Key } from '../libs/KeyManager';
78
import { CommandManager } from '../libs/CommandBuilderWrapper';
@@ -87,6 +88,8 @@ class StrafingScript {
8788
private statusMessage = '';
8889
private statusExpiry = 0;
8990
public isRunning = false; // Only flag needed for running/stopped state
91+
private isStarting = false;
92+
private startTickCounter = 0;
9093
private lastClickTime: { left: number; right: number } = { left: 0, right: 0 };
9194
// Key definitions
9295
private readonly keys = {
@@ -95,7 +98,10 @@ class StrafingScript {
9598
mouseLeft: new Key('key.mouse.left'),
9699
mouseRight: new Key('key.mouse.right'),
97100
sneak: new Key('key.keyboard.left.shift'),
101+
jump: new Key('key.keyboard.space'),
98102
};
103+
104+
public isPaused = false;
99105

100106
constructor() {
101107
this.config = Config.readConfig(this.configPath, this.defaultConfig, this.scriptId);
@@ -110,6 +116,22 @@ class StrafingScript {
110116
this.statusExpiry = Date.now() + duration;
111117
Chat.actionbar(msg); // Show immediately
112118
}
119+
120+
public pause() {
121+
if (!this.isRunning || this.isPaused) return;
122+
this.isPaused = true;
123+
// Keep tick listener active, but clean up keys so player can move freely
124+
this.cleanupKeys();
125+
this.showStatus('§eStrafing paused (Out of Bounds).');
126+
}
127+
128+
public resume() {
129+
if (!this.isRunning || !this.isPaused) return; // Must be running and paused to resume
130+
this.isPaused = false;
131+
// Tick listener is already active, no need to re-attach.
132+
// Input handling will resume automatically in tick().
133+
this.showStatus('§aStrafing resumed.');
134+
}
113135

114136
public setPosition(index: 1 | 2, pos: any) {
115137
const coords = { x: Math.floor(pos.getX()), y: Math.floor(pos.getY()), z: Math.floor(pos.getZ()) };
@@ -229,7 +251,9 @@ class StrafingScript {
229251
return;
230252
}
231253

232-
this.isRunning = true; // Set running state immediately
254+
this.isRunning = true;
255+
this.isStarting = true;
256+
this.startTickCounter = 0;
233257

234258
// Visuals
235259
try {
@@ -254,7 +278,7 @@ class StrafingScript {
254278
);
255279
}
256280

257-
this.showStatus('§aStrafing started!');
281+
this.showStatus('§aStrafing initializing...');
258282
}
259283

260284
private updateVisuals() {
@@ -292,17 +316,74 @@ class StrafingScript {
292316
return x < minX || x > maxX || y < minY || y > maxY || z < minZ || z > maxZ;
293317
}
294318

319+
private handleStartup() {
320+
const player = Player.getPlayer();
321+
if (!player) return;
322+
323+
if (this.startTickCounter === 0) {
324+
if (player.getAbilities().getFlying()) {
325+
this.isStarting = false;
326+
this.showStatus('§aStrafing started!');
327+
return;
328+
}
329+
Chat.log('§7Enabling flight...');
330+
}
331+
332+
const tick = this.startTickCounter;
333+
this.startTickCounter++;
334+
335+
if (tick === 0) this.keys.jump.set(true);
336+
if (tick === 2) this.keys.jump.set(false);
337+
if (tick === 4) this.keys.jump.set(true);
338+
if (tick === 25) this.keys.jump.set(false);
339+
340+
if (tick > 25) {
341+
if (player.getAbilities().getFlying()) {
342+
this.isStarting = false;
343+
this.showStatus('§aStrafing started!');
344+
} else if (tick > 60) {
345+
// Timeout - Retry
346+
this.startTickCounter = 0;
347+
}
348+
}
349+
}
350+
295351
private tick() {
296352
try {
297353
if (!this.isRunning) return;
298354

355+
// If paused, only check for re-entry, otherwise skip main logic
356+
if (this.isPaused) {
357+
const player = Player.getPlayer();
358+
if (!player) return;
359+
const pPos = player.getPos();
360+
if (!this.isOutOfBounds(pPos)) { // Re-entered bounds
361+
this.resume();
362+
}
363+
return; // Skip rest of tick logic while paused
364+
}
365+
366+
if (this.isStarting) {
367+
this.handleStartup();
368+
return;
369+
}
370+
299371
const player = Player.getPlayer();
300372
if (!player) return;
301373

302374
const pPos = player.getPos();
303375

376+
// Change this from stop() to pause()
304377
if (this.isOutOfBounds(pPos)) {
305-
this.stop();
378+
this.pause(); // Now pauses, doesn't stop
379+
return;
380+
}
381+
382+
// Auto-re-enable flight if lost
383+
if (!player.getAbilities().getFlying()) {
384+
this.isStarting = true;
385+
this.startTickCounter = 0;
386+
this.cleanupKeys();
306387
return;
307388
}
308389

@@ -440,6 +521,10 @@ class StrafingScript {
440521
// =============================================================================
441522

442523
const strafer = new StrafingScript();
524+
const antiAFK = new AntiAFK((active) => {
525+
if (active) strafer.pause();
526+
else strafer.resume();
527+
});
443528

444529
// Export cleanup for JsMacros
445530
(event as any).stopListener = JavaWrapper.methodToJava(() => strafer.stop());

0 commit comments

Comments
 (0)