Initial commit: POE2 automated trade bot
Monitors pathofexile.com/trade2 for new listings, travels to seller hideouts, buys items from public stash tabs, and stores them. Includes persistent C# OCR daemon for fast screen capture + Windows native OCR, web dashboard for managing trade links and settings, and full game automation via Win32 SendInput. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
41d174195e
28 changed files with 6449 additions and 0 deletions
107
src/game/GameController.ts
Normal file
107
src/game/GameController.ts
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
import { WindowManager } from './WindowManager.js';
|
||||
import { InputSender, VK } from './InputSender.js';
|
||||
import { sleep, randomDelay } from '../util/sleep.js';
|
||||
import { writeClipboard } from '../util/clipboard.js';
|
||||
import { logger } from '../util/logger.js';
|
||||
import type { Config } from '../types.js';
|
||||
|
||||
export class GameController {
|
||||
private windowManager: WindowManager;
|
||||
private inputSender: InputSender;
|
||||
|
||||
constructor(config: Config) {
|
||||
this.windowManager = new WindowManager(config.poe2WindowTitle);
|
||||
this.inputSender = new InputSender();
|
||||
}
|
||||
|
||||
async focusGame(): Promise<boolean> {
|
||||
const result = this.windowManager.focusWindow();
|
||||
if (result) {
|
||||
await sleep(300); // Wait for window to actually focus
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
isGameFocused(): boolean {
|
||||
return this.windowManager.isGameFocused();
|
||||
}
|
||||
|
||||
getWindowRect() {
|
||||
return this.windowManager.getWindowRect();
|
||||
}
|
||||
|
||||
async sendChat(message: string): Promise<void> {
|
||||
logger.info({ message }, 'Sending chat message');
|
||||
|
||||
// Open chat
|
||||
await this.inputSender.pressKey(VK.RETURN);
|
||||
await randomDelay(100, 200);
|
||||
|
||||
// Clear any existing text
|
||||
await this.inputSender.selectAll();
|
||||
await sleep(50);
|
||||
await this.inputSender.pressKey(VK.DELETE);
|
||||
await sleep(50);
|
||||
|
||||
// Type the message
|
||||
await this.inputSender.typeText(message);
|
||||
await randomDelay(50, 100);
|
||||
|
||||
// Send
|
||||
await this.inputSender.pressKey(VK.RETURN);
|
||||
await sleep(100);
|
||||
}
|
||||
|
||||
async sendChatViaPaste(message: string): Promise<void> {
|
||||
logger.info({ message }, 'Sending chat message via paste');
|
||||
|
||||
// Copy message to clipboard
|
||||
writeClipboard(message);
|
||||
await sleep(50);
|
||||
|
||||
// Open chat
|
||||
await this.inputSender.pressKey(VK.RETURN);
|
||||
await randomDelay(100, 200);
|
||||
|
||||
// Clear any existing text
|
||||
await this.inputSender.selectAll();
|
||||
await sleep(50);
|
||||
await this.inputSender.pressKey(VK.DELETE);
|
||||
await sleep(50);
|
||||
|
||||
// Paste
|
||||
await this.inputSender.paste();
|
||||
await randomDelay(100, 200);
|
||||
|
||||
// Send
|
||||
await this.inputSender.pressKey(VK.RETURN);
|
||||
await sleep(100);
|
||||
}
|
||||
|
||||
async goToHideout(): Promise<void> {
|
||||
logger.info('Sending /hideout command');
|
||||
await this.sendChat('/hideout');
|
||||
}
|
||||
|
||||
async ctrlRightClickAt(x: number, y: number): Promise<void> {
|
||||
await this.inputSender.ctrlRightClick(x, y);
|
||||
}
|
||||
|
||||
async leftClickAt(x: number, y: number): Promise<void> {
|
||||
await this.inputSender.leftClick(x, y);
|
||||
}
|
||||
|
||||
async rightClickAt(x: number, y: number): Promise<void> {
|
||||
await this.inputSender.rightClick(x, y);
|
||||
}
|
||||
|
||||
async pressEscape(): Promise<void> {
|
||||
await this.inputSender.pressKey(VK.ESCAPE);
|
||||
}
|
||||
|
||||
async openInventory(): Promise<void> {
|
||||
logger.info('Opening inventory');
|
||||
await this.inputSender.pressKey(VK.I);
|
||||
await sleep(300);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue