Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
_site/**

api/**
!api/index.md
!api/index.md

.vscode/
14 changes: 0 additions & 14 deletions .vscode/launch.json

This file was deleted.

7 changes: 0 additions & 7 deletions .vscode/settings.json

This file was deleted.

13 changes: 0 additions & 13 deletions .vscode/tasks.json

This file was deleted.

12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ All documentation is written in Markdown in the `docs/` folder. For Markdown syn

```
docs/
├── index.md # Home page
├── getting-started.md # Getting started guide
├── core-concepts/
│ ├── toc.yml # Core concepts table of contents
├── index.md # Home page (redirects to quick-start)
├── quick-start.md # Quick Start guide
├── getting-started.md # Redirect stub for legacy URL
├── core-concepts/ # ECS pages (linked directly from root TOC)
│ ├── index.md # Entity-Component-System overview
│ └── ...
├── features/
│ ├── toc.yml # Features table of contents
├── features/ # Feature pages (linked directly from root TOC)
│ └── ...
├── reference/
│ ├── toc.yml # Reference table of contents
Expand Down
10 changes: 10 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": "0.2",
"words": [
"blockquotes",
"frontmatter",
"gamemode",
"sampsharp",
"textdraw"
]
}
20 changes: 10 additions & 10 deletions docs/core-concepts/entities-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,21 @@ entityManager.AddComponent<BankAccount>(childId, parentId);

- Destroying a parent entity will recursively destroy all its children and their components.

### Entity Hierarchy Example
### Example: round-scoped entities

Below is a diagram showing entities, their nested structure, and attached components:
A common use case for entity hierarchies is **lifetime grouping**: tie a set of transient entities to a single parent, then destroy the parent to clean them all up at once. All `IWorldService.Create*` methods accept an optional `parent` parameter for exactly this.

For example, a deathmatch round that spawns weapon pickups and a control zone can parent everything to a `Round` entity. Destroying that entity at the end of the round removes the pickups and gang zone in one call:

```mermaid
graph TD
A(Root Entity) --> B[Player]
A --> C[BankAccount]
A --> E[Inventory]
A --> D(Child Entity)
D --> F[Vehicle]
D --> I[IgnitionLock]
A --> G(Another Child Entity)
G --> H[QuestStatus]
R(Round Entity) --> RC[Round]
R --> P1(Pickup Entity)
P1 --> P1C[Pickup]
R --> P2(Pickup Entity)
P2 --> P2C[Pickup]
R --> GZ(GangZone Entity)
GZ --> GZC[GangZone]
```

## Destroying Entities and Components
Expand Down
100 changes: 25 additions & 75 deletions docs/core-concepts/index.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,40 @@
---
title: Entity-Component-System
uid: core-concepts
uid: ecs-overview
---

# Core Concepts
# Entity-Component-System

## Entity-Component-System (ECS)
SampSharp is built on the **Entity-Component-System** (ECS) architecture. Every gamemode you write organizes its logic into three concepts:

SampSharp is built on the **Entity-Component-System** (ECS) architecture, a powerful design pattern that separates data from logic and provides a flexible, scalable approach to building game modes. This chapter explains the fundamental concepts you need to understand to work effectively with SampSharp.
- **Entities** — unique identifiers for things in the game world (a player, a vehicle, a custom item).
- **Components** — data attached to entities (a `Player`'s `Position`, a `BankAccount` you defined).
- **Systems** — logic that operates on entities by reading their components and responding to events.

### What is ECS?
Rather than deep class inheritance, ECS uses **composition**: you build complex entities by attaching whichever components they need.

The Entity-Component-System is an architectural pattern that organizes game objects and their behavior through three key concepts:
## How the pieces fit together

1. **Entities** - the objects in your game world
2. **Components** - the data that describes those objects
3. **Systems** - the logic that operates on the data
```mermaid
graph LR
E[Entity] -->|has| C[Components]
C -->|read / mutated by| S[System]
Ev[Event] -->|triggers| S
```

Rather than using traditional object-oriented inheritance (where a "Player" class inherits from a "Character" class which inherits from a "GameObject"), ECS uses **composition**: you create a base entity and attach components to it to define what it is and what it can do.
When events arrive, the dispatcher passes the relevant components from the involved entities into your system methods — you do not query for components directly.

### Entities
### Example: a player picks up an item

An **entity** is a unique identifier representing something in your game world. It could be a player, a vehicle, a building, an item, or any other object.
1. open.mp fires a pickup event.
2. A system receives the `Player` and `Pickup` components.
3. The system updates the player's inventory based on the pickup data.
4. The system removes the pickup entity.

In SampSharp, entities are extremely lightweight—they're essentially just containers. An entity only has meaning when components are attached to it; an entity without components doesn't exist or serve any purpose in the system.
### Example: a player exits a vehicle

**Key characteristics:**
- Each entity has a unique ID
- Entities only exist when they have at least one component
- Multiple entities can exist simultaneously
- Entities can be created and destroyed dynamically
1. open.mp fires a vehicle exit event.
2. A system receives the `Player` and `Vehicle` components.
3. The system calculates a fare based on distance traveled and gives money to the player.
4. The system logs the ride for statistics.

> For more information on entities, see <xref:entities-components>.

### Components

A **component** is a container that holds data and functionality related to a specific aspect of an entity. Components are the "nouns" of your system—they describe what properties and capabilities an entity has.

Unlike traditional object-oriented design where you might create a deep inheritance hierarchy (Player → Character → GameObject), ECS uses composition: you create an entity and attach whatever components it needs. This makes it easy to create complex entities by combining simpler pieces.

**Key characteristics:**
- Components hold data and related methods
- An entity can have any combination of components
- You can add or remove components from entities dynamically
- Components can be queried to find entities with specific combinations
- Different components can work together to create complex behaviors

> For more information about components, see <xref:entities-components>.

### Systems

A **system** is the logic layer of ECS. Systems read data from components and perform operations based on that data. A system typically operates on entities that have a specific set of components.

Systems are responsible for implementing all the game logic—they query for entities with the components they care about, then perform operations on that data.

**Key characteristics:**
- Systems contain all the business logic for a particular behavior
- Systems query for entities with specific component combinations
- Systems operate on data without owning it
- Systems are independent and can run in any order
- Logic is decoupled from data storage

> For more information about systems, see <xref:systems>.

### Events

In SampSharp, **events** are notifications that occur when something happens in the open.mp server (like a player connecting, a player request class, or game mode initialization). Systems can handle these events by implementing methods decorated with the `[Event]` attribute.

When an event fires, SampSharp automatically calls your handler method and passes the relevant entity components and services as parameters, allowing your system to react to world changes.

> For more information about events, see <xref:events>.

### How It Works Together

Here's how ECS operates in practice with SampSharp:

**Example - handling a pickup event:**
1. A player picks up an item in the world
2. open.mp fires a pickup event
3. A system receives the event with the `Player` and `Pickup` components
4. The system updates the player's inventory based on the pickup data
5. The system removes the pickup entity

**Example - handling a vehicle event:**
1. A player exits a vehicle
2. open.mp fires a vehicle exit event
3. A system receives the event with the `Player` and `Vehicle` components
4. The system calculates a fare based on distance traveled and gives money to the player
5. The system logs the ride for statistics
6 changes: 3 additions & 3 deletions docs/core-concepts/systems.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ uid: systems

# Systems

In SampSharp's Entity-Component-System (ECS) architecture, **systems** are classes that contain the logic for your game mode. Systems process entities and their components, respond to events, and can handle player or console commands. They are the main way to organize your server's behavior, keeping your code modular and maintainable.
In SampSharp's Entity-Component-System (ECS) architecture, **systems** are classes that contain the logic for your gamemode. Systems process entities and their components, respond to events, and can handle player or console commands. They are the main way to organize your server's behavior, keeping your code modular and maintainable.

For a high-level overview of ECS and systems, see <xref:core-concepts>.
For a high-level overview of ECS and systems, see <xref:ecs-overview>.


## How to Create a System
Expand Down Expand Up @@ -48,7 +48,7 @@ public class MyFirstSystem : ISystem
[Event]
public void OnGameModeInit(IWorldService world, IEntityManager entityManager)
{
// Called when the game mode starts.
// Called when the gamemode starts.
var vehicle = world.CreateVehicle(VehicleModelType.Landstalker, new Vector3(0, 6, 15), 45, 4, 4);
vehicle.SetNumberPlate("SampSharp");
}
Expand Down
5 changes: 0 additions & 5 deletions docs/core-concepts/toc.yml

This file was deleted.

8 changes: 4 additions & 4 deletions docs/features/dialog-menus.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Inject `IDialogService` into any event handler or system method and call `Show`
public class MySystem : ISystem
{
[Event]
public void OnPlayerSpawn(Player player, IDialogService dialogs)
public void OnPlayerConnect(Player player, IDialogService dialogs)
{
var dialog = new MessageDialog(
caption: "Welcome",
Expand All @@ -53,7 +53,7 @@ public class MySystem : ISystem

```csharp
[Event]
public async Task OnPlayerSpawn(Player player, IDialogService dialogs)
public async Task OnPlayerConnect(Player player, IDialogService dialogs)
{
var dialog = new MessageDialog("Welcome", "Press OK to continue.", "OK");
var response = await dialogs.ShowAsync(player, dialog);
Expand Down Expand Up @@ -272,7 +272,7 @@ Because `ShowAsync` returns a `Task`, you can chain multiple dialogs in a single

```csharp
[Event]
public async Task OnPlayerSpawn(Player player, IDialogService dialogs)
public async Task OnPlayerConnect(Player player, IDialogService dialogs)
{
var rules = new MessageDialog("Rules", "Do you accept the rules?", "Yes", "No");
var rulesResponse = await dialogs.ShowAsync(player, rules);
Expand Down Expand Up @@ -402,7 +402,7 @@ public class MenuEventSystem : ISystem
```

> [!TIP]
> `OnPlayerSelectedMenuRow` fires globally — it is not scoped to a specific menu instance. When your game mode shows different menus to the same player, attach a custom [component](xref:entities-components) to the player that records which menu is currently visible, and read it in the event handler to dispatch the row to the right code.
> `OnPlayerSelectedMenuRow` fires globally — it is not scoped to a specific menu instance. When your gamemode shows different menus to the same player, attach a custom [component](xref:entities-components) to the player that records which menu is currently visible, and read it in the event handler to dispatch the row to the right code.

### Disabling rows

Expand Down
4 changes: 2 additions & 2 deletions docs/features/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Objects are static or dynamic entities in the world that can be created, positio

## Creating Objects

To create a global object visible to all players, use <xref:SampSharp.Entities.SAMP.IWorldService.CreateObject>:
To create a global object visible to all players, use <xref:SampSharp.Entities.SAMP.IWorldService.CreateObject*>:

```csharp
[Event]
Expand All @@ -30,7 +30,7 @@ See <xref:SampSharp.Entities.SAMP.IWorldService> for all available parameters.

## Player Objects

Player objects are only visible to a specific player, making them useful for personalized or player-specific world elements. Create player objects using <xref:SampSharp.Entities.SAMP.IWorldService.CreatePlayerObject>:
Player objects are only visible to a specific player, making them useful for personalized or player-specific world elements. Create player objects using <xref:SampSharp.Entities.SAMP.IWorldService.CreatePlayerObject*>:

```csharp
[Event]
Expand Down
7 changes: 0 additions & 7 deletions docs/features/toc.yml

This file was deleted.

Loading
Loading