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
127 changes: 127 additions & 0 deletions .agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
name: DocWorker
description: Write and improve SampSharp feature documentation articles following DocFX and xref best practices
---

# DocWorker Agent

You are an expert technical writer specializing in SampSharp documentation. Your role is to write new feature documentation articles and review/improve existing ones, ensuring they are clear, accurate, and follow all SampSharp documentation standards.

## Core Responsibilities

- Write conceptual documentation articles explaining **what** and **why**, not just showing code
- Create concise, focused examples that illustrate key concepts
- Ensure all articles follow DocFX Markdown formatting and xref conventions
- Review and improve existing articles for clarity, accuracy, and consistency
- Maintain structural consistency across all documentation

## Documentation Standards

### YAML Frontmatter

Every article must have a unique `uid`:

```yaml
---
title: Article Title
uid: article-unique-id
---
```

### Cross-References (xref)

- **Always** use the `<xref:uid>` syntax (preferred) for cross-references
- Example: `<xref:events>` or `<xref:SampSharp.Entities.SAMP.IWorldService>`
- Use markdown link text syntax `[Text](xref:uid)` only when custom text differs from the page title
- Never use relative links; always use xref for maintainability

### Code Examples

- **Inject services** directly into event handler parameters, not constructors
- **Combine examples** for clarity; avoid "show and tell" with separate code blocks
- Use the `[Event]` attribute for event handlers, never `[EventHandler]`
- Keep examples minimal and focused on the concept being explained
- For full lists of available items, refer to the appropriate article with xref

### DocFX Features

Use these DocFX Markdown features for rich documentation:

**Alerts** for important information:

```
> [!NOTE]
> Information the user should notice.

> [!IMPORTANT]
> Essential information.
```

**Code snippets** with language specification:

```
[!code-csharp[](file.cs#L1-L10)]
```

**Includes** for content reuse when appropriate

### Article Structure

- **No summary sections** at the end (not recommended for documentation)
- Start with a clear introduction explaining what the article covers
- Use numbered sections for logical flow
- Include API reference xref links where appropriate
- End with cross-references to related articles

## Key Patterns from SampSharp

When writing SampSharp articles, remember:

- **Services are injected into event parameters**, not stored as fields

```csharp
[Event]
public void OnGameModeInit(IWorldService worldService)
{
// Use service directly
}
```

- **Component types** are the main interaction points
- `Vehicle` component for vehicle manipulation
- `GlobalObject` component for world objects (named to avoid collision with System.Object)
- `Player` component for player interactions

- **Events drive gameplay** - explain available events and how to handle them
- Always reference <xref:events> for the full list
- Show realistic event handler examples

- **Entity creation** happens through IWorldService
- Demonstrate in the `OnGameModeInit` event handler
- Inject IWorldService as a parameter

## When to Use This Agent

Invoke this agent when:

- Writing new SampSharp feature documentation articles
- Reviewing and improving existing SampSharp documentation
- Ensuring documentation follows all DocFX and xref standards
- Need guidance on documentation structure and best practices for SampSharp

Use the default Copilot agent for general code questions or non-SampSharp tasks.

## Tool Preferences

**Preferred tools:**

- `read_file` - Review existing documentation structure
- `replace_string_in_file` / `multi_replace_string_in_file` - Edit documentation
- `file_search` - Find related articles for xref references
- `grep_search` - Search within specific files for context

**Avoid:**

- Source code references in documentation (use framework documentation instead)
- Linking to specific line numbers in source code
- Creating unnecessary summary sections
4 changes: 2 additions & 2 deletions docs/features/commands.md → docs/features/command-system.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
title: Implementing Commands
title: Command System
uid: commands
---

# Implementing Commands
# Command System

The SampSharp command system provides a declarative way to handle player and console commands through attributes. Commands are discovered automatically from <xref:SampSharp.Entities.ISystem> implementations and can include complex features like overloading, aliasing, command groups, and permission checking.

Expand Down
74 changes: 74 additions & 0 deletions docs/features/objects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: Objects
uid: objects
---

# Objects

Objects are static or dynamic entities in the world that can be created, positioned, and manipulated at runtime. SampSharp distinguishes between global objects (visible to all players) and player objects (visible only to a specific player).

## Creating Objects

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

```csharp
[Event]
public void OnGameModeInit(IWorldService worldService)
{
var obj = worldService.CreateObject(
modelId: 18631, // object model ID
position: new Vector3(100, 200, 30), // position
rotation: new Vector3(0, 0, 45), // rotation
drawDistance: 300 // draw distance
);
}
```

The returned component is of type <xref:SampSharp.Entities.SAMP.GlobalObject> (named as such because `Object` is reserved for `System.Object`).

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>:

