Overview: What core.py is for
At its core (no pun intended), this script is designed to find, activate, and standardize the game client window typically for automation, scripting, or botting purposes.
It doesn’t directly play the game or automate any actions by itself.
Instead, it prepares the environment so that other parts of the bot can interact with the game screen reliably.
Think of it as the foundation layer of a larger automation system.
Github source can be found here: https://github.com/slyautomation/osrs_basic_botting_functions
The main purpose
When automating or capturing input from a desktop application like RuneLite or OpenOSRS (both used for playing Old School RuneScape), consistency is everything.
If the window position or size changes, every pixel coordinate, mouse click, or screenshot-based detection could break.
This core.py script ensures the following:
- The game client is found automatically.
The script scans all active windows and matches one whose title matches the configuration (for example, “RuneLite”). - The client window is activated and brought to the front.
This ensures that any follow-up automation (such as mouse movement, keypresses, or image detection) acts on the correct window. - The client is positioned and resized consistently.
The script moves the window to coordinates (0, 0) and resizes it to exactly 865×830 pixels every time the program runs.
This fixed frame of reference is crucial for accurate coordinate-based logic. - It supports multiple operating systems.
The script automatically adjusts its methods based on whether it’s running on Windows, Linux, or macOS, making the automation cross-platform. - It helps diagnose setup problems.
If the script can’t find the game client, it prints all visible window names to help the user verify the correct title to use in the YAML config.
Typical use case in a project
This file would usually be part of a larger automation package that might include other scripts such as:
- image_recognition.py – Captures screenshots of the game window and detects objects or UI elements using OpenCV.
- actions.py – Simulates human-like mouse movement and clicks inside the window.
- logic.py – Contains the decision-making AI or rule-based logic (e.g., “if inventory full, go to bank”).
- config.yaml – Defines which client to use and possibly other user-defined parameters.
core.py would typically be imported at the start of the main program, like this:
from core import findWindow, getWindow
Then, the main script could call:
x, y, w, h = getWindow("RuneLite")
to make sure everything is aligned and ready before starting any automation routines.
In simple terms
You can think of core.py as the “window control and environment setup” module for an automation framework.
It handles:
- Detection of the game window
- Activation and focusing
- Positioning and resizing
- OS compatibility handling
It ensures that the rest of the system always interacts with a known, predictable visual frame no surprises, no misalignment.
Step 1: Import required libraries
The script begins by importing several Python modules:
import win32gui
import yaml
import platform
- win32gui – provides access to Windows GUI functions, allowing the script to find and control application windows.
- yaml – reads configuration data stored in a YAML file.
- platform – detects the operating system (Windows, Linux, or macOS).
The script also defines a global variable hwnd (window handle) to store references to a specific window later on.
Step 2: Load configuration from a YAML file
with open("pybot-config.yaml", "r") as yamlfile:
data = yaml.load(yamlfile, Loader=yaml.FullLoader)
This section loads settings from a file called pybot-config.yaml.
The configuration file likely contains key information such as which game client window to look for (for example, “RuneLite” or “OpenOSRS”).
Using yaml.FullLoader ensures the YAML data is safely and completely parsed into a Python dictionary called data.
Step 3: Define Linux-specific window control functions
Two functions are defined for Linux environments using the xdotool command-line utility.
a. findWindow_Linux(data)
def findWindow_Linux(data):
import subprocess
subprocess.call(["xdotool", "search", "--name", data, "windowfocus", "%2"])
subprocess.call(["xdotool", "getwindowfocus", "windowmove", "0", "0"])
subprocess.call(["xdotool", "getwindowfocus", "windowsize", "865", "830"])
This function:
- Finds the window whose title matches the value of
data. - Focuses the window.
- Moves it to position (0, 0) on the screen.
- Resizes it to 865×830 pixels.
b. getWindow_Linux(data)
def getWindow_Linux(data):
import subprocess
subprocess.call(["xdotool", "search", "--name", data, "windowfocus", "%2"])
rect = subprocess.call(["xdotool", "getwindowfocus", "getwindowgeometry"])
...
This function tries to:
- Focus on the window by its name.
- Retrieve its geometry (position and size).
- Adjust for border offsets to calculate the usable area of the window.
- Return
(x, y, w, h)— the coordinates and dimensions of the active window.
Step 4: Define Windows-specific window control functions
Several functions are used for Windows environments via the win32gui library.
a. findWindow_runelite() and findWindow_openosrs()
These two are specialized versions designed for specific game clients:
hwnd = win32gui.FindWindow(None, "RuneLite")
win32gui.SetActiveWindow(hwnd)
win32gui.MoveWindow(hwnd, 0, 0, 865, 830, True)
and
hwnd = win32gui.FindWindow(None, "OpenOSRS")
win32gui.SetActiveWindow(hwnd)
win32gui.MoveWindow(hwnd, 0, 0, 865, 830, True)
They:
- Find the window by its exact title.
- Bring it to the front and make it active.
- Move it to the top-left corner.
- Resize it to 865×830 pixels.
b. findWindow(data)
A general-purpose version that works for any window title passed in data.
c. getWindow(data)
Similar to findWindow, but also retrieves the window’s coordinates and size:
rect = win32gui.GetWindowRect(hwnd)
x = rect[0]
y = rect[1] + 30
w = rect[2] - x - 50
h = rect[3] - y - 30
Here, the offsets (30 and 50 pixels) compensate for the borders and title bar so the function returns the usable window region.
Step 5: Listing all visible windows
The printWindows() function loops through all open windows and prints their titles:
def printWindows():
def winEnumHandler(hwnd, ctx):
if win32gui.IsWindowVisible(hwnd):
if win32gui.GetWindowText(hwnd):
print(win32gui.GetWindowText(hwnd))
win32gui.EnumWindows(winEnumHandler, None)
This helps users see what window names exist, useful for debugging when the target window title doesn’t match.
Step 6: Detect the operating system
The script checks the current OS and runs the appropriate window function:
print('Operating system:', platform.system())
If the system is Linux or Mac, it uses the findWindow_Linux() function;
otherwise, it assumes Windows and uses findWindow().
Each block includes error handling — if the window can’t be found, it prints a helpful message and lists all visible windows as a reference.
Step 7: Summary of purpose
In short, this script automates the process of finding, focusing, positioning, and resizing a game client window (like RuneLite or OpenOSRS) on either Windows or Linux.
It’s commonly used as part of automation or botting frameworks where consistent window size and position are essential for accurate screen capture or mouse interaction.
Purpose of this section
This block of code decides which version of the window-finding function to run, depending on the user’s operating system.
It ensures that the right system commands or libraries are used for either Linux/macOS or Windows environments.
Step 1: Detecting the operating system
if platform.system() == 'Linux' or platform.system() == 'Mac':
The function platform.system() returns a string identifying the current operating system, such as:
'Windows''Linux''Mac'(for macOS)
Here, the script checks if the system is Linux or Mac.
If either is true, it executes the first branch of the if statement.
Otherwise, it assumes the script is running on Windows and goes to the else block.
Step 2: Linux/macOS branch
try:
findWindow_Linux(data[0]['Config']['client_title'])
Inside the try block:
- It calls the
findWindow_Linux()function (defined earlier). - The function is passed a window title, which it gets from the YAML configuration file that was loaded earlier in the script.
That YAML file is structured roughly like this:
- Config:
client_title: "RuneLite"
So data[0]['Config']['client_title'] would evaluate to "RuneLite" — or whatever window title the user defined in the config file.
This function will then:
- Search for that window using
xdotool. - Focus it.
- Move and resize it to a consistent location and size.
Step 3: Handling Linux/macOS errors
except BaseException:
print("unable to find window:", data[0]['Config']['client_title'], "please see list of window names below:")
printWindows()
pass
If something goes wrong (for example, the window name doesn’t exist or xdotool fails), the except block catches the error and:
- Prints an error message showing which window couldn’t be found.
- Calls the
printWindows()function to list all currently visible windows on the screen so the user can check what the correct name should be. - Uses
passsimply to skip over the error and let the program continue safely.
Step 4: Windows branch
else:
try:
findWindow(data[0]['Config']['client_title'])
If the system is not Linux or Mac, this part runs.
It calls findWindow() the Windows-specific function that:
- Uses the
win32guilibrary to find the window by title. - Activates it.
- Moves and resizes it.
Again, the same window title is pulled from the YAML config file.
Step 5: Handling Windows errors
except BaseException:
print("Unable to find window:", data[0]['Config']['client_title'], "| Please see list of window names below:")
printWindows()
pass
If the target window can’t be found (for instance, it’s not open or the title doesn’t match), the script:
- Prints a message saying it couldn’t find the specified window.
- Lists all available visible windows (again, via
printWindows()). - Uses
passto safely continue or exit without crashing.
Step 6: Why this matters
This section is the entry point that adapts the script’s behavior to different operating systems.
It ensures:
- On Linux/macOS, the script uses
xdotoolto manage windows. - On Windows, it uses
win32guiinstead. - If the configured window can’t be found, it gracefully falls back by listing what’s currently open a helpful way to debug or correct configuration mistakes.
Summary
In plain terms, this block says:
“Check which operating system we’re running on.
If it’s Linux or Mac, use the Linux function to find the target window title from the config file.
If it’s Windows, use the Windows function.
And if anything fails, tell the user which window couldn’t be found and show all visible windows for reference.”
Visualizing the logic flow
To better understand how this section works, imagine the script as following a simple decision tree.
- Start the program.
The script has already loaded its configuration file and now needs to find the correct game window. - Check which operating system is running.
It callsplatform.system()to identify the OS.- If the result is “Linux” or “Mac”, it will go down the left branch of the tree.
- If it’s anything else (most likely “Windows”), it takes the right branch.
- If on Linux or Mac (left branch):
- The script tries to run
findWindow_Linux()using the title found in the YAML config (for example, “RuneLite”). - If the window is successfully found:
- The script focuses on that window.
- It moves and resizes it to standard dimensions (865×830).
- The script continues normally.
- If the window cannot be found or any error occurs:
- The program prints an error message saying it was unable to find that window.
- Then it calls
printWindows()to display all currently visible window titles, helping the user correct the configuration. - Finally, it skips ahead without crashing.
- The script tries to run
- If on Windows (right branch):
- The script instead calls
findWindow()a Windows-specific function that uses thewin32guiAPI to locate and manipulate windows. - If the target window exists:
- It’s brought to the front, focused, and resized just like in the Linux branch.
- If it cannot be found:
- A similar error message appears.
printWindows()lists all open windows for reference.- The script passes over the error safely.
- The script instead calls
- End of flow.
Once one of these branches finishes (successfully or not), the initialization stage is complete.
At this point, the script has either locked onto the correct client window or informed the user how to fix the title mismatch.
Summary of the flow
You can think of it as a “choose your own path” logic:
Start
├── Is the OS Linux or Mac?
│ ├── Yes → Try findWindow_Linux()
│ │ ├── Success → Focus + Move + Resize window
│ │ └── Error → Print message + List open windows
│
└── No (Windows) → Try findWindow()
├── Success → Focus + Move + Resize window
└── Error → Print message + List open windows
This ensures the script works across multiple operating systems while handling any missing or incorrect window names gracefully.


