diff --git a/YabosRageMPCore.sql b/YabosRageMPCore.sql new file mode 100644 index 0000000..4f21bb4 --- /dev/null +++ b/YabosRageMPCore.sql @@ -0,0 +1,68 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.2 +-- https://www.phpmyadmin.net/ +-- +-- Host: dns.burnednodes.ge +-- Generation Time: Apr 01, 2026 at 03:48 AM +-- Server version: 10.6.22-MariaDB-0ubuntu0.22.04.1 +-- PHP Version: 8.4.18 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `YabosRageMPCore` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users` +-- + +CREATE TABLE `users` ( + `id` int(11) NOT NULL, + `email` varchar(255) NOT NULL, + `password` varchar(255) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `name` varchar(24) NOT NULL DEFAULT '', + `lastname` varchar(24) NOT NULL DEFAULT '', + `hardwareid` varchar(128) DEFAULT '', + `ip` varchar(64) DEFAULT '', + `adminLvl` int(11) DEFAULT 0, + `social` varchar(128) DEFAULT '', + `socialid` varchar(128) DEFAULT '' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `users` +-- +ALTER TABLE `users` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `email` (`email`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `users` +-- +ALTER TABLE `users` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/develop_cef/src/App.vue b/develop_cef/src/App.vue index 8152d81..4f945ba 100644 --- a/develop_cef/src/App.vue +++ b/develop_cef/src/App.vue @@ -1,13 +1,29 @@ diff --git a/develop_client/src/index.ts b/develop_client/src/index.ts index 705c458..14575f5 100644 --- a/develop_client/src/index.ts +++ b/develop_client/src/index.ts @@ -2,8 +2,12 @@ import { Rpc } from '@entityseven/rage-fw-rpc'; const rpc = new Rpc(); let browser: BrowserMp | null = null; +let cursorVisible = true; +let adminLevel = 0; +let noclipActive = false; +let noclipCamera: CameraMp | null = null; -// Initialize CEF via standard RAGE MP event to bootstrap the browser for RPC +// Initialize CEF via standard RAGE MP event mp.events.add('client:initCef', (cefUrl: string, isDebug: boolean) => { if (isDebug) { mp.gui.chat.push(`[Client] Initializing CEF: ${cefUrl}`); @@ -15,37 +19,190 @@ mp.events.add('client:initCef', (cefUrl: string, isDebug: boolean) => { } browser = mp.browsers.new(cefUrl); - rpc.browser = browser; // Link immediately + rpc.browser = browser; - mp.gui.chat.push(`[Client] Browser created and linked to RPC`); + mp.gui.chat.show(false); mp.gui.cursor.show(true, true); + cursorVisible = true; + + mp.players.local.freezePosition(true); }); -// Fallback: auto-link any newly created browser if current is null +// Fallback: auto-link browser mp.events.add('browserCreated', (b: BrowserMp) => { if (!rpc.browser) { rpc.browser = b; - mp.gui.chat.push(`[Client] RPC Browser auto-linked via browserCreated`); } - mp.gui.chat.show(false); }); -// Custom Chat Handlers via RPC -rpc.register('chat:toggleInput', (state: boolean) => { - // This allows you to freeze other inputs while typing if you build a UI manager later +// ─────────────── Keybinds ─────────────────── + +// Backtick (`) — toggle cursor +mp.keys.bind(0xC0, true, () => { + cursorVisible = !cursorVisible; + mp.gui.cursor.show(cursorVisible, cursorVisible); }); +// F2 — toggle admin noclip +mp.keys.bind(0x71, true, async () => { + if (adminLevel <= 0) return; + + try { + const result: any = await rpc.callServer('server:admin:noclip', []); + if (!result || !result.allowed) return; + + noclipActive = result.active; + + if (noclipActive) { + enableNoclip(); + } else { + disableNoclip(); + } + } catch (err) { + // silently fail + } +}); + +// ─────────────── Noclip Logic ─────────────── + +let isNoClip = false; +let noClipPos: Vector3Mp | null = null; + +function enableNoclip() { + isNoClip = true; + noClipPos = mp.players.local.position; + + mp.players.local.freezePosition(true); + mp.players.local.setInvincible(true); + mp.players.local.setVisible(false, false); + mp.players.local.setCollision(false, false); + + mp.gui.cursor.show(false, false); + cursorVisible = false; +} + +function disableNoclip() { + isNoClip = false; + + if (noClipPos) { + mp.players.local.setCoordsNoOffset(noClipPos.x, noClipPos.y, noClipPos.z, false, false, false); + noClipPos = null; + } + + mp.players.local.freezePosition(false); + mp.players.local.setInvincible(false); + mp.players.local.setVisible(true, false); + mp.players.local.setCollision(true, false); +} + +// Math helpers +function getCamDirection() { + const rot = mp.game.cam.getGameplayCamRot(2); + const z = rot.z * (Math.PI / 180.0); + const x = rot.x * (Math.PI / 180.0); + const num = Math.abs(Math.cos(x)); + + return new mp.Vector3( + -Math.sin(z) * num, + Math.cos(z) * num, + Math.sin(x) + ); +} + +mp.events.add('render', () => { + if (!isNoClip || !noClipPos) return; + + // Fast movement using Shift + let speed = 1.0; + if (mp.keys.isDown(0x10)) speed = 3.0; // Shift + if (mp.keys.isDown(0x11)) speed = 0.2; // Ctrl + + // We do NOT disable controls — we let the user look around natively + // But we override position manually. + + const dir = getCamDirection(); + + // W = Forward + if (mp.keys.isDown(0x57)) { + noClipPos.x += dir.x * speed; + noClipPos.y += dir.y * speed; + noClipPos.z += dir.z * speed; + } + // S = Backward + if (mp.keys.isDown(0x53)) { + noClipPos.x -= dir.x * speed; + noClipPos.y -= dir.y * speed; + noClipPos.z -= dir.z * speed; + } + + // A = Left + if (mp.keys.isDown(0x41)) { + noClipPos.x += dir.y * speed; + noClipPos.y -= dir.x * speed; + } + // D = Right + if (mp.keys.isDown(0x44)) { + noClipPos.x -= dir.y * speed; + noClipPos.y += dir.x * speed; + } + // Space = Up + if (mp.keys.isDown(0x20)) { + noClipPos.z += speed; + } + + // We use direct position assignment instead of setCoordsNoOffset + // Function calls to natives in a render loop cause massive FPS drops on low-end hardware + // because they force physics recalculations. Assignment skips some hooks. + mp.players.local.position = noClipPos; +}); + +// ─────────────── Auth Handlers ────────────── + +rpc.register('auth:login', (email: string, password: string) => { + return rpc.callServer('server:auth:login', [email, password]); +}); + +rpc.register('auth:register', (email: string, password: string, firstName: string, lastName: string) => { + return rpc.callServer('server:auth:register', [email, password, firstName, lastName]); +}); + +rpc.register('client:authSuccess', (rpName: string, level: number) => { + adminLevel = level || 0; + + mp.players.local.freezePosition(false); + mp.gui.cursor.show(false, false); + cursorVisible = false; + + rpc.callBrowser('app:showGame', []).catch(() => {}); +}); + +// Save credentials to RAGE:MP local storage +rpc.register('client:saveCredentials', (email: string, password: string) => { + mp.storage.data.auth = { email, password }; + mp.storage.flush(); +}); + +// Load saved credentials from RAGE:MP local storage +rpc.register('client:loadCredentials', () => { + const auth = mp.storage.data.auth; + if (auth && auth.email) { + return { email: auth.email, password: auth.password || '' }; + } + return null; +}); + +// ─────────────── Chat Handlers ────────────── + +rpc.register('chat:toggleInput', (state: boolean) => {}); + rpc.register('chat:sendMessage', (msg: string) => { - // Send the message natively to the server via our RPC rpc.callServer('server:chat:receive', [msg]); }); -// Listen for structured chat broadcasts from the server (Player chat) rpc.register('chat:push:custom', (chatData: any) => { rpc.callBrowser('chat:addMessage', [chatData]); }); -// Listen for incoming native string messages from the server (System prints/announcements) mp.events.add('chat:push', (text: string) => { rpc.callBrowser('chat:addMessage', [{ type: 'system', text: text }]); });