@classic-mp/types
v1.9.0
Published
TypeScript types for the ccmp JavaScript scripting API (server and client).
Downloads
862
Maintainers
Readme
ccmp-types
TypeScript declarations for the CCMP JavaScript scripting API.
Install this package as a development dependency in server scripts, client
scripts, or standalone CEF UI bundles to get autocomplete and tsc checking
for the runtime-provided globalThis.ccmp object.
This package is declaration-only. Do not import runtime values from it; use
import type when you need named TypeScript types.
The package is published publicly on npm. The source repository is private, so package consumers do not need repository access to install or use these types.
Install
npm install -D @classic-mp/typesSubpath Exports
| Subpath | Use it for | Provides |
| --- | --- | --- |
| @classic-mp/types/server | Server-side scripts | ccmp server global, players, entities, world state, server events |
| @classic-mp/types/client | Client-side scripts | ccmp client global, players, browsers, cameras, local peds, GTA natives |
| @classic-mp/types/ui | CEF/browser UI bundles | Minimal UI bridge global exposed as ccmp and window.ccmp |
| @classic-mp/types/natives | Advanced native typing | Standalone GTA V native interfaces |
Use either /server or /client in one script project, not both. They both
declare the same global name (ccmp) with different shapes.
Server Scripts
Add the server subpath to compilerOptions.types:
// tsconfig.json
{
"compilerOptions": {
"types": ["@classic-mp/types/server"],
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true
},
"include": ["**/*.ts", "**/*.js", "**/*.d.ts"]
}The runtime provides ccmp globally, so regular scripts do not need an import.
ccmp.world.weather = 'EXTRASUNNY';
ccmp.world.hour = 12;
ccmp.on('playerConnected', (player) => {
player.teleport(90.79, -1951.33, 20.74, 307.23);
player.giveWeapon(ccmp.hash('WEAPON_PISTOL'), 200);
const vehicle = ccmp.vehicles.create(
ccmp.hash('adder'),
94.5,
-1940.2,
20.7,
307.0,
{
primaryColor: 27,
secondaryColor: 111,
numberPlate: 'CCMP',
engineOn: true
}
);
if (vehicle) {
vehicle.dirtLevel = 0;
vehicle.lockState = 1;
vehicle.setStreamSyncedMeta('ownerId', player.id);
player.putIntoVehicle(vehicle.id, -1);
}
const guard = ccmp.peds.create(
ccmp.hash('s_m_y_cop_01'),
98.0,
-1944.0,
20.7,
180.0,
{
health: 250,
maxHealth: 250,
armour: 100,
frozen: true,
weapon: { hash: ccmp.hash('WEAPON_CARBINERIFLE'), ammo: 90 },
dimension: player.dimension
}
);
if (guard) {
guard.accuracy = 65;
guard.visible = true;
}
});
ccmp.on('playerDisconnected', (player) => {
console.log(`${player.name} (${player.id}) disconnected`);
});Available server managers:
ccmp.players: connected players.ccmp.vehicles,ccmp.objects,ccmp.peds: server-spawned world entities.ccmp.markers,ccmp.blips,ccmp.checkpoints,ccmp.colshapes: world helpers and trigger volumes.ccmp.world: authoritative weather and clock state.
Most server-created entities expose id, isExists, mutable world properties,
dimension, destroy(), and stream-synced meta helpers.
Server-spawned vehicles, peds, markers, blips, and checkpoints use server-authoritative setters for their supported gameplay and visual properties. Updates are synchronized live to clients currently streaming the entity and included in future stream-in snapshots.
Ped setters cover model/position/heading/health/armour plus visibility, physics flags, alpha, max health, accuracy and one authoritative equipped weapon.
const zone = ccmp.colshapes.createSphere(100, -1900, 21, 3, {
dimension: 0
});
ccmp.on('playerEnterColshape', (player, colshape) => {
if (!colshape || colshape.id !== zone?.id) return;
player.emit('hud:toast', {
text: 'You entered the garage.'
});
});Client Scripts
Add the client subpath to compilerOptions.types:
// tsconfig.json
{
"compilerOptions": {
"types": ["@classic-mp/types/client"],
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true
},
"include": ["**/*.ts", "**/*.js", "**/*.d.ts"]
}The client API includes player state, CEF browsers, cameras, local-only peds,
connection control, cursor control, nametags, GTA natives, notifications, and
read-only access to stream-synced entity meta.
The client runtime also provides numeric setTimeout/setInterval timer IDs.
const browser = ccmp.browsers.create('package://ui/index.html');
ccmp.on('keyUp', (key) => {
if (key === 0x50) {
ccmp.notify('P pressed');
browser.executeJavaScript('window.dispatchEvent(new Event("ccmp:p"))');
}
});
ccmp.on('render', () => {
// Per-frame client work, such as native HUD drawing.
});
const hideHintTimer: number = setTimeout(() => {
ccmp.notify('Hint expired');
}, 5000);
clearTimeout(hideHintTimer);
ccmp.on('chatMessage', (message) => {
console.log(`[chat] ${message.authorName}: ${message.text}`);
});
ccmp.on('streamSyncedMetaChange', (change) => {
if (
change.entityType === ccmp.entities.ENTITY_TYPE.Vehicle &&
change.key === 'ownerId'
) {
console.log(`Vehicle ${change.entityId} owner changed`, change.newValue);
}
});
const local = ccmp.players.local;
if (local) {
const faction = local.getStreamSyncedMeta<string>('faction');
console.log('Local faction:', faction);
}Client-only helpers are typed too:
const camera = ccmp.cameras.create(
'garage-preview',
{ x: 100, y: -1900, z: 24 },
{ x: -15, y: 0, z: 140 },
60
);
camera.setActive(true);
ccmp.cameras.renderScriptCams(true, true, 500);
const ped = ccmp.peds.create(
'a_m_m_business_01',
{ x: 102, y: -1902, z: 21 },
180,
{ dimension: 0 }
);
ccmp.cursor.show();
ccmp.nametags.enabled = false;CEF UI Bundles
Use the UI subpath for browser-side code that talks to the client script.
// tsconfig.json
{
"compilerOptions": {
"types": ["@classic-mp/types/ui"],
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"noEmit": true,
"lib": ["ES2022", "DOM"]
},
"include": ["src/**/*"]
}ccmp.emitClient('ui:ready', {
at: Date.now()
});
ccmp.emitServer('garage:buyVehicle', {
model: 'adder'
});
const off = ccmp.on('hud:update', (data) => {
console.log('HUD update from client script:', data);
});
off();Typing Custom Events
Built-in events are typed out of the box. Project-specific events are typed
through declaration merging in a .d.ts file that is included by your
tsconfig.json.
Server-side declaration:
// src/ccmp-events.d.ts
import '@classic-mp/types/server';
declare module '@classic-mp/types/server' {
interface CcmpServerEvents {
teleportRequest: {
x: number;
y: number;
z: number;
heading?: number;
};
}
interface CcmpClientInboundEvents {
'hud:toast': {
text: string;
};
}
}ccmp.on('teleportRequest', (player, data) => {
player.teleport(data.x, data.y, data.z, data.heading);
player.emit('hud:toast', { text: 'Teleported.' });
});Client-side declaration:
// src/ccmp-events.d.ts
import '@classic-mp/types/client';
declare module '@classic-mp/types/client' {
interface CcmpClientEvents {
'hud:toast': {
text: string;
};
'ui:ready': {
at: number;
};
}
interface CcmpServerInboundEvents {
teleportRequest: {
x: number;
y: number;
z: number;
heading?: number;
};
}
}ccmp.on('hud:toast', (payload) => {
ccmp.notify(payload.text);
});
ccmp.emitServer('teleportRequest', {
x: 90.79,
y: -1951.33,
z: 20.74
});UI-side declaration:
// src/ccmp-events.d.ts
import '@classic-mp/types/ui';
declare module '@classic-mp/types/ui' {
interface CcmpClientInboundEvents {
'ui:ready': {
at: number;
};
}
interface CcmpServerInboundEvents {
'garage:buyVehicle': {
model: string;
};
}
}Stream-Synced Meta
Server entities that implement StreamSyncedMeta can store JSON-compatible
values that are automatically replicated to clients currently streaming the
entity and included in future stream-in snapshots.
vehicle.setStreamSyncedMeta('locked', true);
vehicle.setStreamSyncedMeta('fuel', 42.5);
const fuel = vehicle.getStreamSyncedMeta<number>('fuel');
vehicle.deleteStreamSyncedMeta('locked');Clients observe this data read-only:
function isVehicleLocked(vehicleId: number): boolean {
return (
ccmp.entities.getStreamSyncedMeta<boolean>(
ccmp.entities.ENTITY_TYPE.Vehicle,
vehicleId,
'locked'
) ?? false
);
}
ccmp.on('streamSyncedMetaChange', (change) => {
console.log(change.entityType, change.entityId, change.key, change.newValue);
});Checking Your Project
npx tsc --noEmit -p tsconfig.jsonRun TypeScript in your script or UI project after adding the relevant subpath to
compilerOptions.types.
Versioning
@classic-mp/[email protected] tracks CCMP runtime API compatibility by
major/minor version. Patch releases fix declaration bugs without requiring
runtime API changes.
Maintainers
The source repository is private. Maintainers can validate declaration changes locally before release:
npm run checkReleases are published to npm as @classic-mp/types.
License
MIT
