Skip to content

Commit

Permalink
Feature: Pixel detection
Browse files Browse the repository at this point in the history
  • Loading branch information
PassiveLemon committed Dec 24, 2024
1 parent 415fa28 commit 95dccd0
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
**/result
*.out
*.ppm

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ A Nim based fishing script Webfishing
- [x] `-v | --version`
- [x] `-f | --file` (Config file to load)
- [x] `-d | --device` (Device for input)
- [x] mode argument (fishing, bucketting, or combo)
- [x] mode argument (fish, bucket, or combo)
- [ ] Sensory
- [ ] Capture screen and analyze pixels (X11 wrapper)
- [ ] Receive/send keyboard inputs (libevdev wrapper)
Expand Down
5 changes: 4 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{ lib
, buildNimPackage
, xorg
}:
buildNimPackage (finalAttrs: {
pname = "webfisher";
Expand All @@ -11,7 +12,9 @@ buildNimPackage (finalAttrs: {

lockFile = ./lock.json;

buildInputs = [ ];
buildInputs = [
xorg.libXext
];

meta = with lib; {
description = "A Nim based fishing script for Webfishing";
Expand Down
33 changes: 26 additions & 7 deletions src/webfisher.nim
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
# import
# std/os
import
std/os

import
webfisher / [
config,
functions
pixel
]

# import
# x11/xlib,
# libevdev
import
x11/xlib


type
GlobalState* = object
fishingGameActive: bool
bucketGameActive: bool
comboGameActive: bool

var globalState*: GlobalState

block webfisher:
let config: configType = initConfig()
let
config: Config = initConfig()
display: PDisplay = XOpenDisplay(nil)

echo config
echo "Config loaded."

while true:
echo "Simulated main loop"
if getFishingGame(display):
echo "Fishing game found"
sleep((config.checkInterval * 1000).int)

discard XCloseDisplay(display)

6 changes: 3 additions & 3 deletions src/webfisher/cli.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import


type
cliArgsType* = object
CliArgs* = object
file*: string
device*: string
mode*: string
Expand All @@ -33,8 +33,8 @@ proc cliVersion(): void =
echo fmt"Webfisher {releaseVersion}"
quit(0)

proc processCliArgs*(): cliArgsType =
var cliArgs: cliArgsType
proc processCliArgs*(): CliArgs =
var cliArgs: CliArgs

for kind, key, val in getopt():
case kind
Expand Down
17 changes: 11 additions & 6 deletions src/webfisher/config.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import


type
configType* = object
Config* = object
castTime*: float
checkInterval*: float
reelInterval*: float
reelTime*: float
resetTime*: float
Expand All @@ -22,6 +23,7 @@ const
configJson: string = """
{
"castTime": 1.0,
"checkInterval": 0.5,
"reelInterval": 0.5,
"reelTime": 0.3,
"resetTime": 60.0
Expand Down Expand Up @@ -74,10 +76,10 @@ proc updateConfig(filePath: string): void =
echo "Could not update config file."

# Check and return parsed config
proc parseConfig(filePath: string, cliArgs: cliArgsType): configType =
proc parseConfig(filePath: string, cliArgs: CliArgs): Config =
var
node: JsonNode = parseFile(filePath)
json: configType
json: Config

# We can load CLI options into the programs config without writing them to the config file
if cliArgs.device == "":
Expand All @@ -98,6 +100,9 @@ proc parseConfig(filePath: string, cliArgs: cliArgsType): configType =
if node["castTime"].kind != JFloat:
echo "config castTime is not a float"
quit(1)
if node["checkInterval"].kind != JFloat:
echo "config castTime is not a float"
quit(1)
if node["reelInterval"].kind != JFloat:
echo "config reelInterval is not a float"
quit(1)
Expand All @@ -109,15 +114,15 @@ proc parseConfig(filePath: string, cliArgs: cliArgsType): configType =
quit(1)

try:
json = to(node, configType)
json = to(node, Config)
except JsonParsingError:
echo "Config file is not valid json."
quit(1)
finally:
return json

proc initConfig*(): configType =
let cliArgs: cliArgsType = processCliArgs()
proc initConfig*(): Config =
let cliArgs: CliArgs = processCliArgs()
var configDir: string = getRealUserConfigDir()

if cliArgs.file != "":
Expand Down
5 changes: 3 additions & 2 deletions src/webfisher/functions.nim → src/webfisher/evdev.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# proc screenshot() =
# return
# import
# libevdev


# proc press_key() =
# return
Expand Down
3 changes: 3 additions & 0 deletions src/webfisher/games.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import
./pixel

76 changes: 76 additions & 0 deletions src/webfisher/pixel.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import
./config

import
x11/xlib,
x11/xutil,
x11/x


type
Pixel* = object
color*: culong
r*, g*, b*: int

PixelList = seq[tuple[x, y, r, g, b: int]]


const# 428, 745
fishingGamePixels: PixelList = @[(428, 785, 156, 145, 74), (388, 745, 156, 145, 74), (428, 705, 156, 145, 74), (468, 745, 156, 145, 74)]


# saveToPPM: https://github.com/nim-lang/x11/blob/29aca5e519ebf5d833f63a6a2769e62ec7bfb83a/examples/xshmex.nim#L40
proc saveToPPM(image: PXImage, filePath: string) =
var f = open(filePath, fmWrite)
defer: f.close
writeLine(f, "P6")
writeLine(f, image.width, " ", image.height)
writeLine(f, 255)
for i in 0..<(image.width * image.height):
f.write(image.data[i * 4 + 2])
f.write(image.data[i * 4 + 1])
f.write(image.data[i * 4 + 0])

proc getScreenshot(display: PDisplay): PXImage =
return XGetImage(display, RootWindow(display, DefaultScreen(display)), 1920, 0, 1920, 1080, AllPlanes, ZPixmap)

proc getPixelColor(display: PDisplay, image: PXImage, x: int, y: int): Pixel =
var pixel: Pixel

pixel.color = XGetPixel(image, x.cint, y.cint)
# Could not figure out how to use this
#discard XQueryColor(display, DefaultColormap(display, Defaultscreen(display)), pixelX)
pixel.r = ((pixel.color shr 16) and 0xFF).int
pixel.g = ((pixel.color shr 8) and 0xFF).int
pixel.b = (pixel.color and 0xFF).int

return pixel

proc getFishingGame*(display: PDisplay): bool =
let screenshot: PXImage = getScreenshot(display)
var yes1, yes2, yes3: bool = false

# screenshot.saveToPPM("./screenshot.ppm")
for gamePixel in fishingGamePixels:
let pixel: Pixel = getPixelColor(display, screenshot, gamePixel.x, gamePixel.y)
#echo pixel
#echo gamePixel
if
pixel.r == gamePixel.r and
pixel.g == gamePixel.g and
pixel.b == gamePixel.b:

if not yes1:
yes1 = true
elif not yes2:
yes2 = true
else:
yes3 = true

if yes1 and yes2 and yes3:
return true
else:
return false

discard XDestroyImage(screenshot)

0 comments on commit 95dccd0

Please sign in to comment.