chore: initial import of gregWiki

This commit is contained in:
Marvin
2026-04-15 23:38:15 +02:00
commit 0d3d969713
482 changed files with 48850 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
node_modules
dist
.astro
.git
.github
.vscode
npm-debug.log
Dockerfile
.dockerignore
+1
View File
@@ -0,0 +1 @@
node_modules
+18
View File
@@ -0,0 +1,18 @@
# Build stage
FROM node:22-alpine AS build
WORKDIR /app
# Install pnpm
RUN npm install -g pnpm
COPY package.json pnpm-lock.yaml* ./
RUN pnpm install --frozen-lockfile || pnpm install
COPY . .
RUN pnpm run build
# Production stage
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+16
View File
@@ -0,0 +1,16 @@
# gregWiki - Instructions
## Projekt-Kontext
Dieses Verzeichnis ist spezifisch für: gregWiki
## Technologie-Stack
- **Primäre Technologie**: Astro
## Spezifische Details & Regeln für Crush
- Static Site Generation via Astro.
- Styling: TailwindCSS.
## KI-Verhaltensregeln
1. Analysiere vor Änderungen die spezifischen Projektdateien (z.B. `package.json`, `.csproj`, `Cargo.toml`).
2. Respektiere die bestehende Code-Architektur und den Linter/Formatter des Projekts.
3. Lösche keine bestehenden Dateien ohne explizite Aufforderung.
+6
View File
@@ -0,0 +1,6 @@
## Contributors
- @mleem97
- @Joniii11
+55
View File
@@ -0,0 +1,55 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import react from '@astrojs/react';
import tailwindcss from '@tailwindcss/vite';
// https://astro.build/config
export default defineConfig({
site: 'https://wiki.gregframework.eu',
integrations: [
starlight({
title: 'gregWiki',
description: 'The authoritative documentation for gregFramework and Data Center modding.',
social: [
{ icon: 'github', label: 'GitHub', href: 'https://github.com/mleem97/gregCore' },
],
editLink: {
baseUrl: 'https://github.com/mleem97/gregFramework/edit/main/gregWiki/',
},
sidebar: [
{
label: 'Getting Started',
autogenerate: { directory: '01_getting-started' },
},
{
label: 'Development',
autogenerate: { directory: '02_development' },
},
{
label: 'Design System',
autogenerate: { directory: '03_design-system' },
},
{
label: 'Community',
autogenerate: { directory: '04_community' },
},
{
label: 'Legal',
autogenerate: { directory: '05_legal' },
},
{
label: 'Tools',
autogenerate: { directory: '06_tools' },
},
],
customCss: [
'./src/styles/custom.css',
'./src/styles/global.css',
],
}),
react(),
],
vite: {
plugins: [tailwindcss()],
},
});
+9
View File
@@ -0,0 +1,9 @@
version: '3.8'
services:
wiki:
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:80"
+31
View File
@@ -0,0 +1,31 @@
{
"name": "greg-wiki",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^5.0.3",
"@astrojs/starlight": "^0.38.3",
"@tailwindcss/vite": "^4.2.2",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"astro": "^6.1.6",
"clsx": "^2.1.1",
"framer-motion": "^12.38.0",
"gsap": "^3.15.0",
"lucide-react": "^1.8.0",
"ogl": "^1.0.11",
"react": "^19.2.5",
"react-dom": "^19.2.5",
"react-icons": "^5.6.0",
"sharp": "^0.34.5",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.2"
}
}
+4908
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
<rect width="64" height="64" rx="14" fill="#0f172a"/>
<path d="M17 20h30v24H17z" fill="#14b8a6"/>
<path d="M22 26h20v2H22zm0 6h14v2H22zm0 6h10v2H22z" fill="#0f172a"/>
<circle cx="46" cy="42" r="4" fill="#f8fafc"/>
</svg>

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 104 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" fill="none">
<rect width="100" height="100" rx="20" fill="#1b2a44"/>
<path d="M20 30h60v10H20zM20 45h40v10H20zM20 60h60v10H20z" fill="#67e8f9"/>
</svg>

After

Width:  |  Height:  |  Size: 218 B

+3
View File
@@ -0,0 +1,3 @@
(function () {
// Locale redirects intentionally disabled.
})();
+90
View File
@@ -0,0 +1,90 @@
(function () {
try {
const allowedDomainRoots = [
'gregframework.eu',
'gregframework',
'datacentermods.com',
'datacentermods',
'frikadellental.de',
];
const currentHost = globalThis.window.location.hostname.toLowerCase();
const currentOrigin = globalThis.window.location.origin;
const path = globalThis.window.location.pathname + globalThis.window.location.search;
const currentPathname = globalThis.window.location.pathname.toLowerCase();
const isDataCenterModsHost =
currentHost === 'datacentermods.com' ||
currentHost === 'www.datacentermods.com' ||
currentHost.endsWith('.datacentermods.com');
if (isDataCenterModsHost) {
document.documentElement.classList.add('host-datacentermods');
}
const isLegalRoute =
currentPathname.includes('/imprint') ||
currentPathname.includes('/impressum') ||
currentPathname.includes('/privacy') ||
currentPathname.includes('/privacy-policy') ||
currentPathname.includes('/datenschutz');
const isModsRoute = /\/mods(\/|$)/.test(currentPathname);
if (isLegalRoute) {
document.documentElement.classList.add('route-legal');
}
if (isModsRoute) {
document.documentElement.classList.add('route-mods');
}
function isAllowedHost(host, root) {
return host === root || host.endsWith('.' + root);
}
const hostAllowed = allowedDomainRoots.some(function (root) {
return isAllowedHost(currentHost, root);
});
let fallbackOrigin = 'https://frikadellental.de';
const canonicalNode = document.querySelector('link[rel="canonical"]');
if (canonicalNode) {
try {
fallbackOrigin = new URL(canonicalNode.getAttribute('href')).origin;
} catch (error) {
console.warn('[canonical-host] Failed to parse canonical URL, using fallback origin.', error);
}
}
const chosenOrigin = hostAllowed ? currentOrigin : fallbackOrigin;
const currentUrl = chosenOrigin + path;
if (canonicalNode) {
canonicalNode.setAttribute('href', currentUrl);
}
const ogUrl = document.querySelector('meta[property="og:url"]');
if (ogUrl) {
ogUrl.setAttribute('content', currentUrl);
}
const alternates = document.querySelectorAll('link[rel="alternate"]');
alternates.forEach(function (node) {
const href = node.getAttribute('href');
if (!href) {
return;
}
try {
const parsed = new URL(href);
const normalized = chosenOrigin + parsed.pathname + parsed.search;
node.setAttribute('href', normalized);
} catch (error) {
console.warn('[canonical-host] Ignoring malformed alternate URL.', error);
}
});
} catch (error) {
console.warn('[canonical-host] Host normalization failed.', error);
}
})();
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48"><path fill="#fff" d="M30.58 10.84c.66 0 1.2.54 1.2 1.2v1.2c0 .66-.54 1.2-1.2 1.2H17.42c-.66 0-1.2-.54-1.2-1.2v-1.2c0-.66.54-1.2 1.2-1.2h13.16Z"/><path fill="#fff" fill-rule="evenodd" d="M12.1 16.84c0-2.2 1.8-4 4-4H17.42v2.4H16.1c-.88 0-1.6.72-1.6 1.6v14.32c0 .88.72 1.6 1.6 1.6h15.8c.88 0 1.6-.72 1.6-1.6V16.84c0-.88-.72-1.6-1.6-1.6H30.58v-2.4H31.9c2.2 0 4 1.8 4 4v14.32c0 2.2-1.8 4-4 4H16.1c-2.2 0-4-1.8-4-4V16.84ZM20.42 21.04c0-.66.54-1.2 1.2-1.2h4.76c.66 0 1.2.54 1.2 1.2v4.76c0 .66-.54 1.2-1.2 1.2h-4.76c-.66 0-1.2-.54-1.2-1.2v-4.76Z" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 639 B

