Skip to content

Commit

Permalink
split source files
Browse files Browse the repository at this point in the history
  • Loading branch information
theyareonit committed Aug 13, 2024
1 parent 87808e8 commit 8ce58f2
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 182 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ project(ClickBetweenFrames VERSION 1.0.0)

add_library(${PROJECT_NAME} SHARED
"src/main.cpp"
"src/input.cpp"
)

if (NOT DEFINED ENV{GEODE_SDK})
Expand Down
2 changes: 1 addition & 1 deletion mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"gd": {
"win": "2.206"
},
"version": "v1.1.21",
"version": "v1.1.22",
"id": "syzzi.click_between_frames",
"name": "Click Between Frames",
"developer": "syzzi",
Expand Down
51 changes: 51 additions & 0 deletions src/includes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once

#include <queue>
#include <Geode/Geode.hpp>

using namespace geode::prelude;

enum GameAction : int {
p1Jump = 0,
p1Left = 1,
p1Right = 2,
p2Jump = 3,
p2Left = 4,
p2Right = 5
};

enum Player : bool {
Player1 = 0,
Player2 = 1
};

enum State : bool {
Press = 0,
Release = 1
};

struct InputEvent {
LARGE_INTEGER time;
PlayerButton inputType;
bool inputState;
bool player;
};

struct Step {
InputEvent input;
double deltaFactor;
bool endStep;
};

extern std::queue<struct InputEvent> inputQueue;

extern std::unordered_set<size_t> inputBinds[6];
extern std::unordered_set<USHORT> heldInputs;

extern CRITICAL_SECTION inputQueueLock;
extern CRITICAL_SECTION keybindsLock;

extern bool enableRightClick;
extern bool threadPriority;

void inputThread();
146 changes: 146 additions & 0 deletions src/input.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "includes.hpp"

std::queue<struct InputEvent> inputQueue;

std::unordered_set<size_t> inputBinds[6];
std::unordered_set<USHORT> heldInputs;

CRITICAL_SECTION inputQueueLock;
CRITICAL_SECTION keybindsLock;

bool enableRightClick;
bool threadPriority;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
LARGE_INTEGER time;
PlayerButton inputType;
bool inputState;
bool player;

QueryPerformanceCounter(&time);

LPVOID pData;
switch (uMsg) {
case WM_INPUT: {
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));

auto lpb = std::unique_ptr<BYTE[]>(new BYTE[dwSize]);
if (!lpb) {
return 0;
}
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb.get(), &dwSize, sizeof(RAWINPUTHEADER)) != dwSize) {
log::debug("GetRawInputData does not return correct size");
}

RAWINPUT* raw = (RAWINPUT*)lpb.get();
switch (raw->header.dwType) {
case RIM_TYPEKEYBOARD: {
USHORT vkey = raw->data.keyboard.VKey;
inputState = raw->data.keyboard.Flags & RI_KEY_BREAK;

if (vkey >= VK_NUMPAD0 && vkey <= VK_NUMPAD9) vkey -= 0x30; // make numpad numbers work with customkeybinds

// cocos2d::enumKeyCodes corresponds directly to vkeys
if (heldInputs.contains(vkey)) {
if (!inputState) return 0;
else heldInputs.erase(vkey);
}

bool shouldEmplace = true;
player = Player1;

EnterCriticalSection(&keybindsLock);

if (inputBinds[p1Jump].contains(vkey)) inputType = PlayerButton::Jump;
else if (inputBinds[p1Left].contains(vkey)) inputType = PlayerButton::Left;
else if (inputBinds[p1Right].contains(vkey)) inputType = PlayerButton::Right;
else {
player = Player2;
if (inputBinds[p2Jump].contains(vkey)) inputType = PlayerButton::Jump;
else if (inputBinds[p2Left].contains(vkey)) inputType = PlayerButton::Left;
else if (inputBinds[p2Right].contains(vkey)) inputType = PlayerButton::Right;
else shouldEmplace = false;
}
if (!inputState) heldInputs.emplace(vkey);

LeaveCriticalSection(&keybindsLock);

if (!shouldEmplace) return 0; // has to be done outside of the critical section
break;
}
case RIM_TYPEMOUSE: {
USHORT flags = raw->data.mouse.usButtonFlags;
bool shouldEmplace = true;
player = Player1;
inputType = PlayerButton::Jump;

EnterCriticalSection(&keybindsLock);
bool rc = enableRightClick;
LeaveCriticalSection(&keybindsLock);

if (flags & RI_MOUSE_BUTTON_1_DOWN) inputState = Press;
else if (flags & RI_MOUSE_BUTTON_1_UP) inputState = Release;
else {
player = Player2;
if (!rc) return 0;
if (flags & RI_MOUSE_BUTTON_2_DOWN) inputState = Press;
else if (flags & RI_MOUSE_BUTTON_2_UP) inputState = Release;
else return 0;
}
break;
}
default:
return 0;
}
break;
}
default:
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}

EnterCriticalSection(&inputQueueLock);
inputQueue.emplace(InputEvent{ time, inputType, inputState, player });
LeaveCriticalSection(&inputQueueLock);

return 0;
}

void inputThread() {

WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandleA(NULL);
wc.lpszClassName = "CBF";

RegisterClass(&wc);
HWND hwnd = CreateWindow("CBF", "Raw Input Window", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, wc.hInstance, 0);
if (!hwnd) {
const DWORD err = GetLastError();
log::error("Failed to create raw input window: {}", err);
return;
}

RAWINPUTDEVICE dev[2];
dev[0].usUsagePage = 0x01; // generic desktop controls
dev[0].usUsage = 0x02; // mouse
dev[0].dwFlags = RIDEV_INPUTSINK; // allow inputs without being in the foreground
dev[0].hwndTarget = hwnd; // raw input window

dev[1].usUsagePage = 0x01;
dev[1].usUsage = 0x06; // keyboard
dev[1].dwFlags = RIDEV_INPUTSINK;
dev[1].hwndTarget = hwnd;

if (!RegisterRawInputDevices(dev, 2, sizeof(dev[0]))) {
log::error("Failed to register raw input devices");
return;
}

if (threadPriority) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

MSG msg;
while (GetMessage(&msg, hwnd, 0, 0)) {
DispatchMessage(&msg);
}
}
Loading

0 comments on commit 8ce58f2

Please sign in to comment.