chore: initial import of gregWiki
@@ -0,0 +1,9 @@
|
||||
node_modules
|
||||
dist
|
||||
.astro
|
||||
.git
|
||||
.github
|
||||
.vscode
|
||||
npm-debug.log
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
@@ -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;"]
|
||||
@@ -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.
|
||||
@@ -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()],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
wiki:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- "8080:80"
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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 |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 2.1 MiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 104 KiB |
@@ -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 |
@@ -0,0 +1,3 @@
|
||||
(function () {
|
||||
// Locale redirects intentionally disabled.
|
||||
})();
|
||||
@@ -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);
|
||||
}
|
||||
})();
|
||||
@@ -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 |
@@ -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;
|
||||
@@ -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'],
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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} />;
|
||||
}
|
||||
@@ -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.
|
||||
|
||||