```csharp
[Event]
public void OnPlayerSpawn(Player player, IWorldService worldService)
{
var playerObj = worldService.CreatePlayerObject(
player,
modelId: 18631,
position: new Vector3(100, 200, 30),
rotation: new Vector3(0, 0, 45)
);
}
```

Only the specified player can see and interact with this object.

## Handling Object Events

You can respond to object-related events, such as when an object is moved. For example:

```csharp
[Event]
public void OnObjectMoved(GlobalObject obj)
{
// Handle object movement
}
```

See <xref:events> for a full list of available object events.

## Manipulating Objects

The <xref:SampSharp.Entities.SAMP.GlobalObject> component provides properties and methods to interact with objects. You can change their position, rotation, and other properties:

```csharp
obj.Position = new Vector3(150, 250, 35); // Change position
obj.Rotation = new Vector3(0, 0, 90); // Change rotation
```

See <xref:SampSharp.Entities.SAMP.GlobalObject> for the full API.

123 changes: 109 additions & 14 deletions docs/features/timers.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,112 @@ uid: timers

# Timers and Scheduling

> [!NOTE]
> This article is coming soon! Check back later, or feel free to open an issue if you have questions.

<!--
TODO: Document timer functionality including:
- The TimerService for scheduling tasks
- One-time vs repeating timers
- Timer callbacks and handlers
- Canceling and managing timers
- Delay and interval configuration
- Timer lifecycle management
- Performance considerations for many timers
- Examples of common timer patterns
-->
Timers allow you to schedule tasks to execute at regular intervals or after a specific delay. SampSharp provides two approaches: the `[Timer]` attribute for simple repeating timers, and `ITimerService` for more advanced scenarios requiring manual control.

## Simple Timers with [Timer] Attribute

The simplest way to create a repeating timer is using the `[Timer]` attribute on a method in your system. Specify the interval in milliseconds:

```csharp
public class GameSystem : ISystem
{
[Timer(1000)] // Interval in milliseconds (1 second)
public void OnGameTick()
{
Console.WriteLine("Game tick!");
}

[Timer(100)] // 10 times per second
public void OnFastUpdate()
{
// High-frequency updates
}
}
```

The timer automatically starts when the system is initialized and runs at the specified interval. This approach is ideal for fire-and-forget timers without manual lifecycle management.

## Advanced Timer Control with ITimerService

For more complex scenarios, use `ITimerService` to have full control over timer creation, stopping, and lifecycle. Both `Start` and `Delay` return a `TimerReference` that you can use to cancel the timer:

```csharp
[Event]
public void OnGameModeInit(ITimerService timerService)
{
// Repeating timer: runs every 1 second
var repeatTimer = timerService.Start(serviceProvider =>
{
Console.WriteLine("Timer tick!");
}, TimeSpan.FromSeconds(1));

// One-time timer: runs once after 5 seconds
var delayTimer = timerService.Delay(serviceProvider =>
{
Console.WriteLine("Delayed action executed");
}, TimeSpan.FromSeconds(5));
}
```

### Canceling Timers

To stop a running timer, pass its `TimerReference` to `timerService.Stop()`:

```csharp
public class MySystem : ISystem
{
private TimerReference? _timer;

[Event]
public void OnGameModeInit(ITimerService timerService)
{
_timer = timerService.Start(serviceProvider =>
{
Console.WriteLine("Timer is running");
}, TimeSpan.FromSeconds(2));
}

public void StopTimer(ITimerService timerService)
{
if (_timer != null)
{
timerService.Stop(_timer);
_timer = null;
}
}
}
```

You can also check a timer's state using `TimerReference.IsActive` and `TimerReference.NextTick` to see when the next execution is scheduled.

### Accessing Services in Timer Actions

Timer actions receive an `IServiceProvider` parameter, allowing you to access services without storing them as fields:

```csharp
timerService.Start(serviceProvider =>
{
var worldService = serviceProvider.GetRequiredService<IWorldService>();
// Use worldService within the timer action
}, TimeSpan.FromSeconds(1));
```

This is useful for keeping timers self-contained without field dependencies.

### One-Time Delays

Use `Delay` for one-time scheduled tasks without keeping references:

```csharp
timerService.Delay(serviceProvider =>
{
Console.WriteLine("This runs once after a delay");
}, TimeSpan.FromSeconds(10));
```

## When to Use Each Approach

- **[Timer] attribute** — Simple, recurring timers with fixed intervals; fire-and-forget
- **ITimerService** — Manual control needed; dynamic intervals; one-time delays; conditional stopping

See <xref:SampSharp.Entities.ITimerService> for the complete API.
Loading
Loading