+326
View File
@@ -0,0 +1,326 @@
'use client';
import React, {useRef, useEffect, useCallback, useMemo} from 'react';
import {gsap} from 'gsap';
import {InertiaPlugin} from 'gsap/InertiaPlugin';
gsap.registerPlugin(InertiaPlugin);
function throttle<TArgs extends unknown[]>(func: (...args: TArgs) => void, limit: number) {
let lastCall = 0;
return (...args: TArgs) => {
const now = performance.now();
if (now - lastCall >= limit) {
lastCall = now;
func(...args);
}
};
}
interface Dot {
cx: number;
cy: number;
xOffset: number;
yOffset: number;
_inertiaApplied: boolean;
}
export interface DotGridProps {
dotSize?: number;
gap?: number;
baseColor?: string;
activeColor?: string;
proximity?: number;
speedTrigger?: number;
shockRadius?: number;
shockStrength?: number;
maxSpeed?: number;
resistance?: number;
returnDuration?: number;
className?: string;
style?: React.CSSProperties;
}
function hexToRgb(hex: string) {
const matcher = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
const match = matcher.exec(hex);
if (!match) {
return {r: 0, g: 0, b: 0};
}
return {
r: Number.parseInt(match[1], 16),
g: Number.parseInt(match[2], 16),
b: Number.parseInt(match[3], 16),
};
}
const DotGrid: React.FC<Readonly<DotGridProps>> = ({
dotSize = 16,
gap = 32,
baseColor = '#61f4d8',
activeColor = '#64d0ff',
proximity = 150,
speedTrigger = 100,
shockRadius = 250,
shockStrength = 5,
maxSpeed = 5000,
resistance = 750,
returnDuration = 1.5,
className = '',
style,
}) => {
const wrapperRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const dotsRef = useRef<Dot[]>([]);
const pointerRef = useRef({
x: 0,
y: 0,
vx: 0,
vy: 0,
speed: 0,
lastTime: 0,
lastX: 0,
lastY: 0,
});
const baseRgb = useMemo(() => hexToRgb(baseColor), [baseColor]);
const activeRgb = useMemo(() => hexToRgb(activeColor), [activeColor]);
const circlePath = useMemo(() => {
if (!globalThis.window?.Path2D) {
return null;
}
const path = new Path2D();
path.arc(0, 0, dotSize / 2, 0, Math.PI * 2);
return path;
}, [dotSize]);
const buildGrid = useCallback(() => {
const wrap = wrapperRef.current;
const canvas = canvasRef.current;
if (!wrap || !canvas) {
return;
}
const {width, height} = wrap.getBoundingClientRect();
const dpr = globalThis.window.devicePixelRatio || 1;
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.scale(dpr, dpr);
}
const cols = Math.floor((width + gap) / (dotSize + gap));
const rows = Math.floor((height + gap) / (dotSize + gap));
const cell = dotSize + gap;
const gridWidth = cell * cols - gap;
const gridHeight = cell * rows - gap;
const startX = (width - gridWidth) / 2 + dotSize / 2;
const startY = (height - gridHeight) / 2 + dotSize / 2;
const dots: Dot[] = [];
for (let y = 0; y < rows; y += 1) {
for (let x = 0; x < cols; x += 1) {
const cx = startX + x * cell;
const cy = startY + y * cell;
dots.push({cx, cy, xOffset: 0, yOffset: 0, _inertiaApplied: false});
}
}
dotsRef.current = dots;
}, [dotSize, gap]);
useEffect(() => {
if (!circlePath) {
return undefined;
}
let rafId = 0;
const proximitySquared = proximity * proximity;
const draw = () => {
const canvas = canvasRef.current;
if (!canvas) {
return;
}
const ctx = canvas.getContext('2d');
if (!ctx) {
return;
}
const displayWidth = Number.parseFloat(canvas.style.width || '0');
const displayHeight = Number.parseFloat(canvas.style.height || '0');
ctx.clearRect(0, 0, displayWidth, displayHeight);
const {x: px, y: py} = pointerRef.current;
for (const dot of dotsRef.current) {
const ox = dot.cx + dot.xOffset;
const oy = dot.cy + dot.yOffset;
const dx = dot.cx - px;
const dy = dot.cy - py;
const distanceSquared = dx * dx + dy * dy;
let fill = baseColor;
if (distanceSquared <= proximitySquared) {
const distance = Math.sqrt(distanceSquared);
const t = 1 - distance / proximity;
const r = Math.round(baseRgb.r + (activeRgb.r - baseRgb.r) * t);
const g = Math.round(baseRgb.g + (activeRgb.g - baseRgb.g) * t);
const b = Math.round(baseRgb.b + (activeRgb.b - baseRgb.b) * t);
fill = `rgb(${r},${g},${b})`;
}
ctx.save();
ctx.translate(ox, oy);
ctx.fillStyle = fill;
ctx.fill(circlePath);
ctx.restore();
}
rafId = globalThis.requestAnimationFrame(draw);
};
draw();
return () => globalThis.cancelAnimationFrame(rafId);
}, [proximity, baseColor, activeRgb, baseRgb, circlePath]);
useEffect(() => {
buildGrid();
let resizeObserver: ResizeObserver | null = null;
if ('ResizeObserver' in globalThis.window) {
resizeObserver = new ResizeObserver(buildGrid);
if (wrapperRef.current) {
resizeObserver.observe(wrapperRef.current);
}
} else {
globalThis.window.addEventListener('resize', buildGrid);
}
return () => {
if (resizeObserver) {
resizeObserver.disconnect();
} else {
globalThis.window.removeEventListener('resize', buildGrid);
}
};
}, [buildGrid]);
useEffect(() => {
const onMove = (event: MouseEvent) => {
const now = performance.now();
const pointer = pointerRef.current;
const dt = pointer.lastTime ? now - pointer.lastTime : 16;
const dx = event.clientX - pointer.lastX;
const dy = event.clientY - pointer.lastY;
let vx = (dx / dt) * 1000;
let vy = (dy / dt) * 1000;
let speed = Math.hypot(vx, vy);
if (speed > maxSpeed) {
const scale = maxSpeed / speed;
vx *= scale;
vy *= scale;
speed = maxSpeed;
}
pointer.lastTime = now;
pointer.lastX = event.clientX;
pointer.lastY = event.clientY;
pointer.vx = vx;
pointer.vy = vy;
pointer.speed = speed;
const canvas = canvasRef.current;
if (!canvas) {
return;
}
const rect = canvas.getBoundingClientRect();
pointer.x = event.clientX - rect.left;
pointer.y = event.clientY - rect.top;
for (const dot of dotsRef.current) {
const distance = Math.hypot(dot.cx - pointer.x, dot.cy - pointer.y);
if (speed > speedTrigger && distance < proximity && !dot._inertiaApplied) {
dot._inertiaApplied = true;
gsap.killTweensOf(dot);
const pushX = dot.cx - pointer.x + vx * 0.005;
const pushY = dot.cy - pointer.y + vy * 0.005;
gsap.to(dot, {
inertia: {xOffset: pushX, yOffset: pushY, resistance},
onComplete: () => {
gsap.to(dot, {
xOffset: 0,
yOffset: 0,
duration: returnDuration,
ease: 'elastic.out(1,0.75)',
});
dot._inertiaApplied = false;
},
});
}
}
};
const onClick = (event: MouseEvent) => {
const canvas = canvasRef.current;
if (!canvas) {
return;
}
const rect = canvas.getBoundingClientRect();
const cx = event.clientX - rect.left;
const cy = event.clientY - rect.top;
for (const dot of dotsRef.current) {
const distance = Math.hypot(dot.cx - cx, dot.cy - cy);
if (distance < shockRadius && !dot._inertiaApplied) {
dot._inertiaApplied = true;
gsap.killTweensOf(dot);
const falloff = Math.max(0, 1 - distance / shockRadius);
const pushX = (dot.cx - cx) * shockStrength * falloff;
const pushY = (dot.cy - cy) * shockStrength * falloff;
gsap.to(dot, {
inertia: {xOffset: pushX, yOffset: pushY, resistance},
onComplete: () => {
gsap.to(dot, {
xOffset: 0,
yOffset: 0,
duration: returnDuration,
ease: 'elastic.out(1,0.75)',
});
dot._inertiaApplied = false;
},
});
}
}
};
const throttledMove = throttle(onMove, 50);
globalThis.window.addEventListener('mousemove', throttledMove, {passive: true});
globalThis.window.addEventListener('click', onClick);
return () => {
globalThis.window.removeEventListener('mousemove', throttledMove);
globalThis.window.removeEventListener('click', onClick);
};
}, [maxSpeed, speedTrigger, proximity, resistance, returnDuration, shockRadius, shockStrength]);
return (
<section className={`relative flex h-full w-full items-center justify-center ${className}`} style={style}>
<div ref={wrapperRef} className="relative h-full w-full">
<canvas ref={canvasRef} className="pointer-events-none absolute inset-0 h-full w-full" />
</div>
</section>
);
};
export default DotGrid;
+396
View File
@@ -0,0 +1,396 @@
import React, {useEffect, useRef} from 'react';
import {Renderer, Program, Mesh, Triangle} from 'ogl';
export interface GradientBlindsProps {
className?: string;
dpr?: number;
paused?: boolean;
gradientColors?: string[];
angle?: number;
noise?: number;
blindCount?: number;
blindMinWidth?: number;
mouseDampening?: number;
mirrorGradient?: boolean;
spotlightRadius?: number;
spotlightSoftness?: number;
spotlightOpacity?: number;
distortAmount?: number;
shineDirection?: 'left' | 'right';
mixBlendMode?: string;
}
const MAX_COLORS = 8;
const hexToRGB = (hex: string): [number, number, number] => {
const c = hex.replace('#', '').padEnd(6, '0');
const r = parseInt(c.slice(0, 2), 16) / 255;
const g = parseInt(c.slice(2, 4), 16) / 255;
const b = parseInt(c.slice(4, 6), 16) / 255;
return [r, g, b];
};
const prepStops = (stops?: string[]) => {
const base = (stops && stops.length ? stops : ['#61f4d8', '#08c1a6']).slice(0, MAX_COLORS);
if (base.length === 1) {
base.push(base[0]);
}
while (base.length < MAX_COLORS) {
base.push(base[base.length - 1]);
}
const arr: [number, number, number][] = [];
for (let index = 0; index < MAX_COLORS; index += 1) {
arr.push(hexToRGB(base[index]));
}
const count = Math.max(2, Math.min(MAX_COLORS, stops?.length ?? 2));
return {arr, count};
};
export default function GradientBlinds({
className,
dpr,
paused = false,
gradientColors,
angle = 0,
noise = 0.25,
blindCount = 16,
blindMinWidth = 60,
mouseDampening = 0.15,
mirrorGradient = false,
spotlightRadius = 0.5,
spotlightSoftness = 1,
spotlightOpacity = 1,
distortAmount = 0,
shineDirection = 'left',
mixBlendMode = 'lighten',
}: GradientBlindsProps): JSX.Element {
const containerRef = useRef<HTMLDivElement | null>(null);
const rafRef = useRef<number | null>(null);
const programRef = useRef<Program | null>(null);
const meshRef = useRef<Mesh<Triangle> | null>(null);
const geometryRef = useRef<Triangle | null>(null);
const rendererRef = useRef<Renderer | null>(null);
const mouseTargetRef = useRef<[number, number]>([0, 0]);
const lastTimeRef = useRef<number>(0);
const firstResizeRef = useRef<boolean>(true);
useEffect(() => {
const container = containerRef.current;
if (!container || typeof window === 'undefined') {
return undefined;
}
const renderer = new Renderer({
dpr: dpr ?? (window.devicePixelRatio || 1),
alpha: true,
antialias: true,
});
rendererRef.current = renderer;
const gl = renderer.gl;
const canvas = gl.canvas as HTMLCanvasElement;
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.style.display = 'block';
container.appendChild(canvas);
const vertex = `
attribute vec2 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(position, 0.0, 1.0);
}
`;
const fragment = `
#ifdef GL_ES
precision mediump float;
#endif
uniform vec3 iResolution;
uniform vec2 iMouse;
uniform float iTime;
uniform float uAngle;
uniform float uNoise;
uniform float uBlindCount;
uniform float uSpotlightRadius;
uniform float uSpotlightSoftness;
uniform float uSpotlightOpacity;
uniform float uMirror;
uniform float uDistort;
uniform float uShineFlip;
uniform vec3 uColor0;
uniform vec3 uColor1;
uniform vec3 uColor2;
uniform vec3 uColor3;
uniform vec3 uColor4;
uniform vec3 uColor5;
uniform vec3 uColor6;
uniform vec3 uColor7;
uniform int uColorCount;
varying vec2 vUv;
float rand(vec2 co){
return fract(sin(dot(co, vec2(12.9898,78.233))) * 43758.5453);
}
vec2 rotate2D(vec2 p, float a){
float c = cos(a);
float s = sin(a);
return mat2(c, -s, s, c) * p;
}
vec3 getGradientColor(float t){
float tt = clamp(t, 0.0, 1.0);
int count = uColorCount;
if (count < 2) count = 2;
float scaled = tt * float(count - 1);
float seg = floor(scaled);
float f = fract(scaled);
if (seg < 1.0) return mix(uColor0, uColor1, f);
if (seg < 2.0 && count > 2) return mix(uColor1, uColor2, f);
if (seg < 3.0 && count > 3) return mix(uColor2, uColor3, f);
if (seg < 4.0 && count > 4) return mix(uColor3, uColor4, f);
if (seg < 5.0 && count > 5) return mix(uColor4, uColor5, f);
if (seg < 6.0 && count > 6) return mix(uColor5, uColor6, f);
if (seg < 7.0 && count > 7) return mix(uColor6, uColor7, f);
if (count > 7) return uColor7;
if (count > 6) return uColor6;
if (count > 5) return uColor5;
if (count > 4) return uColor4;
if (count > 3) return uColor3;
if (count > 2) return uColor2;
return uColor1;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv0 = fragCoord.xy / iResolution.xy;
float aspect = iResolution.x / iResolution.y;
vec2 p = uv0 * 2.0 - 1.0;
p.x *= aspect;
vec2 pr = rotate2D(p, uAngle);
pr.x /= aspect;
vec2 uv = pr * 0.5 + 0.5;
vec2 uvMod = uv;
if (uDistort > 0.0) {
float a = uvMod.y * 6.0;
float b = uvMod.x * 6.0;
float w = 0.01 * uDistort;
uvMod.x += sin(a) * w;
uvMod.y += cos(b) * w;
}
float t = uvMod.x;
if (uMirror > 0.5) {
t = 1.0 - abs(1.0 - 2.0 * fract(t));
}
vec3 base = getGradientColor(t);
vec2 offset = vec2(iMouse.x / iResolution.x, iMouse.y / iResolution.y);
float d = length(uv0 - offset);
float r = max(uSpotlightRadius, 1e-4);
float dn = d / r;
float spot = (1.0 - 2.0 * pow(dn, uSpotlightSoftness)) * uSpotlightOpacity;
vec3 cir = vec3(spot);
float stripe = fract(uvMod.x * max(uBlindCount, 1.0));
if (uShineFlip > 0.5) {
stripe = 1.0 - stripe;
}
vec3 ran = vec3(stripe);
vec3 col = cir + base - ran;
col += (rand(gl_FragCoord.xy + iTime) - 0.5) * uNoise;
fragColor = vec4(col, 1.0);
}
void main() {
vec4 color;
mainImage(color, vUv * iResolution.xy);
gl_FragColor = color;
}
`;
const {arr: colorArr, count: colorCount} = prepStops(gradientColors);
const uniforms = {
iResolution: {value: [gl.drawingBufferWidth, gl.drawingBufferHeight, 1] as [number, number, number]},
iMouse: {value: [0, 0] as [number, number]},
iTime: {value: 0},
uAngle: {value: (angle * Math.PI) / 180},
uNoise: {value: noise},
uBlindCount: {value: Math.max(1, blindCount)},
uSpotlightRadius: {value: spotlightRadius},
uSpotlightSoftness: {value: spotlightSoftness},
uSpotlightOpacity: {value: spotlightOpacity},
uMirror: {value: mirrorGradient ? 1 : 0},
uDistort: {value: distortAmount},
uShineFlip: {value: shineDirection === 'right' ? 1 : 0},
uColor0: {value: colorArr[0]},
uColor1: {value: colorArr[1]},
uColor2: {value: colorArr[2]},
uColor3: {value: colorArr[3]},
uColor4: {value: colorArr[4]},
uColor5: {value: colorArr[5]},
uColor6: {value: colorArr[6]},
uColor7: {value: colorArr[7]},
uColorCount: {value: colorCount},
};
const program = new Program(gl, {vertex, fragment, uniforms});
programRef.current = program;
const geometry = new Triangle(gl);
geometryRef.current = geometry;
const mesh = new Mesh(gl, {geometry, program});
meshRef.current = mesh;
const resize = () => {
const rect = container.getBoundingClientRect();
renderer.setSize(rect.width, rect.height);
uniforms.iResolution.value = [gl.drawingBufferWidth, gl.drawingBufferHeight, 1];
if (blindMinWidth > 0) {
const maxByMinWidth = Math.max(1, Math.floor(rect.width / blindMinWidth));
const effective = blindCount ? Math.min(blindCount, maxByMinWidth) : maxByMinWidth;
uniforms.uBlindCount.value = Math.max(1, effective);
} else {
uniforms.uBlindCount.value = Math.max(1, blindCount);
}
if (firstResizeRef.current) {
firstResizeRef.current = false;
const cx = gl.drawingBufferWidth / 2;
const cy = gl.drawingBufferHeight / 2;
uniforms.iMouse.value = [cx, cy];
mouseTargetRef.current = [cx, cy];
}
};
resize();
const observer = new ResizeObserver(resize);
observer.observe(container);
const onPointerMove = (event: PointerEvent) => {
const rect = canvas.getBoundingClientRect();
const canvasDpr = renderer.dpr || 1;
const x = (event.clientX - rect.left) * canvasDpr;
const y = (rect.height - (event.clientY - rect.top)) * canvasDpr;
mouseTargetRef.current = [x, y];
if (mouseDampening <= 0) {
uniforms.iMouse.value = [x, y];
}
};
canvas.addEventListener('pointermove', onPointerMove);
const loop = (timeMs: number) => {
rafRef.current = requestAnimationFrame(loop);
uniforms.iTime.value = timeMs * 0.001;
if (mouseDampening > 0) {
if (!lastTimeRef.current) {
lastTimeRef.current = timeMs;
}
const dt = (timeMs - lastTimeRef.current) / 1000;
lastTimeRef.current = timeMs;
const tau = Math.max(1e-4, mouseDampening);
let factor = 1 - Math.exp(-dt / tau);
if (factor > 1) {
factor = 1;
}
const target = mouseTargetRef.current;
const current = uniforms.iMouse.value;
current[0] += (target[0] - current[0]) * factor;
current[1] += (target[1] - current[1]) * factor;
} else {
lastTimeRef.current = timeMs;
}
if (!paused && programRef.current && meshRef.current) {
try {
renderer.render({scene: meshRef.current});
} catch {
return;
}
}
};
rafRef.current = requestAnimationFrame(loop);
return () => {
if (rafRef.current) {
cancelAnimationFrame(rafRef.current);
}
canvas.removeEventListener('pointermove', onPointerMove);
observer.disconnect();
if (canvas.parentElement === container) {
container.removeChild(canvas);
}
const callIfFn = <T extends object, K extends keyof T>(obj: T | null, key: K) => {
if (obj && typeof obj[key] === 'function') {
(obj[key] as unknown as () => void).call(obj);
}
};
callIfFn(programRef.current, 'remove');
callIfFn(geometryRef.current, 'remove');
callIfFn(meshRef.current as unknown as {remove?: () => void}, 'remove');
callIfFn(rendererRef.current as unknown as {destroy?: () => void}, 'destroy');
programRef.current = null;
geometryRef.current = null;
meshRef.current = null;
rendererRef.current = null;
};
}, [
dpr,
paused,
gradientColors,
angle,
noise,
blindCount,
blindMinWidth,
mouseDampening,
mirrorGradient,
spotlightRadius,
spotlightSoftness,
spotlightOpacity,
distortAmount,
shineDirection,
]);
return (
<div
ref={containerRef}
className={`h-full w-full overflow-hidden ${className ?? ''}`}
style={{
...(mixBlendMode && {
mixBlendMode: mixBlendMode as React.CSSProperties['mixBlendMode'],
}),
}}
/>
);
}
+42
View File
@@ -0,0 +1,42 @@
import React, {useMemo} from 'react';
import {GREG_CORE_SNIPPETS} from '../data/gregCoreSnippets';
type Props = {
caption: string;
loadingLabel: string;
};
/**
* Picks one snippet per client mount.
*/
export function GregCoreRandomSnippet({caption}: Props): JSX.Element {
const snippet = useMemo(
() => GREG_CORE_SNIPPETS[Math.floor(Math.random() * GREG_CORE_SNIPPETS.length)],
[],
);
return (
<div className="rounded-xl border border-slate-800 bg-slate-900 p-1 shadow-2xl">
<div className="rounded-lg bg-slate-950 p-6 font-mono text-sm text-white">
<div className="mb-3 flex flex-wrap items-center justify-between gap-2 border-b border-slate-800 pb-3">
<div>
<div className="text-xs font-bold uppercase tracking-wider text-teal-400">{caption}</div>
<div className="mt-1 text-xs text-slate-400">
<span className="font-semibold text-slate-200">{snippet.title}</span>
<span className="mx-1.5 text-slate-700">·</span>
<code className="text-[11px] text-cyan-400">{snippet.sourcePath}</code>
</div>
</div>
<div className="flex gap-2" aria-hidden>
<div className="h-3 w-3 rounded-full bg-red-500/50" />
<div className="h-3 w-3 rounded-full bg-yellow-500/50" />
<div className="h-3 w-3 rounded-full bg-green-500/50" />
</div>
</div>
<pre className="max-h-[min(420px,55vh)] overflow-auto whitespace-pre pr-1 leading-relaxed text-slate-300">
{snippet.code.trimEnd()}
</pre>
</div>
</div>
);
}
+205
View File
@@ -0,0 +1,205 @@
import React, {useEffect, useMemo, useState} from 'react';
type GithubRepo = {
name: string;
html_url: string;
};
type GithubRelease = {
id: number;
name: string | null;
tag_name: string;
html_url: string;
published_at: string;
draft: boolean;
prerelease: boolean;
body: string | null;
};
type RepoRelease = {
repoName: string;
repoUrl: string;
releaseName: string;
tagName: string;
releaseUrl: string;
publishedAt: string;
prerelease: boolean;
bodyPreview: string;
};
type Props = {
owner: string;
repoPrefix?: string;
};
function toBodyPreview(body: string | null, maxLength = 140): string {
if (!body) {
return 'No release notes provided.';
}
const normalized = body.replace(/\r\n/g, '\n').replace(/[#>*`\-_]/g, '').trim();
if (normalized.length <= maxLength) {
return normalized;
}
return `${normalized.slice(0, maxLength).trimEnd()}`;
}
function formatUtcDate(dateIso: string): string {
return new Date(dateIso).toLocaleDateString(undefined, {
year: 'numeric',
month: 'short',
day: 'numeric',
timeZone: 'UTC',
});
}
export default function GregGithubReleases({owner, repoPrefix = 'greg'}: Props): JSX.Element {
const [releases, setReleases] = useState<RepoRelease[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
useEffect(() => {
let isCancelled = false;
async function fetchGregReleases(): Promise<void> {
setIsLoading(true);
setErrorMessage(null);
try {
const reposResponse = await fetch(
`https://api.github.com/users/${encodeURIComponent(owner)}/repos?type=owner&per_page=100&sort=updated`,
{
headers: {
Accept: 'application/vnd.github+json',
},
},
);
if (!reposResponse.ok) {
throw new Error(`GitHub repos request failed (${reposResponse.status}).`);
}
const repos = (await reposResponse.json()) as GithubRepo[];
const matchingRepos = repos.filter((repo) =>
repo.name.toLowerCase().startsWith(repoPrefix.toLowerCase()),
);
const releaseBatches = await Promise.all(
matchingRepos.map(async (repo) => {
const releasesResponse = await fetch(
`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo.name)}/releases?per_page=100`,
{
headers: {
Accept: 'application/vnd.github+json',
},
},
);
if (!releasesResponse.ok) {
return [] as RepoRelease[];
}
const repoReleases = (await releasesResponse.json()) as GithubRelease[];
return repoReleases
.filter((release) => !release.draft)
.map((release) => ({
repoName: repo.name,
repoUrl: repo.html_url,
releaseName: release.name?.trim() || release.tag_name,
tagName: release.tag_name,
releaseUrl: release.html_url,
publishedAt: release.published_at,
prerelease: release.prerelease,
bodyPreview: toBodyPreview(release.body),
}));
}),
);
const flattened = releaseBatches
.flat()
.sort(
(left, right) =>
new Date(right.publishedAt).getTime() - new Date(left.publishedAt).getTime(),
);
if (!isCancelled) {
setReleases(flattened);
}
} catch (error) {
if (!isCancelled) {
setErrorMessage(error instanceof Error ? error.message : 'Failed to load releases.');
}
} finally {
if (!isCancelled) {
setIsLoading(false);
}
}
}
void fetchGregReleases();
return () => {
isCancelled = true;
};
}, [owner, repoPrefix]);
const heading = useMemo(
() => `Latest GitHub releases (${owner}/${repoPrefix}*)`,
[owner, repoPrefix],
);
if (isLoading) {
return (
<div className="mod-release-card rounded-xl border border-outline-variant/15 p-5">
<p className="text-sm text-on-surface-variant">Loading releases from GitHub</p>
</div>
);
}
if (errorMessage) {
return (
<div className="mod-release-card rounded-xl border border-outline-variant/15 p-5">
<p className="mb-2 font-semibold text-on-surface">Could not load GitHub releases.</p>
<p className="text-sm text-on-surface-variant">{errorMessage}</p>
</div>
);
}
if (releases.length === 0) {
return (
<div className="mod-release-card rounded-xl border border-outline-variant/15 p-5">
<p className="mb-2 font-semibold text-on-surface">No releases found.</p>
<p className="text-sm text-on-surface-variant">
Repositories matching <code>{repoPrefix}*</code> currently have no published releases.
</p>
</div>
);
}
return (
<div className="space-y-4">
<p className="text-sm font-semibold uppercase tracking-wider text-primary">{heading}</p>
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
{releases.map((release) => (
<article key={`${release.repoName}-${release.releaseUrl}`} className="mod-release-card rounded-xl p-5">
<div className="mb-2 flex flex-wrap items-center gap-2">
<a href={release.repoUrl} className="mod-release-badge" target="_blank" rel="noopener noreferrer">
{release.repoName}
</a>
{release.prerelease ? <span className="mod-release-badge">Prerelease</span> : null}
</div>
<h3 className="mb-1 text-base font-bold text-on-surface">{release.releaseName}</h3>
<p className="mb-3 text-xs text-on-surface-variant">
{release.tagName} · Published {formatUtcDate(release.publishedAt)}
</p>
<p className="mb-4 text-sm text-on-surface-variant">{release.bodyPreview}</p>
<a href={release.releaseUrl} className="mod-release-btn-primary inline-block" target="_blank" rel="noopener noreferrer">
Open release
</a>
</article>
))}
</div>
</div>
);
}
+238
View File
@@ -0,0 +1,238 @@
import React from 'react';
type ReleaseKind = 'mod' | 'plugin';
type ModReleasePageProps = {
title: string;
kind: ReleaseKind;
dllName: string;
description: string;
version?: string;
author?: string;
category?: string;
dependencies?: string[];
codeLanguages?: string[];
releaseReady?: boolean;
banner?: string;
releaseNotesPath?: string;
installation?: React.ReactNode;
};
function toTitleCase(value: ReleaseKind): string {
return value.charAt(0).toUpperCase() + value.slice(1);
}
function normalizeReleaseNotesPath(releaseNotesPath?: string): string | undefined {
if (!releaseNotesPath) return undefined;
if (releaseNotesPath.startsWith('/wiki/')) {
return releaseNotesPath;
}
if (
releaseNotesPath.startsWith('/mods/') ||
releaseNotesPath.startsWith('/plugins/') ||
releaseNotesPath.startsWith('/tools/')
) {
return `/wiki${releaseNotesPath}`;
}
return releaseNotesPath;
}
export default function ModReleasePage({
title,
kind,
dllName,
description,
version = 'NotReleasedYet',
author = 'gregFramework Community',
category = 'Mod',
dependencies = [],
codeLanguages = ['C#'],
releaseReady = false,
banner,
releaseNotesPath,
installation,
}: ModReleasePageProps): JSX.Element {
const downloadPath = `/${kind}/${dllName}`;
const downloadUrl =
typeof window !== 'undefined'
? new URL(downloadPath, window.location.origin).toString()
: downloadPath;
const docPath = normalizeReleaseNotesPath(releaseNotesPath);
return (
<div className="mod-release-root bg-background text-on-surface min-h-screen">
<div className="mx-auto max-w-7xl px-4 py-10 md:px-8 md:py-12">
<header className="mb-12">
<div className="mb-4 flex flex-wrap items-center gap-3">
<span className="rounded-full border border-primary/30 bg-primary-container/20 px-3 py-1 text-[10px] font-bold uppercase tracking-widest text-primary">
{releaseReady ? 'Stable release' : 'Preview / in development'}
</span>
<span className="font-mono text-xs text-on-surface-variant">{dllName}</span>
</div>
<h1 className="mb-4 font-headline text-4xl font-bold leading-tight tracking-tighter text-on-surface md:text-6xl">
{title}
</h1>
<p className="max-w-3xl text-xl leading-relaxed text-on-surface-variant">
{banner ?? 'Official release download and module details'}
</p>
</header>
<div className="grid grid-cols-1 gap-12 lg:grid-cols-12">
<article className="space-y-12 lg:col-span-8">
<section>
<h2 className="mb-6 flex items-center gap-2 font-headline text-2xl font-bold text-secondary">
<span className="material-symbols-outlined text-primary">description</span>
Description
</h2>
<div className="prose prose-invert max-w-none space-y-4 text-on-surface-variant">
<p>{description}</p>
</div>
</section>
<section className="rounded-xl bg-surface-container-low p-8 outline-[1px] outline-outline-variant/10">
<h2 className="mb-6 flex items-center gap-2 font-headline text-2xl font-bold text-secondary">
<span className="material-symbols-outlined text-primary">terminal</span>
Installation
</h2>
{installation ?? (
<ol className="space-y-6">
<li className="flex gap-4">
<span className="flex h-8 w-8 flex-none items-center justify-center rounded-full border border-primary/20 bg-primary/10 font-headline text-sm font-bold text-primary">
01
</span>
<div>
<h4 className="font-bold text-on-surface">
Download the release DLL.
</h4>
<p className="text-sm text-on-surface-variant">
Use the GitHub release asset or the route below.
</p>
</div>
</li>
<li className="flex gap-4">
<span className="flex h-8 w-8 flex-none items-center justify-center rounded-full border border-primary/20 bg-primary/10 font-headline text-sm font-bold text-primary">
02
</span>
<div>
<h4 className="font-bold text-on-surface">
Copy into the game folder
</h4>
<p className="text-sm text-on-surface-variant">
Copy it to your Data Center `Mods/` folder.
</p>
</div>
</li>
<li className="flex gap-4">
<span className="flex h-8 w-8 flex-none items-center justify-center rounded-full border border-primary/20 bg-primary/10 font-headline text-sm font-bold text-primary">
03
</span>
<div>
<h4 className="font-bold text-on-surface">
Launch
</h4>
<p className="text-sm text-on-surface-variant">
Start the game with MelonLoader.
</p>
</div>
</li>
</ol>
)}
</section>
<section>
<h2 className="mb-6 flex items-center gap-2 font-headline text-2xl font-bold text-secondary">
<span className="material-symbols-outlined text-primary">code</span>
Direct DLL route
</h2>
<div className="group relative">
<div className="absolute -inset-0.5 rounded-xl bg-linear-to-r from-primary/20 to-tertiary/20 opacity-30 blur transition group-hover:opacity-50" />
<div className="relative overflow-x-auto rounded-xl bg-surface-container-highest p-6 font-mono text-sm text-on-surface">
<code>{downloadPath}</code>
</div>
</div>
</section>
</article>
<aside className="space-y-6 lg:col-span-4" aria-label="Download sidebar">
<div className="space-y-3">
{releaseReady ? (
<a
className="flex w-full items-center justify-center gap-2 rounded-xl bg-linear-to-br from-primary to-primary-container py-4 font-headline font-bold text-on-primary shadow-[0_0_32px_-4px_rgba(0,191,165,0.35)] transition hover:scale-[1.02] active:scale-[0.98]"
href={downloadUrl}
>
<span className="material-symbols-outlined">download</span>
Download DLL
</a>
) : (
<button
className="flex w-full cursor-not-allowed items-center justify-center gap-2 rounded-xl bg-surface-container py-4 font-headline font-bold text-on-surface-variant opacity-80 outline-[1px] outline-outline-variant/25"
disabled
type="button"
>
<span className="material-symbols-outlined">lock</span>
Not released yet
</button>
)}
{docPath ? (
<a
className="flex w-full items-center justify-center gap-2 rounded-xl border border-outline-variant/40 bg-surface-container py-4 font-headline font-bold text-on-surface transition hover:border-outline-variant hover:bg-surface-container-high"
href={docPath}
>
<span className="material-symbols-outlined">open_in_new</span>
Open module docs
</a>
) : null}
</div>
<div className="rounded-xl bg-surface-container p-6 outline-[1px] outline-outline-variant/20">
<h3 className="mb-6 font-headline text-sm font-bold uppercase tracking-widest text-primary">
Reference metadata
</h3>
<dl className="space-y-4 text-sm">
<div className="flex items-center justify-between border-b border-outline-variant/10 py-2">
<dt className="text-xs font-medium text-on-surface-variant">
Version
</dt>
<dd className="rounded bg-surface-variant px-2 py-0.5 font-mono text-xs text-primary">
{version}
</dd>
</div>
<div className="flex items-center justify-between border-b border-outline-variant/10 py-2">
<dt className="text-xs font-medium text-on-surface-variant">
Author
</dt>
<dd className="text-on-surface">{author}</dd>
</div>
<div className="flex items-center justify-between border-b border-outline-variant/10 py-2">
<dt className="text-xs font-medium text-on-surface-variant">
Category
</dt>
<dd className="text-on-surface">
{category} · {toTitleCase(kind)}
</dd>
</div>
<div className="flex items-center justify-between border-b border-outline-variant/10 py-2">
<dt className="text-xs font-medium text-on-surface-variant">
Dependencies
</dt>
<dd className="text-right text-on-surface">
{dependencies.length ? dependencies.join(', ') : '—'}
</dd>
</div>
<div className="flex items-center justify-between py-2">
<dt className="text-xs font-medium text-on-surface-variant">
Languages
</dt>
<dd className="text-on-surface">{codeLanguages.join(', ')}</dd>
</div>
</dl>
<p className="mt-6 text-xs leading-relaxed text-on-surface-variant">
The download route redirects to the latest GitHub release asset when published.
</p>
</div>
</aside>
</div>
</div>
</div>
);
}
+128
View File
@@ -0,0 +1,128 @@
import React, {useEffect, useRef} from 'react';
type ShapeGridProps = {
className?: string;
cellSize?: number;
strokeWidth?: number;
drift?: number;
};
function cssVar(name: string, fallback: string): string {
if (globalThis.window === undefined) {
return fallback;
}
const value = globalThis
.getComputedStyle(document.documentElement)
.getPropertyValue(name)
.trim();
return value.length > 0 ? value : fallback;
}
export default function ShapeGrid({
className,
cellSize = 64,
strokeWidth = 1,
drift = 0.16,
}: Readonly<ShapeGridProps>): JSX.Element {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) {
return undefined;
}
const ctx = canvas.getContext('2d');
if (!ctx) {
return undefined;
}
const lineColor = cssVar('--color-outline-variant', '#0f514c');
const accentA = cssVar('--color-primary', '#61f4d8');
const accentB = cssVar('--color-secondary', '#1cede1');
const accentC = cssVar('--color-tertiary', '#64d0ff');
let rafId = 0;
let width = 0;
let height = 0;
let cols = 0;
let rows = 0;
const dpr = Math.max(1, globalThis.window.devicePixelRatio || 1);
const resize = () => {
const rect = canvas.getBoundingClientRect();
width = Math.max(1, Math.floor(rect.width));
height = Math.max(1, Math.floor(rect.height));
cols = Math.ceil(width / cellSize) + 1;
rows = Math.ceil(height / cellSize) + 1;
canvas.width = Math.floor(width * dpr);
canvas.height = Math.floor(height * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
ctx.lineWidth = strokeWidth;
};
resize();
const resizeObserver = new ResizeObserver(() => resize());
resizeObserver.observe(canvas);
const draw = (timestamp: number) => {
const time = timestamp * 0.001;
ctx.clearRect(0, 0, width, height);
const driftX = Math.sin(time * 0.25) * cellSize * drift;
const driftY = Math.cos(time * 0.2) * cellSize * drift;
ctx.strokeStyle = lineColor;
ctx.globalAlpha = 0.22;
for (let x = 0; x < cols; x += 1) {
const xPos = x * cellSize + driftX;
ctx.beginPath();
ctx.moveTo(xPos, 0);
ctx.lineTo(xPos, height);
ctx.stroke();
}
for (let y = 0; y < rows; y += 1) {
const yPos = y * cellSize + driftY;
ctx.beginPath();
ctx.moveTo(0, yPos);
ctx.lineTo(width, yPos);
ctx.stroke();
}
for (let y = 0; y < rows; y += 1) {
for (let x = 0; x < cols; x += 1) {
const xPos = x * cellSize + driftX;
const yPos = y * cellSize + driftY;
const pulse = (Math.sin(time * 1.8 + x * 0.7 + y * 0.5) + 1) * 0.5;
const patternIndex = (x + y) % 3;
let accentColor = accentC;
if (patternIndex === 0) {
accentColor = accentA;
} else if (patternIndex === 1) {
accentColor = accentB;
}
ctx.fillStyle = accentColor;
ctx.globalAlpha = 0.08 + pulse * 0.22;
ctx.fillRect(xPos - 1.2, yPos - 1.2, 2.4, 2.4);
}
}
ctx.globalAlpha = 1;
rafId = globalThis.requestAnimationFrame(draw);
};
rafId = globalThis.requestAnimationFrame(draw);
return () => {
globalThis.cancelAnimationFrame(rafId);
resizeObserver.disconnect();
};
}, [cellSize, drift, strokeWidth]);
return <canvas ref={canvasRef} className={className} />;
}
+10
View File
@@ -0,0 +1,10 @@
import { defineCollection } from 'astro:content';
import { docsSchema } from '@astrojs/starlight/schema';
import { glob } from 'astro/loaders';
export const collections = {
docs: defineCollection({
loader: glob({ pattern: '**/[^_]*.md', base: 'src/content/docs' }),
schema: docsSchema(),
}),
};
@@ -0,0 +1,15 @@
---
title: System Architecture
description: Overview of the gregFramework layers and Data Center integration.
---
The **gregFramework** is designed as a multi-layer middleware that sits between the native Unity game engine and the high-level modding API.
## Core Layers
1. **Native Bridge:** Low-level patches and event hooks.
2. **Framework Core:** The central registry and service orchestrator.
3. **SDK Surface:** The public API consumed by mod authors.
## Visual Overview
(Diagram coming soon)
@@ -0,0 +1,33 @@
---
id: intro
title: Mod author wiki
description: Technical documentation for Data Center mod and plugin authors gregFramework, hooks, workspace, and releases.
---
# Mod author wiki
:::danger ENGINE UPGRADE
Data Center has been upgraded to **Unity 6**. All mods must be updated to target **.NET 6** and use the modernized assembly references. See the [Engine Upgrade Guide](/docs/02_development/engine-upgrades) for details.
:::
This site (**`/wiki`**) is for people who **write or maintain mods and plugins**, work on **gregFramework**, or contribute to **repos and documentation**.
:::important Compatibility Scope
This wiki targets **Data Center by Waseku only**. Content here is not a generic Unity modding guide and is not maintained for other games.
:::
**Players** install MelonLoader, browse mods, and get help on the **[For players](/players)** page (`/players`), the **[mod catalog](/mods)**, and Discord.
## Getting started
1. **[Getting started](/wiki/01_getting-started/quickstart)** split-repo layout, build gregCore, hooks and registries
2. **[Documentation layout](/wiki/01_getting-started/quickstart)** how `docs/` is organised
3. **[Workspace map](/wiki/01_getting-started/architecture)** folders on disk
Then read **[System architecture & documentation principles](/wiki/01_getting-started/architecture)** canonical **Mod Manager ? Framework ? Plugins ? Mods** model.
## Full index
**[Documentation hub ?](/wiki/developers)** complete table of contents: framework, plugins, mods, guides, releases, reference, roadmap.
The sidebar matches this wiki: **Getting started** is at the top, then the rest of the author tree.
@@ -0,0 +1,64 @@
---
title: Quickstart - Build Your First Mod
description: Set up your environment and build a simple mod in less than 5 minutes.
---
Welcome to the **gregFramework** ecosystem! This guide will help you set up your environment and build a simple "Hello World" mod in less than 5 minutes.
## 1. Prerequisites
- **Visual Studio 2022** or **VS Code** with .NET 6 SDK.
- **MelonLoader v0.7.2+** installed in your Data Center game folder.
- **gregCore.dll** placed in the `Mods/` folder of your game.
## 2. Using the Templates
The easiest way to start is using the `gregModmanager` template system:
1. Open `gregModmanager`.
2. Go to the **New Project** tab.
3. Select the **gregCore Framework** template.
4. Enter a name (e.g., `MyFirstMod`) and click **Create**.
## 3. Basic Code Structure
Open your new project. Your main class should look like this:
```csharp
using MelonLoader;
using UnityEngine;
using greg.Core;
using greg.Sdk.Services;
[assembly: MelonInfo(typeof(MyFirstMod.Main), "MyFirstMod", "1.0.0", "YourName")]
[assembly: MelonGame("Waseku", "Data Center")]
namespace MyFirstMod;
public class Main : MelonMod
{
public override void OnInitializeMelon()
{
MelonLogger.Msg("Hello gregFramework!");
// Register your mod for discovery
GregModRegistry.Register("MyFirstMod", "1.0.0");
}
public override void OnUpdate()
{
if (UnityEngine.InputSystem.Keyboard.current.f5Key.wasPressedThisFrame)
{
GregNotificationService.Show("Mod is working!", "SUCCESS");
}
}
}
```
## 4. Build & Run
1. Press `F6` or run `dotnet build`.
2. Copy the resulting `.dll` from `bin/Debug/net6.0/` to your game's `Mods/` folder.
3. Start the game!
## 5. Next Steps
- Explore the [SDK Services](/docs/02_development/api-reference/game-system-bridges) to interact with game logic.
- Learn about [Custom UI](/02_development/ui/custom-ugui-csharp).
- Join our [Discord](https://discord.gg/greg) for support.
*Follow best practices: Always use SDK services instead of direct patches when possible.*
@@ -0,0 +1,115 @@
---
title: Game System Bridges (IL2CPP)
sidebar_label: Game System Bridges
description: typsichere C# Bridges für interne IL2CPP Spielsysteme (GameManager, Shop, Technicians etc.).
---
# Game System Bridges (IL2CPP)
Seit `v1.0.0.30-pre` bietet `gregCore` (API v12) typsichere Abstraktionen für die wichtigsten internen Spielsysteme. Diese ermöglichen es, komplexe Spiellogik zu steuern, ohne direkt mit IL2CPP-Objekten hantieren zu müssen.
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## Verfügbare Services (gregSdk.Services)
### 1. GregUiService (v12 UI Hijack)
Ermöglicht das sichere Ersetzen von vanilla Spiel-UI nach der "Silent Takedown" Architektur.
<Tabs groupId="language">
<TabItem value="csharp" label="C#" default>
```csharp
using greg.Sdk.Services;
// Phase 2: Silent Takedown
GregUiService.HijackCanvas("PauseMenuCanvas", false);
// Phase 3: New Foundation
var myCanvas = GregUiService.CreateCanvas("MyModCanvas", 999);
```
</TabItem>
<TabItem value="lua" label="Lua">
```lua
-- Phase 2
greg.sdk.ui.hijack_canvas("PauseMenuCanvas", false)
-- Phase 3
local my_canvas = greg.sdk.ui.create_modern_canvas("MyModCanvas", 999)
```
</TabItem>
<TabItem value="rust" label="Rust">
```rust
// Phase 2: Silent Takedown
api.hijack_vanilla_canvas("PauseMenuCanvas");
// Phase 3: New Foundation
let my_canvas = api.create_modern_canvas("MyModCanvas", 999);
```
</TabItem>
</Tabs>
### 2. GregGameManagerService
Steuerung des globalen Spielzustands und der UI-Layer.
<Tabs groupId="language">
<TabItem value="csharp" label="C#" default>
```csharp
using gregSdk.Services;
GregGameManagerService.CloseAnyCanvas();
```
</TabItem>
<TabItem value="lua" label="Lua">
```lua
greg.game.close_any_canvas()
```
</TabItem>
<TabItem value="rust" label="Rust">
```rust
// via v8 API table
(api.close_any_canvas)();
```
</TabItem>
</Tabs>
### 2. GregPlayerManagerService
Interaktion mit dem Spieler-Avatar und dem Cursor.
<Tabs groupId="language">
<TabItem value="csharp" label="C#">
```csharp
using gregSdk.Services;
GregPlayerManagerService.ConfineCursorForUI();
```
</TabItem>
<TabItem value="lua" label="Lua">
```lua
greg.player.confine_cursor()
```
</TabItem>
</Tabs>
### 3. GregShopService
Vollständige Kontrolle über das Einkaufsmenü und physische Pakete.
<Tabs groupId="language">
<TabItem value="csharp" label="C#">
```csharp
using gregSdk.Services;
GregShopService.OpenColorPicker();
```
</TabItem>
<TabItem value="lua" label="Lua">
```lua
greg.shop.open_color_picker()
```
</TabItem>
</Tabs>
*(Weitere Services finden Sie in den entsprechenden Sprach-SDK-Referenzen.)*
## Best Practices
Alle Services nutzen intern `UnityEngine.Object.FindObjectOfType`. Rufen Sie diese Methoden daher **nicht** in jeder `Update()`-Schleife auf, sondern nur bei Bedarf (z.B. Event-getrieben), um die Performance zu schonen.
@@ -0,0 +1,211 @@
---
id: greg-hooks-catalog
title: greg hooks catalog & events runtime
description: Canonical `greg.*` runtime reference across HookBinder, GregEventDispatcher, GregNativeEventHooks, and EventIds mappings.
---
This page is the **canonical runtime reference** for the `greg.*` hook/event surface.
It merges the previous pages:
- `Hooks Catalog`
- `Greg Hooks & Events`
## Layer ownership
- **Core SDK layer:** `GregEventDispatcher`, `GregNativeEventHooks`, EventIds mapping
- **Hook registry layer:** `greg_hooks.json` + HookBinder-based Harmony wiring
- **Mod layer:** C#/Lua/TS/Rust consumers subscribe via `greg.*`
## Runtime model (single source of truth)
| Surface | Owner | Scope |
| --- | --- | --- |
| `greg_hooks.json` | Core hook registry | Full hook inventory for generated hook pages and HookBinder registration |
| `GregNativeEventHooks` | Core SDK | Named constants for stable subscriptions |
| `EventIds` -> `greg.*` | Core SDK bridge | Native/FFI numeric events normalized to string hook ids |
| `GregEventDispatcher` | Core SDK | Runtime payload bus (`On`, `Once`, `Off`, `Emit`) |
:::tip Canonical policy
If documentation conflicts, prefer this page + generated per-hook pages under **Hooks Library** (`/wiki/02_development/hooks-library/*`).
:::
## Subscription API
```csharp
GregEventDispatcher.On(GregNativeEventHooks.ServerInsertedInRack, payload =>
{
// handle payload
}, "MyMod");
GregEventDispatcher.Off(GregNativeEventHooks.ServerInsertedInRack, handler);
GregEventDispatcher.UnregisterAll("MyMod");
```
## Hook string constants (native bridge set)
| C# field | Hook string / expression |
| --- | --- |
| ``ContentOverrideApplied`` | ``greg.CONTENT.OverrideApplied`` |
| ``ContentRegistered`` | ``greg.CONTENT.Registered`` |
| ``ContentLoaded`` | ``greg.CONTENT.Loaded`` |
| ``CustomerAppRequirementsFailed`` | ``GregHookName.Create(GregDomain.Customer, "AppRequirementsFailed")`` |
| ``CustomerAppRequirementsSatisfied`` | ``GregHookName.Create(GregDomain.Customer, "AppRequirementsSatisfied")`` |
| ``CustomerMoneyUpdated`` | ``greg.CUSTOMER.MoneyUpdated`` |
| ``CustomerRequirementEvaluated`` | ``greg.CUSTOMER.RequirementEvaluated`` |
| ``EmployeeAnimationStateChanged`` | ``greg.EMPLOYEE.AnimationStateChanged`` |
| ``EmployeeCustomFired`` | ``GregHookName.Create(GregDomain.Employee, "CustomFired")`` |
| ``EmployeeCustomHired`` | ``GregHookName.Create(GregDomain.Employee, "CustomHired")`` |
| ``EmployeeDispatchProcessed`` | ``greg.EMPLOYEE.DispatchProcessed`` |
| ``EmployeeDispatchQueued`` | ``greg.EMPLOYEE.DispatchQueued`` |
| ``EmployeeIdleStateEntered`` | ``greg.EMPLOYEE.IdleStateEntered`` |
| ``EmployeeIdleStateExited`` | ``greg.EMPLOYEE.IdleStateExited`` |
| ``GameplayIncidentTriggered`` | ``greg.GAMEPLAY.IncidentTriggered`` |
| ``InputActionTriggered`` | ``greg.INPUT.ActionTriggered`` |
| ``InputBindingApplied`` | ``greg.INPUT.BindingApplied`` |
| ``InputBindingStarted`` | ``greg.INPUT.BindingStarted`` |
| ``NetworkBrokenSwitchAdded`` | ``greg.NETWORK.BrokenSwitchAdded`` |
| ``NetworkBrokenSwitchRemoved`` | ``greg.NETWORK.oveBrokenSwitchRemoved`` |
| ``NetworkCableLifecycleChanged`` | ``greg.NETWORK.CableLifecycleChanged`` |
| ``NetworkClearAllCables`` | ``greg.NETWORK.ClearAllCables`` |
| ``NetworkConnectionSpeedSet`` | ``greg.NETWORK.ConnectionSpeedSet`` |
| ``NetworkCreateNewCable`` | ``greg.NETWORK.CreateNewCable`` |
| ``NetworkDispatchProcessed`` | ``greg.NETWORK.DispatchProcessed`` |
| ``NetworkDispatchQueued`` | ``greg.NETWORK.DispatchQueued`` |
| ``NetworkInsertSfp`` | ``greg.NETWORK.InsertSFP`` |
| ``NetworkNetWatchDispatched`` | ``GregHookName.Create(GregDomain.Network, "NetWatchDispatched")`` |
| ``NetworkPositionRemoved`` | ``greg.NETWORK.ovePositionRemoved`` |
| ``NetworkSfpRemoved`` | ``greg.NETWORK.oveSFPRemoved`` |
| ``NetworkSwitchConfigClosed`` | ``greg.NETWORK.SwitchConfigClosed`` |
| ``NetworkSwitchConfigOpened`` | ``greg.NETWORK.SwitchConfigOpened`` |
| ``NetworkTopologyValidated`` | ``greg.NETWORK.TopologyValidated`` |
| ``PlayerCoinChanged`` | ``greg.PLAYER.CoinChanged`` |
| ``PlayerReputationChanged`` | ``greg.PLAYER.ReputationChanged`` |
| ``PlayerXpChanged`` | ``greg.PLAYER.XPChanged`` |
| ``RackButtonUnmountRack`` | ``greg.RACK.ButtonUnmountRack`` |
| ``RackDoorStateChanged`` | ``greg.RACK.DoorStateChanged`` |
| ``ServerAppIdChanged`` | ``greg.SERVER.AppIDChanged`` |
| ``ServerCustomerChanged`` | ``greg.SERVER.CustomerChanged`` |
| ``ServerDeviceRepaired`` | ``greg.SERVER.DeviceRepaired`` |
| ``ServerInsertedInRack`` | ``greg.SERVER.ServerInsertedInRack`` |
| ``ServerItIsBroken`` | ``greg.SERVER.ItIsBroken`` |
| ``ServerLoadingCompleted`` | ``greg.SERVER.LoadingCompleted`` |
| ``ServerLoadingStarted`` | ``greg.SERVER.LoadingStarted`` |
| ``ServerPowerButton`` | ``greg.SERVER.PowerButton`` |
| ``ServerRegisterLink`` | ``greg.SERVER.RegisterLink`` |
| ``ServerUnregisterLink`` | ``greg.SERVER.UnregisterLink`` |
| ``SystemApplicationQuit`` | ``greg.SYSTEM.ApplicationQuit`` |
| ``SystemAutoSaveRequested`` | ``GregHookName.Create(GregDomain.System, "AutoSaveRequested")`` |
| ``SystemButtonBuyShopItem`` | ``greg.SYSTEM.ButtonBuyShopItem`` |
| ``SystemButtonBuyWall`` | ``greg.SYSTEM.ButtonBuyWall`` |
| ``SystemButtonCheckOut`` | ``greg.SYSTEM.ButtonCheckOut`` |
| ``SystemButtonClear`` | ``greg.SYSTEM.ButtonClear`` |
| ``SystemButtonConfirmFireEmployee`` | ``greg.SYSTEM.ButtonConfirmFireEmployee`` |
| ``SystemButtonConfirmHire`` | ``greg.SYSTEM.ButtonConfirmHire`` |
| ``SystemButtonCustomerChosen`` | ``greg.SYSTEM.ButtonCustomerChosen`` |
| ``SystemDayEnded`` | ``greg.SYSTEM.DayEnded`` |
| ``SystemGameDayAdvanced`` | ``GregHookName.Create(GregDomain.System, "GameDayAdvanced")`` |
| ``SystemGameLoaded`` | ``GregHookName.Create(GregDomain.System, "GameLoaded")`` |
| ``SystemGameSaved`` | ``GregHookName.Create(GregDomain.System, "GameSaved")`` |
| ``SystemHookBridgeInstalled`` | ``GregHookName.Create(GregDomain.System, "HookBridgeInstalled")`` |
| ``SystemHookBridgeTriggered`` | ``GregHookName.Create(GregDomain.System, "HookBridgeTriggered")`` |
| ``SystemIncidentResolved`` | ``greg.SYSTEM.IncidentResolved`` |
| ``SystemIncidentTriggered`` | ``greg.SYSTEM.IncidentTriggered`` |
| ``SystemLoadCompleted`` | ``greg.SYSTEM.LoadCompleted`` |
| ``SystemLoadStarted`` | ``greg.SYSTEM.LoadStarted`` |
| ``SystemRuntimeObjectDestroyed`` | ``greg.SYSTEM.RuntimeObjectDestroyed`` |
| ``SystemRuntimeObjectDisabled`` | ``greg.SYSTEM.RuntimeObjectDisabled`` |
| ``SystemRuntimeObjectEnabled`` | ``greg.SYSTEM.RuntimeObjectEnabled`` |
| ``SystemRuntimeObjectLoaded`` | ``greg.SYSTEM.RuntimeObjectLoaded`` |
| ``SystemSaveStarted`` | ``greg.SYSTEM.SaveStarted`` |
| ``SystemShopCartItemAdded`` | ``greg.SYSTEM.ShopCartItemAdded`` |
| ``SystemShopCartItemRemoved`` | ``greg.SYSTEM.ShopCartItemRemoved`` |
| ``SystemSnapshotSaved`` | ``greg.SYSTEM.SnapshotSaved`` |
| ``SystemSpawnedItemRemoved`` | ``greg.SYSTEM.oveSpawnedItemRemoved`` |
| ``UiCancel`` | ``greg.UI.Cancel`` |
| ``UiPauseClosed`` | ``greg.UI.PauseClosed`` |
| ``UiPauseOpened`` | ``greg.UI.PauseOpened`` |
| ``UiPointerClick`` | ``greg.UI.PointerClick`` |
| ``UiPointerEnter`` | ``greg.UI.PointerEnter`` |
| ``UiPointerExit`` | ``greg.UI.PointerExit`` |
| ``UiSubmit`` | ``greg.UI.Submit`` |
| ``UiTabSelected`` | ``greg.UI.TabSelected`` |
| ``UnknownNativeEvent`` | ``greg.SYSTEM.UnmappedNativeEvent`` |
| ``WorldCollisionEntered`` | ``greg.WORLD.CollisionEntered`` |
| ``WorldInteractionHovered`` | ``greg.WORLD.InteractionHovered`` |
| ``WorldTriggerEntered`` | ``greg.WORLD.TriggerEntered`` |
## Event id to hook mapping (native bridge)
| Event id (uint) | EventIds name | GregNativeEventHooks field | Hook string |
| --- | --- | --- | --- |
| 213 | `CableCleared` | `NetworkClearAllCables` | `greg.NETWORK.ClearAllCables` |
| 204 | `CableConnected` | `ServerRegisterLink` | `greg.SERVER.RegisterLink` |
| 211 | `CableCreated` | `NetworkCreateNewCable` | `greg.NETWORK.CreateNewCable` |
| 205 | `CableDisconnected` | `ServerUnregisterLink` | `greg.SERVER.UnregisterLink` |
| 212 | `CableRemoved` | `NetworkPositionRemoved` | `greg.NETWORK.ovePositionRemoved` |
| 215 | `CableSfpInserted` | `NetworkInsertSfp` | `greg.NETWORK.InsertSFP` |
| 216 | `CableSfpRemoved` | `NetworkSfpRemoved` | `greg.NETWORK.oveSFPRemoved` |
| 214 | `CableSpeedChanged` | `NetworkConnectionSpeedSet` | `greg.NETWORK.ConnectionSpeedSet` |
| 1001 | `CustomEmployeeFired` | `EmployeeCustomFired` | `GregHookName.Create(GregDomain.Employee, "CustomFired")` |
| 1000 | `CustomEmployeeHired` | `EmployeeCustomHired` | `GregHookName.Create(GregDomain.Employee, "CustomHired")` |
| 400 | `CustomerAccepted` | `SystemButtonCustomerChosen` | `greg.SYSTEM.ButtonCustomerChosen` |
| 401 | `CustomerSatisfied` | `CustomerAppRequirementsSatisfied` | `GregHookName.Create(GregDomain.Customer, "AppRequirementsSatisfied")` |
| 402 | `CustomerUnsatisfied` | `CustomerAppRequirementsFailed` | `GregHookName.Create(GregDomain.Customer, "AppRequirementsFailed")` |
| 300 | `DayEnded` | `SystemGameDayAdvanced` | `GregHookName.Create(GregDomain.System, "GameDayAdvanced")` |
| 601 | `EmployeeFired` | `SystemButtonConfirmFireEmployee` | `greg.SYSTEM.ButtonConfirmFireEmployee` |
| 600 | `EmployeeHired` | `SystemButtonConfirmHire` | `greg.SYSTEM.ButtonConfirmHire` |
| 702 | `GameAutoSaved` | `SystemAutoSaveRequested` | `GregHookName.Create(GregDomain.System, "AutoSaveRequested")` |
| 701 | `GameLoaded` | `SystemGameLoaded` | `GregHookName.Create(GregDomain.System, "GameLoaded")` |
| 700 | `GameSaved` | `SystemGameSaved` | `GregHookName.Create(GregDomain.System, "GameSaved")` |
| 1100 | `HookBridgeInstalled` | `SystemHookBridgeInstalled` | `GregHookName.Create(GregDomain.System, "HookBridgeInstalled")` |
| 1101 | `HookBridgeTriggered` | `SystemHookBridgeTriggered` | `GregHookName.Create(GregDomain.System, "HookBridgeTriggered")` |
| 100 | `MoneyChanged` | `PlayerCoinChanged` | `greg.PLAYER.CoinChanged` |
| 301 | `MonthEnded` | `SystemSnapshotSaved` | `greg.SYSTEM.SnapshotSaved` |
| 900 | `NetWatchDispatched` | `NetworkNetWatchDispatched` | `GregHookName.Create(GregDomain.Network, "NetWatchDispatched")` |
| 208 | `RackUnmounted` | `RackButtonUnmountRack` | `greg.RACK.ButtonUnmountRack` |
| 102 | `ReputationChanged` | `PlayerReputationChanged` | `greg.PLAYER.ReputationChanged` |
| 207 | `ServerAppChanged` | `ServerAppIdChanged` | `greg.SERVER.AppIDChanged` |
| 201 | `ServerBroken` | `ServerItIsBroken` | `greg.SERVER.ItIsBroken` |
| 206 | `ServerCustomerChanged` | `ServerCustomerChanged` | `greg.SERVER.CustomerChanged` |
| 203 | `ServerInstalled` | `ServerInsertedInRack` | `greg.SERVER.ServerInsertedInRack` |
| 200 | `ServerPowered` | `ServerPowerButton` | `greg.SERVER.PowerButton` |
| 202 | `ServerRepaired` | `ServerDeviceRepaired` | `greg.SERVER.DeviceRepaired` |
| 502 | `ShopCartCleared` | `SystemButtonClear` | `greg.SYSTEM.ButtonClear` |
| 500 | `ShopCheckout` | `SystemButtonCheckOut` | `greg.SYSTEM.ButtonCheckOut` |
| 501 | `ShopItemAdded` | `SystemButtonBuyShopItem` | `greg.SYSTEM.ButtonBuyShopItem` |
| 503 | `ShopItemRemoved` | `SystemSpawnedItemRemoved` | `greg.SYSTEM.oveSpawnedItemRemoved` |
| 209 | `SwitchBroken` | `NetworkBrokenSwitchAdded` | `greg.NETWORK.BrokenSwitchAdded` |
| 210 | `SwitchRepaired` | `NetworkBrokenSwitchRemoved` | `greg.NETWORK.oveBrokenSwitchRemoved` |
| 800 | `WallPurchased` | `SystemButtonBuyWall` | `greg.SYSTEM.ButtonBuyWall` |
| 101 | `XPChanged` | `PlayerXpChanged` | `greg.PLAYER.XPChanged` |
## Important coverage note
The two tables above cover the **native bridge constants/mappings** surface.
The complete hook inventory (including non-EventIds HookBinder hooks) is documented in the generated **Hooks Library** pages.
- Hooks Library root: `/wiki/02_development/hooks-library`
- Source for generated hook pages: `gregCore/gregFramework/greg_hooks.json`
## Stability advisory: `Interact.OnHoverOver`
- **Layer:** Core SDK layer (`gregCore` Harmony patch class `GregHexViewerPatch`)
- **Current runtime status:** The `Interact.OnHoverOver` postfix hook path is currently safeguarded and disabled as a temporary stability gate.
- **Why:** Crash dump analysis identified a recursive hook loop in the hover path that produced stack overflow failures (`0xc00000fd`) during early runtime interaction.
- **Mitigation applied:** The hook was hard-gated to prevent execution while preserving broader hook/event runtime initialization.
- **Activation switch:** The hook is **opt-in** and only active when environment variable `GREG_ENABLE_HOVER_PATCH` is truthy (`1`, `true`, `yes`, `on`).
- **Impact to mods:** `greg.WORLD.InteractionHovered`-adjacent behavior may be reduced until a safe reimplementation is shipped.
- **Re-enable policy:** Re-enable only after a validated non-recursive implementation passes startup stability and interaction stress checks.
## Fallback behavior
Unknown event ids resolve to ``greg.SYSTEM.UnmappedNativeEvent`` via ``GregNativeEventHooks.Resolve``.
## See also
- [greg hook naming](/wiki/reference/fmf-hook-naming)
- [hooks library](/wiki/02_development/hooks-library)
- [EventIds source](https://github.com/mleem97/gregFramework/blob/main/gregCore/gregModLoader/EventDispatcher.cs)
- [GregNativeEventHooks source](https://github.com/mleem97/gregFramework/blob/main/gregCore/gregSdk/GregNativeEventHooks.cs)
@@ -0,0 +1,80 @@
---
id: fmf-hook-naming
title: FMF hook and event naming
description: Legacy documentation naming (`FMF.*`) and migration notes to canonical runtime `greg.*` hooks.
---
# FMF hook and event naming
:::warning Legacy documentation namespace
`FMF.*` is kept for documentation compatibility and historical references.
For runtime subscriptions and new APIs, use canonical `greg.*` hooks from `GregHookName` / `GregNativeEventHooks`.
:::
## Target format
All **new** public hook and event identifiers should follow:
```text
FMF.<Domain>.<EventOrHook>
```
- **`FMF`** Fixed prefix (Greg Mod Framework / **gregFramework** hook namespace).
- **`<Domain>`** Uppercase domain from the [approved domain list](#approved-domain-segments). Describes *where* the signal belongs in the game (player, rack, server, economy, ).
- **`<EventOrHook>`** `PascalCase` segment(s), usually `OnSomething` for events or a verb phrase for commands.
Examples (illustrative): `FMF.RACK.CableSpinnerColorResolved`, `FMF.PLAYER.InputPoll`, `FMF.NETWORK.Cable.OnConnected`.
## Approved domain segments
Domains are **closed by default**. Add a new domain only via changelog + maintainer review.
| Domain | Scope |
|--------|--------|
| `GAMEPLAY` | Rules, scoring, simulation beats not covered elsewhere |
| `PLAYER` | Local player input, camera, UI focus |
| `EMPLOYEE` | NPC staff, hiring, schedules |
| `CUSTOMER` | Contracts, SLA, satisfaction |
| `SERVER` | In-game server racks, VMs, power |
| `RACK` | Physical rack placement, mounting |
| `NETWORK` | Cables, switches, traffic |
| `STORE` | Shop cart, checkout |
| `WORLD` | Rooms, expansion, walls |
| `UI` | HUD overlays, menus (when not `PLAYER`) |
| `SAVE` | Save/load lifecycle |
| `FRAMEWORK` | Loader, bridge, diagnostics |
## Runtime IL2CPP (MelonLoader): `greg.*`
Harmony patches in **gregFramework** emit stable **`greg.<DOMAIN>.<Action>`** strings via `GregHookName` / `GregEventDispatcher`. That surface is documented in **[greg hooks catalog (IL2CPP)](/wiki/reference/greg-hooks-catalog)** (`greg_hooks.json`, regeneration, overlap with hand-written `HarmonyPatches`). It is separate from the `FMF.*` / `FFM.*` documentation constants below.
## Native pipeline: `GregNativeEventHooks` (replaces `gregNativeEventHooks`)
Numeric **`EventIds`** are mapped to canonical **`greg.*`** strings in **`GregNativeEventHooks`** ([source](https://github.com/mleem97/gregFramework/blob/main/gregCore/gregSdk/GregNativeEventHooks.cs)), aligned with **`greg_hooks.json`** where that file names the patched method. Logging uses **`GregNativeEventHooks.Resolve(uint)`**; unknown ids ? **`greg.SYSTEM.UnmappedNativeEvent`**.
**`GregCompatBridge`** ([source](https://github.com/mleem97/gregFramework/blob/main/gregCore/gregSdk/GregCompatBridge.cs)) redirects **deprecated** hook spellings (including older documentation-style names) to the current **`greg.*`** string see also `legacy` entries in **`greg_hooks.json`**.
**Policy**
- New **documentation** identifiers: **`FMF.<Domain>.*`** as above.
- New **runtime** subscriptions: always **`greg.*`** via **`GregHookName.Create`** or **`GregNativeEventHooks`** constants see [greg hooks catalog](/wiki/reference/greg-hooks-catalog).
## Cross-language stubs (documentation)
For each canonical hook, the wiki may add **non-normative** snippets:
| Language | Convention |
|----------|------------|
| C# | `FMF.Domain.OnSomething.Subscribe(...)` or string literal |
| Lua | `FMF.Domain.OnSomething:subscribe(...)` |
| Rust | `fmf::domain::on_something::subscribe(...)` |
| Python | `fmf.domain.on_something.subscribe(...)` |
| TypeScript | `FMF.Domain.OnSomething.subscribe(...)` |
Bindings are **not** auto-generated for all languages; stubs are for contributor clarity.
## Related
- [greg hooks catalog](/wiki/reference/greg-hooks-catalog) EventId ? **`greg.*`** (generated)
- [FMF hooks catalog](/wiki/reference/fmf-hook-naming) Short overview / Redirect
- [FMF hooks](/wiki/reference/fmf-hook-naming) declarative surface (may be superseded by the core registry)
@@ -0,0 +1,64 @@
---
title: SDK Services Overview
description: A complete index of the 40+ services available in the gregSdk for mod development.
---
The **gregSdk** provides a robust set of services to interact with Data Center's core systems, from networking and UI to game logic and employee AI.
## Core Services
### 💾 Persistence & State
- **GregPersistenceService**: Handles saving and loading mod-specific data.
- **GregSaveService**: Hooks into the main game save system.
- **GregMetadataService**: Manages metadata for game objects and entities.
### 🌐 Networking & IPAM
- **GregIpService**: The primary service for IP address management (IPAM).
- **GregIPAllocationService**: Handles automated IP assignment for server racks.
- **GregPacketService**: Provides low-level traffic and packet simulation data.
- **GregVlanService**: Manages virtual network segmentation and tagging.
- **GregTopologyService**: Visualizes and manages network connections.
### 🎨 User Interface (UI)
- **GregUiService**: The standard for creating integrated UI panels using the **LuminescentArchitect** design system.
- **GregHudService**: Manages overlays and HUD elements.
- **GregUiReplacementService**: Allows mods to swap vanilla game menus with custom implementations.
- **GregNotificationService**: Standardized toast and popup notifications.
## Game World Interaction
### 🏢 Infrastructure
- **GregRackService**: Service for rack state, cooling, and power management.
- **GregServerInteractionService**: Handles player interaction with server hardware.
- **GregPowerService**: Manages electricity distribution and usage tracking.
- **GregRackInteractionService**: Hooks for physical interaction with racks.
### 🤖 Automation & AI
- **GregTechnicianService**: API for interacting with the technician worker AI.
- **GregTaskQueueService**: Allows mods to queue tasks for worker AIs.
- **GregEmployeeAIBridge**: Bridge for extending default worker behaviors.
## System Utilities
### 🔧 Framework & Patches
- **GregHarmonyService**: Managed patching service for safe method hooking.
- **GregCompatBridgeService**: Ensures compatibility between different framework versions.
- **GregEventBus**: Global pub/sub system for inter-mod communication.
- **GregModRegistry**: The central directory of loaded mods and their capabilities.
### 🌍 Translation & Global
- **GregLocalisationService**: Integrated translation system for multi-language mods.
- **GregTimeService**: Access to game-time, simulation-speed, and historical events.
---
## Usage Patterns
Most services are available via static accessors for ease of use in small mods, but the framework recommends using dependency injection or service discovery for larger plugins.
```csharp
// Example: Sending a notification using GregNotificationService
GregNotificationService.Notify("System Update", "IPAM module has been synchronized.", NotificationType.Info);
```
For a full list of methods and properties, see the individual service pages in the sidebar.
@@ -0,0 +1,12 @@
---
title: Greg hooks & events (moved)
sidebar_label: Greg hooks & events (moved)
description: This page has been merged into the canonical greg hooks catalog & events runtime page.
unlisted: true
---
This page is deprecated and kept only for backward compatibility links.
Please use the merged canonical page:
- [greg hooks catalog & events runtime](/wiki/reference/greg-hooks-catalog)
@@ -0,0 +1,83 @@
---
id: developers
title: Documentation hub
sidebar_label: Documentation hub
description: Technical documentation for mod authors, plugin authors, and repo contributors hooks, workspace, releases, and internals.
---
# Documentation hub
Use this index if you **build mods or plugins**, work on **framework** code, or contribute to **repositories and docs**.
**Players** install and troubleshooting: **[For players](/players)** (not part of this wiki sidebar).
**Architecture:** read **[System architecture & documentation principles](/wiki/01_getting-started/architecture)** first canonical **ModManager ? Framework ? Plugins ? Mods** model, priorities (stability, maintainability, DX), and wiki writing rules.
## Workspace & onboarding
- [Getting started](/wiki/01_getting-started/quickstart) split-repo layout, build core, hook naming
- [Documentation layout](/wiki/01_getting-started/quickstart) how `docs/` is organized
- [Workspace map](/wiki/01_getting-started/architecture) folders on disk
## Framework
- [Architecture](/wiki/01_getting-started/architecture)
- [greg hooks catalog & events runtime](/wiki/reference/greg-hooks-catalog)
- [FMF hooks](/wiki/reference/fmf-hook-naming)
- [Hexmod](/wiki/developers)
## Plugins (`FFM.Plugin.*`) & mods (`FMF.*`)
- [Plugins overview](/mods)
- [Mods overview](/mods) gameplay mods and framework catalog
## Guides (authors & repo)
- [Mod developers](/wiki/developers)
- [Contributors (workflow)](/wiki/04_community/contributing)
- [Contributor workshop](/wiki/04_community/contributing)
- [Release guide](/wiki/developers)
- [Sponsors](/wiki/legal/sponsors)
## Tools & meta (advanced)
- [Steam Workshop & tooling](/wiki/developers)
- [Devserver betas](/wiki/developers)
- [IDEA backlog](/wiki/developers)
## Releases
- [Releases index](/wiki/developers)
## Reference
- [Wiki mapping](/wiki/developers)
- [Mod store vision](/wiki/developers)
- [FMF hook naming](/wiki/reference/fmf-hook-naming)
- [FMF hooks catalog](/wiki/reference/fmf-hook-naming)
- [MCP server](/wiki/developers)
- [Release channels](/wiki/developers) where authors publish (Workshop vs GitHub); players see a short summary on [/players](/players)
- [Reference data files](/wiki/developers)
- [Modding language requirement](/wiki/developers)
## Topics
- [Topics hub](/wiki/developers)
## Contributors (workflow)
- [Repo inventory](/wiki/04_community/contributing)
- [Monorepo target layout](/wiki/04_community/contributing)
- [Design system](/wiki/04_community/contributing)
- [Contributor workflow](/wiki/04_community/contributing)
- [Plugin submission audit](/wiki/04_community/contributing)
- [Sponsorship automation](/wiki/04_community/contributing)
## Roadmap
- [Unified roadmap](/wiki/developers)
- [Mod store stages](/wiki/developers)
## Sponsors
- [SPONSORS](/wiki/legal/sponsors)
@@ -0,0 +1,24 @@
---
title: greg.Content.Loaded
sidebar_label: Loaded
description: "gregCore Hook — Normalized Unity signal for content being loaded."
---
# `greg.Content.Loaded`
## Description
- Normalized Unity signal for content being loaded.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Content.Loaded", payload =>
{
// Handle content loaded event
});
```
@@ -0,0 +1,24 @@
---
title: greg.Content.OverrideApplied
sidebar_label: OverrideApplied
description: "gregCore Hook — Normalized Unity signal for content override being applied."
---
# `greg.Content.OverrideApplied`
## Description
- Normalized Unity signal for content override being applied.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Content.OverrideApplied", payload =>
{
// Handle content override applied event
});
```
@@ -0,0 +1,24 @@
---
title: greg.Content.Registered
sidebar_label: Registered
description: "gregCore Hook — Normalized Unity signal for content being registered."
---
# `greg.Content.Registered`
## Description
- Normalized Unity signal for content being registered.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Content.Registered", payload =>
{
// Handle content registered event
});
```
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.AppPerformanceAdded
sidebar_label: AppPerformanceAdded
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.AddAppPerformance"
---
# `greg.CUSTOMER.AppPerformanceAdded`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.AddAppPerformance
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::AddAppPerformance(int, float)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.AddAppPerformance |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.AppPerformanceAdded`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.AppPerformanceAdded", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.AppPerformanceAdded`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.AppPerformanceAdded", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.AppPerformanceAdded", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.AppPerformanceAdded", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.AppPerformanceAdded", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.AppPerformanceAdded", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.AppPerformanceAdded", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.AppPerformanceAdded` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.AppText
sidebar_label: AppText
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.AppText"
---
# `greg.CUSTOMER.AppText`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.AppText
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::AppText(int)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.AppText |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.AppText`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.AppText", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.AppText`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.AppText", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.AppText", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.AppText", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.AppText", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.AppText", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.AppText", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.AppText` as the canonical routing key end-to-end.
@@ -0,0 +1,123 @@
---
title: greg.CUSTOMER.ComponentInitialized
sidebar_label: ComponentInitialized
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.Awake"
---
# `greg.CUSTOMER.ComponentInitialized`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.Awake
- Auto-generated from Il2Cpp unpack: CustomerBase.Start
## Patch Targets (Il2Cpp)
This hook name can be mapped to **2** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::Awake()` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.Awake |
| `Il2Cpp.CustomerBase::Start()` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.Start |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.ComponentInitialized`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.ComponentInitialized", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.ComponentInitialized`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.ComponentInitialized", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.ComponentInitialized", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.ComponentInitialized", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.ComponentInitialized", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.ComponentInitialized", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.ComponentInitialized", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.ComponentInitialized` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.CustomerServerCountAndSpeedChanged
sidebar_label: CustomerServerCountAndSpeedChanged
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.UpdateCustomerServerCountAndSpeed"
---
# `greg.CUSTOMER.CustomerServerCountAndSpeedChanged`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.UpdateCustomerServerCountAndSpeed
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::UpdateCustomerServerCountAndSpeed(int, float)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.UpdateCustomerServerCountAndSpeed |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.CustomerServerCountAndSpeedChanged`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.CustomerServerCountAndSpeedChanged`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.CustomerServerCountAndSpeedChanged", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.CustomerServerCountAndSpeedChanged` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.DataLoaded
sidebar_label: DataLoaded
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.LoadData"
---
# `greg.CUSTOMER.DataLoaded`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.LoadData
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::LoadData(CustomerBaseSaveData)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.LoadData |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.DataLoaded`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.DataLoaded", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.DataLoaded`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.DataLoaded", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.DataLoaded", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.DataLoaded", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.DataLoaded", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.DataLoaded", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.DataLoaded", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.DataLoaded` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.GetAppIDForIP
sidebar_label: GetAppIDForIP
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.GetAppIDForIP"
---
# `greg.CUSTOMER.GetAppIDForIP`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.GetAppIDForIP
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::GetAppIDForIP(string)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.GetAppIDForIP |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.GetAppIDForIP`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.GetAppIDForIP", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.GetAppIDForIP`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.GetAppIDForIP", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.GetAppIDForIP", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.GetAppIDForIP", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.GetAppIDForIP", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.GetAppIDForIP", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.GetAppIDForIP", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.GetAppIDForIP` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.GetServerTypeForIP
sidebar_label: GetServerTypeForIP
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.GetServerTypeForIP"
---
# `greg.CUSTOMER.GetServerTypeForIP`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.GetServerTypeForIP
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::GetServerTypeForIP(string)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.GetServerTypeForIP |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.GetServerTypeForIP`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.GetServerTypeForIP", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.GetServerTypeForIP`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.GetServerTypeForIP", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.GetServerTypeForIP", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.GetServerTypeForIP", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.GetServerTypeForIP", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.GetServerTypeForIP", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.GetServerTypeForIP", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.GetServerTypeForIP` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.GetSubnetsPerApp
sidebar_label: GetSubnetsPerApp
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.GetSubnetsPerApp"
---
# `greg.CUSTOMER.GetSubnetsPerApp`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.GetSubnetsPerApp
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::GetSubnetsPerApp()` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.GetSubnetsPerApp |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.GetSubnetsPerApp`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.GetSubnetsPerApp", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.GetSubnetsPerApp`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.GetSubnetsPerApp", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.GetSubnetsPerApp", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.GetSubnetsPerApp", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.GetSubnetsPerApp", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.GetSubnetsPerApp", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.GetSubnetsPerApp", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.GetSubnetsPerApp` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.GetTotalAppSpeed
sidebar_label: GetTotalAppSpeed
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.GetTotalAppSpeed"
---
# `greg.CUSTOMER.GetTotalAppSpeed`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.GetTotalAppSpeed
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::GetTotalAppSpeed()` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.GetTotalAppSpeed |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.GetTotalAppSpeed`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.GetTotalAppSpeed", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.GetTotalAppSpeed`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.GetTotalAppSpeed", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.GetTotalAppSpeed", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.GetTotalAppSpeed", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.GetTotalAppSpeed", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.GetTotalAppSpeed", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.GetTotalAppSpeed", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.GetTotalAppSpeed` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.IsIPPresent
sidebar_label: IsIPPresent
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.IsIPPresent"
---
# `greg.CUSTOMER.IsIPPresent`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.IsIPPresent
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::IsIPPresent(string)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.IsIPPresent |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.IsIPPresent`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.IsIPPresent", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.IsIPPresent`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.IsIPPresent", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.IsIPPresent", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.IsIPPresent", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.IsIPPresent", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.IsIPPresent", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.IsIPPresent", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.IsIPPresent` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.CUSTOMER.MoneyUpdated
sidebar_label: MoneyUpdated
description: Canonical event hook for greg.CUSTOMER.MoneyUpdated (Normalized Unity Signal).
---
# greg.CUSTOMER.MoneyUpdated
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.CustomerMoneyUpdated, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.CUSTOMER.MoneyUpdated triggered for {entityId}");
});
```
@@ -0,0 +1,28 @@
---
title: greg.CUSTOMER.RequirementEvaluated
sidebar_label: RequirementEvaluated
description: Canonical event hook for greg.CUSTOMER.RequirementEvaluated (Normalized Unity Signal).
---
# greg.CUSTOMER.RequirementEvaluated
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.CustomerRequirementEvaluated, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.CUSTOMER.RequirementEvaluated triggered for {entityId}");
});
```
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.ResetAllAppSpeeds
sidebar_label: ResetAllAppSpeeds
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.ResetAllAppSpeeds"
---
# `greg.CUSTOMER.ResetAllAppSpeeds`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.ResetAllAppSpeeds
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::ResetAllAppSpeeds()` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.ResetAllAppSpeeds |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.ResetAllAppSpeeds`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.ResetAllAppSpeeds", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.ResetAllAppSpeeds`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.ResetAllAppSpeeds", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.ResetAllAppSpeeds", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.ResetAllAppSpeeds", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.ResetAllAppSpeeds", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.ResetAllAppSpeeds", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.ResetAllAppSpeeds", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.ResetAllAppSpeeds` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.SpeedOnCustomerBaseAppChanged
sidebar_label: SpeedOnCustomerBaseAppChanged
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.UpdateSpeedOnCustomerBaseApp"
---
# `greg.CUSTOMER.SpeedOnCustomerBaseAppChanged`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.UpdateSpeedOnCustomerBaseApp
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::UpdateSpeedOnCustomerBaseApp(int, float)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.UpdateSpeedOnCustomerBaseApp |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.SpeedOnCustomerBaseAppChanged`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.SpeedOnCustomerBaseAppChanged`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.SpeedOnCustomerBaseAppChanged", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.SpeedOnCustomerBaseAppChanged` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.UpAppSet
sidebar_label: UpAppSet
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.SetUpApp"
---
# `greg.CUSTOMER.UpAppSet`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.SetUpApp
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::SetUpApp(int, int, CustomerBaseSaveData)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.SetUpApp |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.UpAppSet`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.UpAppSet", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.UpAppSet`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.UpAppSet", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.UpAppSet", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.UpAppSet", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.UpAppSet", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.UpAppSet", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.UpAppSet", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.UpAppSet` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.CUSTOMER.UpBaseSet
sidebar_label: UpBaseSet
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CustomerBase.SetUpBase"
---
# `greg.CUSTOMER.UpBaseSet`
## Description
- Auto-generated from Il2Cpp unpack: CustomerBase.SetUpBase
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CustomerBase::SetUpBase(CustomerItem, CustomerBaseSaveData)` | Postfix | Auto-generated from Il2Cpp unpack: CustomerBase.SetUpBase |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.CUSTOMER.UpBaseSet`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.CUSTOMER.UpBaseSet", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.CUSTOMER.UpBaseSet`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.CUSTOMER.UpBaseSet", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.CUSTOMER.UpBaseSet", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.CUSTOMER.UpBaseSet", |payload| {
if let Some(method) = payload.get("method") {
println!("[CUSTOMER] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.CUSTOMER.UpBaseSet", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[CUSTOMER] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.CUSTOMER.UpBaseSet", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.CUSTOMER.UpBaseSet", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[CUSTOMER] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.CUSTOMER.UpBaseSet` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.EMPLOYEE.AnimationStateChanged
sidebar_label: AnimationStateChanged
description: Canonical event hook for greg.EMPLOYEE.AnimationStateChanged (Normalized Unity Signal).
---
# greg.EMPLOYEE.AnimationStateChanged
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.EmployeeAnimationStateChanged, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.EMPLOYEE.AnimationStateChanged triggered for {entityId}");
});
```
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.AssignJob
sidebar_label: AssignJob
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.AssignJob"
---
# `greg.EMPLOYEE.AssignJob`
## Description
- Auto-generated from Il2Cpp unpack: Technician.AssignJob
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::AssignJob(TechnicianManager.RepairJob)` | Postfix | Auto-generated from Il2Cpp unpack: Technician.AssignJob |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.AssignJob`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.AssignJob", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.AssignJob`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.AssignJob", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.AssignJob", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.AssignJob", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.AssignJob", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.AssignJob", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.AssignJob", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.AssignJob` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.ButtonFireEmployee
sidebar_label: ButtonFireEmployee
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: HRSystem.ButtonFireEmployee"
---
# `greg.EMPLOYEE.ButtonFireEmployee`
## Description
- Auto-generated from Il2Cpp unpack: HRSystem.ButtonFireEmployee
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.HRSystem::ButtonFireEmployee(int)` | Postfix | Auto-generated from Il2Cpp unpack: HRSystem.ButtonFireEmployee |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.ButtonFireEmployee`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.ButtonFireEmployee", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.ButtonFireEmployee`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.ButtonFireEmployee", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.ButtonFireEmployee", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.ButtonFireEmployee", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.ButtonFireEmployee", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.ButtonFireEmployee", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.ButtonFireEmployee", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.ButtonFireEmployee` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.ButtonHireEmployee
sidebar_label: ButtonHireEmployee
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: HRSystem.ButtonHireEmployee"
---
# `greg.EMPLOYEE.ButtonHireEmployee`
## Description
- Auto-generated from Il2Cpp unpack: HRSystem.ButtonHireEmployee
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.HRSystem::ButtonHireEmployee(int)` | Postfix | Auto-generated from Il2Cpp unpack: HRSystem.ButtonHireEmployee |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.ButtonHireEmployee`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.ButtonHireEmployee", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.ButtonHireEmployee`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.ButtonHireEmployee", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.ButtonHireEmployee", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.ButtonHireEmployee", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.ButtonHireEmployee", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.ButtonHireEmployee", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.ButtonHireEmployee", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.ButtonHireEmployee` as the canonical routing key end-to-end.
@@ -0,0 +1,125 @@
---
title: greg.EMPLOYEE.ComponentInitialized
sidebar_label: ComponentInitialized
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.Awake"
---
# `greg.EMPLOYEE.ComponentInitialized`
## Description
- Auto-generated from Il2Cpp unpack: Technician.Awake
- Auto-generated from Il2Cpp unpack: Technician.Start
- Auto-generated from Il2Cpp unpack: TechnicianManager.Awake
## Patch Targets (Il2Cpp)
This hook name can be mapped to **3** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::Awake()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.Awake |
| `Il2Cpp.Technician::Start()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.Start |
| `Il2Cpp.TechnicianManager::Awake()` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.Awake |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.ComponentInitialized`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.ComponentInitialized", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.ComponentInitialized`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.ComponentInitialized", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.ComponentInitialized", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.ComponentInitialized", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.ComponentInitialized", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.ComponentInitialized", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.ComponentInitialized", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.ComponentInitialized` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.DeviceRepaired
sidebar_label: DeviceRepaired
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.RepairDevice"
---
# `greg.EMPLOYEE.DeviceRepaired`
## Description
- Auto-generated from Il2Cpp unpack: Technician.RepairDevice
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::RepairDevice()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.RepairDevice |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.DeviceRepaired`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.DeviceRepaired", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.DeviceRepaired`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.DeviceRepaired", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.DeviceRepaired", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.DeviceRepaired", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.DeviceRepaired", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.DeviceRepaired", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.DeviceRepaired", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.DeviceRepaired` as the canonical routing key end-to-end.
@@ -0,0 +1,122 @@
---
title: greg.EMPLOYEE.Dispatched
sidebar_label: Dispatched
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.SendTechnician"
---
# `greg.EMPLOYEE.Dispatched`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.SendTechnician
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::SendTechnician(NetworkSwitch, Server)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.SendTechnician |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `networkSwitch` | `NetworkSwitch` |
| `server` | `Server` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.Dispatched`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.Dispatched", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.Dispatched`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.Dispatched", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.Dispatched", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.Dispatched", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.Dispatched", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.Dispatched", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.Dispatched", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.Dispatched` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.EMPLOYEE.DispatchProcessed
sidebar_label: DispatchProcessed
description: Canonical event hook for greg.EMPLOYEE.DispatchProcessed (Normalized Unity Signal).
---
# greg.EMPLOYEE.DispatchProcessed
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.EmployeeDispatchProcessed, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.EMPLOYEE.DispatchProcessed triggered for {entityId}");
});
```
@@ -0,0 +1,28 @@
---
title: greg.EMPLOYEE.DispatchQueued
sidebar_label: DispatchQueued
description: Canonical event hook for greg.EMPLOYEE.DispatchQueued (Normalized Unity Signal).
---
# greg.EMPLOYEE.DispatchQueued
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.EmployeeDispatchQueued, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.EMPLOYEE.DispatchQueued triggered for {entityId}");
});
```
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.Fired
sidebar_label: Fired
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.FireTechnician"
---
# `greg.EMPLOYEE.Fired`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.FireTechnician
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::FireTechnician(int)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.FireTechnician |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `technicianID` | `int` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.Fired`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.Fired", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.Fired`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.Fired", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.Fired", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.Fired", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.Fired", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.Fired", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.Fired", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.Fired` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.GetCorrectDevicePrefab
sidebar_label: GetCorrectDevicePrefab
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.GetCorrectDevicePrefab"
---
# `greg.EMPLOYEE.GetCorrectDevicePrefab`
## Description
- Auto-generated from Il2Cpp unpack: Technician.GetCorrectDevicePrefab
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::GetCorrectDevicePrefab()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.GetCorrectDevicePrefab |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.GetCorrectDevicePrefab`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.GetCorrectDevicePrefab", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.GetCorrectDevicePrefab`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.GetCorrectDevicePrefab", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.GetCorrectDevicePrefab", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.GetCorrectDevicePrefab", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.GetCorrectDevicePrefab", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.GetCorrectDevicePrefab", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.GetCorrectDevicePrefab", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.GetCorrectDevicePrefab` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.Hired
sidebar_label: Hired
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.AddTechnician"
---
# `greg.EMPLOYEE.Hired`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.AddTechnician
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::AddTechnician(Technician)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.AddTechnician |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `technician` | `Technician` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.Hired`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.Hired", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.Hired`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.Hired", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.Hired", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.Hired", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.Hired", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.Hired", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.Hired", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.Hired` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.EMPLOYEE.IdleStateEntered
sidebar_label: IdleStateEntered
description: Canonical event hook for greg.EMPLOYEE.IdleStateEntered (Normalized Unity Signal).
---
# greg.EMPLOYEE.IdleStateEntered
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.EmployeeIdleStateEntered, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.EMPLOYEE.IdleStateEntered triggered for {entityId}");
});
```
@@ -0,0 +1,28 @@
---
title: greg.EMPLOYEE.IdleStateExited
sidebar_label: IdleStateExited
description: Canonical event hook for greg.EMPLOYEE.IdleStateExited (Normalized Unity Signal).
---
# greg.EMPLOYEE.IdleStateExited
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.EmployeeIdleStateExited, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.EMPLOYEE.IdleStateExited triggered for {entityId}");
});
```
@@ -0,0 +1,123 @@
---
title: greg.EMPLOYEE.IsDeviceAlreadyAssigned
sidebar_label: IsDeviceAlreadyAssigned
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.IsDeviceAlreadyAssigned"
---
# `greg.EMPLOYEE.IsDeviceAlreadyAssigned`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.IsDeviceAlreadyAssigned
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::IsDeviceAlreadyAssigned(NetworkSwitch, Server)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.IsDeviceAlreadyAssigned |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `networkSwitch` | `NetworkSwitch` |
| `server` | `Server` |
| `assigned` | `bool` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.IsDeviceAlreadyAssigned`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.IsDeviceAlreadyAssigned", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.IsDeviceAlreadyAssigned`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.IsDeviceAlreadyAssigned", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.IsDeviceAlreadyAssigned", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.IsDeviceAlreadyAssigned", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.IsDeviceAlreadyAssigned", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.IsDeviceAlreadyAssigned", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.IsDeviceAlreadyAssigned", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.IsDeviceAlreadyAssigned` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.JobQueued
sidebar_label: JobQueued
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.EnqueueDispatch"
---
# `greg.EMPLOYEE.JobQueued`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.EnqueueDispatch
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::EnqueueDispatch(TechnicianManager.RepairJob)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.EnqueueDispatch |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `job` | `TechnicianManager.RepairJob` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.JobQueued`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.JobQueued", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.JobQueued`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.JobQueued", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.JobQueued", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.JobQueued", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.JobQueued", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.JobQueued", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.JobQueued", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.JobQueued` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.JobQueueLoaded
sidebar_label: JobQueueLoaded
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.RestoreJobQueue"
---
# `greg.EMPLOYEE.JobQueueLoaded`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.RestoreJobQueue
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::RestoreJobQueue(List<RepairJobSaveData>)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.RestoreJobQueue |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `savedJobs` | `List<RepairJobSaveData>` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.JobQueueLoaded`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.JobQueueLoaded", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.JobQueueLoaded`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.JobQueueLoaded", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.JobQueueLoaded", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.JobQueueLoaded", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.JobQueueLoaded", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.JobQueueLoaded", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.JobQueueLoaded", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.JobQueueLoaded` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.NextJobRequested
sidebar_label: NextJobRequested
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: TechnicianManager.RequestNextJob"
---
# `greg.EMPLOYEE.NextJobRequested`
## Description
- Auto-generated from Il2Cpp unpack: TechnicianManager.RequestNextJob
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.TechnicianManager::RequestNextJob(Technician)` | Postfix | Auto-generated from Il2Cpp unpack: TechnicianManager.RequestNextJob |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `technician` | `Technician` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.NextJobRequested`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.NextJobRequested", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.NextJobRequested`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.NextJobRequested", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.NextJobRequested", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.NextJobRequested", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.NextJobRequested", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.NextJobRequested", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.NextJobRequested", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.NextJobRequested` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.OnDestroy
sidebar_label: OnDestroy
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.OnDestroy"
---
# `greg.EMPLOYEE.OnDestroy`
## Description
- Auto-generated from Il2Cpp unpack: Technician.OnDestroy
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::OnDestroy()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.OnDestroy |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.OnDestroy`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.OnDestroy", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.OnDestroy`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.OnDestroy", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.OnDestroy", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.OnDestroy", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.OnDestroy", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.OnDestroy", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.OnDestroy", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.OnDestroy` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.OnLoadingStarted
sidebar_label: OnLoadingStarted
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.OnLoadingStarted"
---
# `greg.EMPLOYEE.OnLoadingStarted`
## Description
- Auto-generated from Il2Cpp unpack: Technician.OnLoadingStarted
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::OnLoadingStarted()` | Postfix | Auto-generated from Il2Cpp unpack: Technician.OnLoadingStarted |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.OnLoadingStarted`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.OnLoadingStarted", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.OnLoadingStarted`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.OnLoadingStarted", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.OnLoadingStarted", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.OnLoadingStarted", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.OnLoadingStarted", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.OnLoadingStarted", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.OnLoadingStarted", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.OnLoadingStarted` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.PositionHandTargetsOnDevice
sidebar_label: PositionHandTargetsOnDevice
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.PositionHandTargetsOnDevice"
---
# `greg.EMPLOYEE.PositionHandTargetsOnDevice`
## Description
- Auto-generated from Il2Cpp unpack: Technician.PositionHandTargetsOnDevice
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::PositionHandTargetsOnDevice(GameObject)` | Postfix | Auto-generated from Il2Cpp unpack: Technician.PositionHandTargetsOnDevice |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.PositionHandTargetsOnDevice`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.PositionHandTargetsOnDevice", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.PositionHandTargetsOnDevice`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.PositionHandTargetsOnDevice", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.PositionHandTargetsOnDevice", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.PositionHandTargetsOnDevice", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.PositionHandTargetsOnDevice", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.PositionHandTargetsOnDevice", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.PositionHandTargetsOnDevice", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.PositionHandTargetsOnDevice` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.EMPLOYEE.RotateTowardsGoal
sidebar_label: RotateTowardsGoal
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Technician.RotateTowardsGoal"
---
# `greg.EMPLOYEE.RotateTowardsGoal`
## Description
- Auto-generated from Il2Cpp unpack: Technician.RotateTowardsGoal
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Technician::RotateTowardsGoal(Vector3)` | Postfix | Auto-generated from Il2Cpp unpack: Technician.RotateTowardsGoal |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.EMPLOYEE.RotateTowardsGoal`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.EMPLOYEE.RotateTowardsGoal", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.EMPLOYEE.RotateTowardsGoal`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.EMPLOYEE.RotateTowardsGoal", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.EMPLOYEE.RotateTowardsGoal", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.EMPLOYEE.RotateTowardsGoal", |payload| {
if let Some(method) = payload.get("method") {
println!("[EMPLOYEE] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.EMPLOYEE.RotateTowardsGoal", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[EMPLOYEE] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.EMPLOYEE.RotateTowardsGoal", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.EMPLOYEE.RotateTowardsGoal", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[EMPLOYEE] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.EMPLOYEE.RotateTowardsGoal` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.ClearObjectives
sidebar_label: ClearObjectives
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.ClearObjectives"
---
# `greg.GAMEPLAY.ClearObjectives`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.ClearObjectives
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::ClearObjectives()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.ClearObjectives |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.ClearObjectives`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.ClearObjectives", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.ClearObjectives`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.ClearObjectives", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.ClearObjectives", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.ClearObjectives", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.ClearObjectives", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.ClearObjectives", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.ClearObjectives", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.ClearObjectives` as the canonical routing key end-to-end.
@@ -0,0 +1,123 @@
---
title: greg.GAMEPLAY.ComponentInitialized
sidebar_label: ComponentInitialized
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.Awake"
---
# `greg.GAMEPLAY.ComponentInitialized`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.Awake
- Auto-generated from Il2Cpp unpack: Objectives.Start
## Patch Targets (Il2Cpp)
This hook name can be mapped to **2** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::Awake()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.Awake |
| `Il2Cpp.Objectives::Start()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.Start |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.ComponentInitialized`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.ComponentInitialized", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.ComponentInitialized`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.ComponentInitialized", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.ComponentInitialized", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.ComponentInitialized", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.ComponentInitialized", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.ComponentInitialized", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.ComponentInitialized", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.ComponentInitialized` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.CreateAppObjective
sidebar_label: CreateAppObjective
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.CreateAppObjective"
---
# `greg.GAMEPLAY.CreateAppObjective`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.CreateAppObjective
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::CreateAppObjective(int, int, int, int)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.CreateAppObjective |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.CreateAppObjective`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.CreateAppObjective", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.CreateAppObjective`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.CreateAppObjective", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.CreateAppObjective", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.CreateAppObjective", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.CreateAppObjective", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.CreateAppObjective", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.CreateAppObjective", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.CreateAppObjective` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.CreateNewObjective
sidebar_label: CreateNewObjective
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.CreateNewObjective"
---
# `greg.GAMEPLAY.CreateNewObjective`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.CreateNewObjective
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::CreateNewObjective(int, int, Vector3, int, int, bool)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.CreateNewObjective |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.CreateNewObjective`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.CreateNewObjective", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.CreateNewObjective`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.CreateNewObjective", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.CreateNewObjective", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.CreateNewObjective", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.CreateNewObjective", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.CreateNewObjective", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.CreateNewObjective", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.CreateNewObjective` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.DestroyObjective
sidebar_label: DestroyObjective
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.DestroyObjective"
---
# `greg.GAMEPLAY.DestroyObjective`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.DestroyObjective
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::DestroyObjective(int)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.DestroyObjective |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.DestroyObjective`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.DestroyObjective", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.DestroyObjective`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.DestroyObjective", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.DestroyObjective", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.DestroyObjective", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.DestroyObjective", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.DestroyObjective", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.DestroyObjective", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.DestroyObjective` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.GetTimedObjective
sidebar_label: GetTimedObjective
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.GetTimedObjective"
---
# `greg.GAMEPLAY.GetTimedObjective`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.GetTimedObjective
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::GetTimedObjective(int)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.GetTimedObjective |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.GetTimedObjective`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.GetTimedObjective", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.GetTimedObjective`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.GetTimedObjective", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.GetTimedObjective", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.GetTimedObjective", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.GetTimedObjective", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.GetTimedObjective", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.GetTimedObjective", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.GetTimedObjective` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.GAMEPLAY.IncidentTriggered
sidebar_label: IncidentTriggered
description: Canonical event hook for greg.GAMEPLAY.IncidentTriggered (Normalized Unity Signal).
---
# greg.GAMEPLAY.IncidentTriggered
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.GameplayIncidentTriggered, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.GAMEPLAY.IncidentTriggered triggered for {entityId}");
});
```
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.InstantiateObjectiveSign
sidebar_label: InstantiateObjectiveSign
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.InstantiateObjectiveSign"
---
# `greg.GAMEPLAY.InstantiateObjectiveSign`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.InstantiateObjectiveSign
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::InstantiateObjectiveSign(int, Vector3)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.InstantiateObjectiveSign |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.InstantiateObjectiveSign`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.InstantiateObjectiveSign", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.InstantiateObjectiveSign`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.InstantiateObjectiveSign", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.InstantiateObjectiveSign", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.InstantiateObjectiveSign", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.InstantiateObjectiveSign", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.InstantiateObjectiveSign", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.InstantiateObjectiveSign", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.InstantiateObjectiveSign` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.IsTutorialInProgress
sidebar_label: IsTutorialInProgress
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.IsTutorialInProgress"
---
# `greg.GAMEPLAY.IsTutorialInProgress`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.IsTutorialInProgress
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::IsTutorialInProgress()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.IsTutorialInProgress |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.IsTutorialInProgress`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.IsTutorialInProgress", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.IsTutorialInProgress`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.IsTutorialInProgress", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.IsTutorialInProgress", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.IsTutorialInProgress", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.IsTutorialInProgress", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.IsTutorialInProgress", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.IsTutorialInProgress", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.IsTutorialInProgress` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.ObjectiveSignRemoved
sidebar_label: ObjectiveSignRemoved
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.RemoveObjectiveSign"
---
# `greg.GAMEPLAY.ObjectiveSignRemoved`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.RemoveObjectiveSign
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::RemoveObjectiveSign(int)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.RemoveObjectiveSign |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.ObjectiveSignRemoved`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.ObjectiveSignRemoved", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.ObjectiveSignRemoved`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.ObjectiveSignRemoved", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.ObjectiveSignRemoved", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.ObjectiveSignRemoved", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.ObjectiveSignRemoved", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.ObjectiveSignRemoved", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.ObjectiveSignRemoved", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.ObjectiveSignRemoved` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.ObjectiveTimedText
sidebar_label: ObjectiveTimedText
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.ObjectiveTimedText"
---
# `greg.GAMEPLAY.ObjectiveTimedText`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.ObjectiveTimedText
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::ObjectiveTimedText()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.ObjectiveTimedText |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.ObjectiveTimedText`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.ObjectiveTimedText", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.ObjectiveTimedText`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.ObjectiveTimedText", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.ObjectiveTimedText", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.ObjectiveTimedText", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.ObjectiveTimedText", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.ObjectiveTimedText", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.ObjectiveTimedText", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.ObjectiveTimedText` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.OnDestroy
sidebar_label: OnDestroy
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.OnDestroy"
---
# `greg.GAMEPLAY.OnDestroy`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.OnDestroy
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::OnDestroy()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.OnDestroy |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.OnDestroy`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.OnDestroy", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.OnDestroy`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.OnDestroy", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.OnDestroy", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.OnDestroy", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.OnDestroy", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.OnDestroy", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.OnDestroy", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.OnDestroy` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.OnLoad
sidebar_label: OnLoad
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.OnLoad"
---
# `greg.GAMEPLAY.OnLoad`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.OnLoad
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::OnLoad()` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.OnLoad |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.OnLoad`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.OnLoad", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.OnLoad`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.OnLoad", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.OnLoad", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.OnLoad", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.OnLoad", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.OnLoad", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.OnLoad", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.OnLoad` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.GAMEPLAY.StartObjective
sidebar_label: StartObjective
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: Objectives.StartObjective"
---
# `greg.GAMEPLAY.StartObjective`
## Description
- Auto-generated from Il2Cpp unpack: Objectives.StartObjective
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.Objectives::StartObjective(int, Vector3, bool)` | Postfix | Auto-generated from Il2Cpp unpack: Objectives.StartObjective |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.GAMEPLAY.StartObjective`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.GAMEPLAY.StartObjective", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.GAMEPLAY.StartObjective`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.GAMEPLAY.StartObjective", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.GAMEPLAY.StartObjective", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.GAMEPLAY.StartObjective", |payload| {
if let Some(method) = payload.get("method") {
println!("[GAMEPLAY] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.GAMEPLAY.StartObjective", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[GAMEPLAY] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.GAMEPLAY.StartObjective", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.GAMEPLAY.StartObjective", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[GAMEPLAY] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.GAMEPLAY.StartObjective` as the canonical routing key end-to-end.
@@ -0,0 +1,24 @@
---
id: hooks-library-index
title: Hooks Library
description: Generated per-hook documentation for the full greg.* hook inventory from greg_hooks.json.
---
This section contains one page per discovered `greg.*` hook.
## Source and scope
- **Primary source:** `gregCore/gregFramework/greg_hooks.json`
- **Layer:** Core SDK hook registry surface consumed by mods
- **Coverage:** Full generated hook inventory (broader than EventIds-only native bridge mappings)
Use this library when you need hook-specific behavior and payload usage examples.
## Related canonical docs
- [greg hooks catalog & events runtime](/wiki/reference/greg-hooks-catalog)
- [greg hook naming](/wiki/reference/fmf-hook-naming)
## Navigation
Use the **Hooks Library** section in the left docs sidebar to browse by domain (`CONTENT`, `NETWORK`, `SYSTEM`, `UI`, etc.) and open individual generated hook pages.
@@ -0,0 +1,24 @@
---
title: greg.Input.ActionTriggered
sidebar_label: ActionTriggered
description: "gregCore Hook — Normalized Unity signal for an input action being triggered."
---
# `greg.Input.ActionTriggered`
## Description
- Normalized Unity signal for an input action being triggered.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Input.ActionTriggered", payload =>
{
// Handle input action triggered event
});
```
@@ -0,0 +1,24 @@
---
title: greg.Input.BindingApplied
sidebar_label: BindingApplied
description: "gregCore Hook — Normalized Unity signal for an input binding being applied."
---
# `greg.Input.BindingApplied`
## Description
- Normalized Unity signal for an input binding being applied.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Input.BindingApplied", payload =>
{
// Handle input binding applied event
});
```
@@ -0,0 +1,24 @@
---
title: greg.Input.BindingStarted
sidebar_label: BindingStarted
description: "gregCore Hook — Normalized Unity signal for an input binding process starting."
---
# `greg.Input.BindingStarted`
## Description
- Normalized Unity signal for an input binding process starting.
## How to use this hook
### C# Snippet (using `gregSdk`)
```csharp
using gregSdk;
GregEventDispatcher.On("greg.Input.BindingStarted", payload =>
{
// Handle input binding started event
});
```
@@ -0,0 +1,121 @@
---
title: greg.NETWORK.AssignNewPosition
sidebar_label: AssignNewPosition
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: CablePositions.AssignNewPosition"
---
# `greg.NETWORK.AssignNewPosition`
## Description
- Auto-generated from Il2Cpp unpack: CablePositions.AssignNewPosition
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.CablePositions::AssignNewPosition(int, Transform, bool, bool, CableLink.TypeOfLink, string)` | Postfix | Auto-generated from Il2Cpp unpack: CablePositions.AssignNewPosition |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.NETWORK.AssignNewPosition`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.NETWORK.AssignNewPosition", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.NETWORK.AssignNewPosition`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.NETWORK.AssignNewPosition", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.NETWORK.AssignNewPosition", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.NETWORK.AssignNewPosition", |payload| {
if let Some(method) = payload.get("method") {
println!("[NETWORK] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.NETWORK.AssignNewPosition", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[NETWORK] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.NETWORK.AssignNewPosition", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.NETWORK.AssignNewPosition", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[NETWORK] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.NETWORK.AssignNewPosition` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.NETWORK.BrokenServerAdded
sidebar_label: BrokenServerAdded
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: NetworkMap.AddBrokenServer"
---
# `greg.NETWORK.BrokenServerAdded`
## Description
- Auto-generated from Il2Cpp unpack: NetworkMap.AddBrokenServer
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.NetworkMap::AddBrokenServer(Server)` | Postfix | Auto-generated from Il2Cpp unpack: NetworkMap.AddBrokenServer |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.NETWORK.BrokenServerAdded`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.NETWORK.BrokenServerAdded", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.NETWORK.BrokenServerAdded`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.NETWORK.BrokenServerAdded", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.NETWORK.BrokenServerAdded", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.NETWORK.BrokenServerAdded", |payload| {
if let Some(method) = payload.get("method") {
println!("[NETWORK] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.NETWORK.BrokenServerAdded", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[NETWORK] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.NETWORK.BrokenServerAdded", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.NETWORK.BrokenServerAdded", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[NETWORK] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.NETWORK.BrokenServerAdded` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.NETWORK.BrokenServerRemoved
sidebar_label: BrokenServerRemoved
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: NetworkMap.RemoveBrokenServer"
---
# `greg.NETWORK.BrokenServerRemoved`
## Description
- Auto-generated from Il2Cpp unpack: NetworkMap.RemoveBrokenServer
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.NetworkMap::RemoveBrokenServer(string)` | Postfix | Auto-generated from Il2Cpp unpack: NetworkMap.RemoveBrokenServer |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.NETWORK.BrokenServerRemoved`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.NETWORK.BrokenServerRemoved", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.NETWORK.BrokenServerRemoved`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.NETWORK.BrokenServerRemoved", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.NETWORK.BrokenServerRemoved", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.NETWORK.BrokenServerRemoved", |payload| {
if let Some(method) = payload.get("method") {
println!("[NETWORK] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.NETWORK.BrokenServerRemoved", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[NETWORK] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.NETWORK.BrokenServerRemoved", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.NETWORK.BrokenServerRemoved", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[NETWORK] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.NETWORK.BrokenServerRemoved` as the canonical routing key end-to-end.
@@ -0,0 +1,28 @@
---
title: greg.NETWORK.BrokenSwitchAdded
sidebar_label: BrokenSwitchAdded
description: Canonical event hook for greg.NETWORK.BrokenSwitchAdded (Normalized Unity Signal).
---
# greg.NETWORK.BrokenSwitchAdded
This hook is triggered during the $fullHook event lifecycle. It is part of the normalized gregCore event pipeline.
## Payload Contract (GregSignalPayload)
- SourceAsm: Assembly name
- SourceType: Type name
- SourceMethod: Method name
- EntityId: Contextual ID of the affected entity
- TimestampUtc: Time of the event
## Example
````csharp
using gregSdk;
gregEventDispatcher.On(gregNativeEventHooks.NetworkBrokenSwitchAdded, payload => {
var entityId = gregPayload.Get<string>(payload, "EntityId");
MelonLoader.MelonLogger.Msg($"Event greg.NETWORK.BrokenSwitchAdded triggered for {entityId}");
});
```
@@ -0,0 +1,121 @@
---
title: greg.NETWORK.ButtonShowNetworkSwitchConfig
sidebar_label: ButtonShowNetworkSwitchConfig
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: NetworkSwitch.ButtonShowNetworkSwitchConfig"
---
# `greg.NETWORK.ButtonShowNetworkSwitchConfig`
## Description
- Auto-generated from Il2Cpp unpack: NetworkSwitch.ButtonShowNetworkSwitchConfig
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.NetworkSwitch::ButtonShowNetworkSwitchConfig()` | Postfix | Auto-generated from Il2Cpp unpack: NetworkSwitch.ButtonShowNetworkSwitchConfig |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.NETWORK.ButtonShowNetworkSwitchConfig`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.NETWORK.ButtonShowNetworkSwitchConfig", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.NETWORK.ButtonShowNetworkSwitchConfig`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.NETWORK.ButtonShowNetworkSwitchConfig", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.NETWORK.ButtonShowNetworkSwitchConfig", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.NETWORK.ButtonShowNetworkSwitchConfig", |payload| {
if let Some(method) = payload.get("method") {
println!("[NETWORK] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.NETWORK.ButtonShowNetworkSwitchConfig", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[NETWORK] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.NETWORK.ButtonShowNetworkSwitchConfig", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.NETWORK.ButtonShowNetworkSwitchConfig", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[NETWORK] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.NETWORK.ButtonShowNetworkSwitchConfig` as the canonical routing key end-to-end.
@@ -0,0 +1,121 @@
---
title: greg.NETWORK.CableConnectionRemoved
sidebar_label: CableConnectionRemoved
description: "gregCore Hook — Auto-generated from Il2Cpp unpack: NetworkMap.RemoveCableConnection"
---
# `greg.NETWORK.CableConnectionRemoved`
## Description
- Auto-generated from Il2Cpp unpack: NetworkMap.RemoveCableConnection
## Patch Targets (Il2Cpp)
This hook name can be mapped to **1** Harmony target(s):
| Patch Target | Strategy | Description |
|------------|-----------|--------------|
| `Il2Cpp.NetworkMap::RemoveCableConnection(int)` | Postfix | Auto-generated from Il2Cpp unpack: NetworkMap.RemoveCableConnection |
**Strategy:** Postfix — The catalog says **Postfix** → typically use `HookBinder.OnAfter(...)`.
## Payload Schema (from Registry)
| Field | Type / Note |
|------|----------------|
| `method` | `string` |
## How to use this hook
### 1. Harmony Pipeline: `HookBinder` (Main path for `greg_hooks.json`)
The framework code patches Il2Cpp methods and calls `HookBinder.DispatchBefore` / `DispatchAfter`. You register handlers with the **exact** string `greg.NETWORK.CableConnectionRemoved`:
```csharp
using gregSdk;
// For Postfix strategy (common):
HookBinder.OnAfter("greg.NETWORK.CableConnectionRemoved", ctx =>
{
// ctx.HookName, ctx.Method, ctx.Instance, ctx.Arguments, ctx.ReturnValue
});
```
Prerequisites:
- A hook **catalog** / alias file has been loaded (e.g., `HookBinder.LoadAliases(path)` or `Hooker.InstallFromCatalog(...)`), so the Il2Cpp signature is mapped to the canonical string `greg.NETWORK.CableConnectionRemoved`.
- Namespace `gregSdk`, type `HookContext` (includes `Arguments`, `Instance`, `ReturnValue`, etc.).
### 2. Object Bus: `GregEventDispatcher` (Rust / FFI / manual emits)
Some names in the form ``greg.<Domain>.<Action>`` are additionally fired from the core via `GregHookIntegration` / `GregEventDispatcher.Emit` (numeric `EventIds` → String). If your hook is only defined in `greg_hooks.json` as an Il2Cpp patch, **HookBinder** is the correct entry point; use `GregEventDispatcher` if you want to explicitly listen to the payload bus:
```csharp
using gregSdk;
GregEventDispatcher.On("greg.NETWORK.CableConnectionRemoved", payload =>
{
// depending on the payload type; helpers: GregPayload.Get<T>(payload, "field", fallback)
});
```
Unregister: `GregEventDispatcher.Off("greg.NETWORK.CableConnectionRemoved", handler)` (same delegate reference as for `On`).
## See also
- [Overview of all greg hooks](/wiki/02_development/hooks-library)
- Source: `gregCore/gregFramework/greg_hooks.json`
## Usage in Rust
If your Rust bridge exposes the event bus, subscribe to the exact hook name:
~~~rust
use greg_framework::events::EventBus;
fn register_hooks(bus: &mut EventBus) {
bus.on("greg.NETWORK.CableConnectionRemoved", |payload| {
if let Some(method) = payload.get("method") {
println!("[NETWORK] method={}", method);
}
});
}
~~~
> If your current Rust runtime only exposes numeric EventIds, map those IDs to canonical `greg.*` names in your bridge layer before dispatching to mod code.
## Usage in Lua
Use the Lua bridge and register against the same canonical hook string:
~~~lua
greg.on("greg.NETWORK.CableConnectionRemoved", function(payload)
local method = payload and payload.method or "unknown"
greg.log("[NETWORK] method=" .. tostring(method))
end)
~~~
For Harmony-level interception use:
~~~lua
greg.hook.after("greg.NETWORK.CableConnectionRemoved", function(ctx)
greg.log("after hook: " .. tostring(ctx.method_name))
end)
~~~
## Usage in TypeScript
In a TS/JS bridge, subscribe via your event client using the same hook key:
~~~ts
import { gregBus } from './gregBus';
gregBus.on("greg.NETWORK.CableConnectionRemoved", (payload) => {
const method = payload?.method ?? 'unknown';
console.log("[NETWORK] method=" + method);
});
~~~
When using RPC/WebSocket transport, keep `greg.NETWORK.CableConnectionRemoved` as the canonical routing key end-to-end.

Some files were not shown because too many files have changed in this diff Show More