issun-bevy 0.10.0

ISSUN plugins for Bevy ECS
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# Plugin Macro Integration Design

**Date**: 2025-11-27
**Status**: Implemented
**Scope**: IssunBevyPlugin Derive Macro

---

## ๐Ÿ“‹ Overview

The IssunBevyPlugin macro provides declarative plugin configuration for Bevy-based ISSUN plugins. It automates boilerplate code generation including resource registration, type registration, event/system setup, dependency validation, and builder pattern implementation.

### Core Capabilities

1. **Resource Management**: Automatic resource registration with Clone requirement
2. **Type Registration**: Reflection support for serialization and inspection
3. **Event Integration**: Message/event auto-registration
4. **Component Registration**: Component type registration for Reflection
5. **System Registration**: Startup and Update system auto-registration
6. **Dependency Validation**: Runtime plugin dependency checking
7. **Builder Pattern**: Fluent configuration API generation

---

## ๐ŸŽฏ Design Goals

### Primary Objectives

**Boilerplate Reduction**
- Eliminate repetitive `Plugin::build()` implementations
- Auto-generate common patterns (resource registration, builder methods)
- Reduce code size: ~10-20 lines saved per plugin

**Declarative Configuration**
- Express plugin structure through attributes
- Self-documenting code (attributes as specification)
- Separation of concerns (what vs how)

**Consistency Enforcement**
- Uniform plugin structure across codebase
- Naming conventions automatically applied
- Pattern compliance through code generation

**Developer Experience**
- Clear compile-time errors
- Helpful runtime error messages
- IDE autocomplete for builder methods

---

## ๐Ÿ—๏ธ Architecture

### Macro Expansion Flow

```
User Code (Plugin Struct)
         โ†“
  [IssunBevyPlugin Macro]
         โ†“
   Parse Attributes
   - #[plugin(...)]
   - #[config], #[resource], #[skip]
         โ†“
   Generate Components
   - Marker Resource
   - Dependency Checks
   - Resource Registration
   - Type Registration
   - Event/System Registration
   - Builder Methods
         โ†“
   Output: impl Plugin + impl PluginStruct
```

### Generated Code Structure

```rust
// Input (User Code)
#[derive(Default, IssunBevyPlugin)]
#[plugin(
    name = "action",
    requires = [TimePlugin],
    messages = [ActionConsumed],
    components = [ActionPoints],
    startup_systems = [setup_actions],
    update_systems = [tick_actions]
)]
pub struct ActionPlugin {
    #[resource]
    pub config: ActionConfig,
}

// Output (Generated)
#[derive(Resource)]
pub struct ActionPluginMarker;

impl Plugin for ActionPlugin {
    fn build(&self, app: &mut App) {
        // 1. Dependency checks
        assert!(app.world().contains_resource::<TimePluginMarker>(), ...);

        // 2. Marker registration
        app.insert_resource(ActionPluginMarker);

        // 3. Resource registration
        app.insert_resource(self.config.clone());

        // 4. Event registration
        app.add_event::<ActionConsumed>();

        // 5. Component registration
        app.register_type::<ActionPoints>();

        // 6. System registration
        app.add_systems(Startup, (setup_actions));
        app.add_systems(Update, (tick_actions));
    }
}

impl ActionPlugin {
    pub fn with_config(mut self, config: ActionConfig) -> Self {
        self.config = config;
        self
    }
}
```

---

## ๐Ÿ—‚๏ธ Feature Specifications

### 1. Resource Registration

**Attributes**: `#[config]`, `#[resource]`

**Semantics**:
- Fields marked with `#[config]` or `#[resource]` are auto-registered
- Generates `app.insert_resource(self.field.clone())`
- **Clone Requirement**: All resource fields must implement `Clone`
- Rationale: `Plugin::build(&self, app)` takes `&self`, requiring cloning

**Builder Methods**:
- Auto-generates `with_{field_name}(value) -> Self` for each resource field
- Enables fluent configuration: `Plugin::default().with_config(...)`

### 2. Type Registration (Reflection)

**Attribute**: `auto_register_types = true`

**Semantics**:
- Registers resource field types for Bevy's Reflection system
- Generates `app.register_type::<FieldType>()` for each resource
- Enables serialization, inspection, and dynamic access
- Optional feature (opt-in)

### 3. Event Registration

**Attribute**: `messages = [EventType1, EventType2, ...]`

**Semantics**:
- Registers event/message types with Bevy's event system
- Generates `app.add_event::<EventType>()` for each type
- Types must implement `Message` trait (Bevy 0.17+) or `Event` (Bevy 0.15-)

### 4. Component Registration

**Attribute**: `components = [ComponentType1, ComponentType2, ...]`

**Semantics**:
- Registers component types for Reflection
- Generates `app.register_type::<ComponentType>()` for each type
- Separate from resource types (components are not plugin fields)
- Enables serialization and dynamic component access

### 5. System Registration

**Attributes**:
- `startup_systems = [fn1, fn2, ...]`
- `update_systems = [fn1, fn2, ...]`

**Semantics**:
- Registers systems to specific schedules
- Startup: `app.add_systems(Startup, (fn1, fn2))`
- Update: `app.add_systems(Update, (fn1, fn2))`
- Systems are added as a tuple (parallel execution)

**Design Choice**: No SystemSet support
- Rationale: Complex syntax, limited benefit, users can manually add via extension point
- Extension point: Additional systems can be added in `Plugin::build()` manually

### 6. Dependency Validation

**Attributes**:
- `requires = [Plugin1, Plugin2, ...]`
- `requires_bevy = [BevyPlugin1, ...]`
- `auto_require_core = true` (default)

**Semantics**:
- `requires`: ISSUN plugin dependencies (runtime validated via Marker Resources)
- `requires_bevy`: Bevy standard plugin dependencies (documentation only)
- `auto_require_core`: Auto-require IssunCorePlugin (opt-out via `false`)

**Marker Resource Pattern**:
- Each plugin generates a zero-size Marker Resource: `{PluginName}Marker`
- Marker is registered in `Plugin::build()`
- Dependencies are validated by checking `contains_resource::<Marker>()`

**Validation Timing**: Plugin::build() entry point (fail-fast)

**Error Messages**:
```
ActionPlugin requires TimePlugin. Add it before ActionPlugin:
app.add_plugins(TimePlugin::default());
app.add_plugins(ActionPlugin::default());
```

---

## ๐Ÿ“ Technical Specifications

### Attribute Syntax

```rust
#[plugin(
    name = "plugin_name",                    // Optional: custom name
    auto_register_types = true,              // Optional: enable Reflection
    messages = [Type1, Type2],               // Optional: event types
    components = [Type1, Type2],             // Optional: component types
    startup_systems = [fn1, fn2],            // Optional: startup systems
    update_systems = [fn1, fn2],             // Optional: update systems
    requires = [Plugin1, Plugin2],           // Optional: ISSUN dependencies
    requires_bevy = [BevyPlugin1],           // Optional: Bevy dependencies
    auto_require_core = true                 // Optional: default true
)]
```

### Field Attributes

```rust
#[config]     // Config resource (insert + builder method)
#[resource]   // Resource (insert + builder method)
#[skip]       // Skip this field (no auto-generation)
```

### Naming Conventions

- **Plugin Name**: Default is `to_snake_case(StructName)` (e.g., `ActionPlugin` โ†’ `"action_plugin"`)
- **Builder Methods**: `with_{field_name}`
- **Marker Resources**: `{StructName}Marker`

### Code Generation Order

```rust
impl Plugin for PluginStruct {
    fn build(&self, app: &mut App) {
        // 1. Dependency checks (requires)
        #dependency_checks

        // 2. Marker registration
        app.insert_resource(PluginStructMarker);

        // 3. Resource registration (fields)
        #resource_registrations

        // 4. Type registration (auto_register_types)
        #type_registrations

        // 5. Event registration (messages)
        #message_registrations

        // 6. Component registration (components)
        #component_registrations

        // 7. System registration (startup/update)
        #startup_systems
        #update_systems

        // 8. Extension point (user can add more here)
    }
}
```

---

## ๐ŸŽจ Design Patterns

### Pattern 1: Declarative Resource Registration

**Intent**: Express plugin resources as struct fields, auto-generate registration

**Implementation**:
- Fields with `#[config]` or `#[resource]` โ†’ automatic registration
- Clone-based insertion (required by `&self` in `Plugin::build`)

**Benefits**:
- Resources are co-located with plugin definition
- Type safety: resources are typed struct fields
- Discoverability: IDE shows all resources as fields

### Pattern 2: Marker Resource for Detection

**Intent**: Detect plugin presence at runtime via zero-cost marker

**Implementation**:
- Auto-generate `{PluginName}Marker` struct
- Register in `Plugin::build()`
- Check via `contains_resource::<Marker>()`

**Benefits**:
- Zero runtime overhead (zero-size type)
- Type-safe detection (no string-based checks)
- Consistent naming convention

### Pattern 3: Fail-Fast Validation

**Intent**: Detect dependency issues immediately, not deep in execution

**Implementation**:
- Dependency checks at `Plugin::build()` entry
- `assert!` macro for immediate panic
- Helpful error messages with fix suggestions

**Benefits**:
- Early problem detection
- Clear error messages
- Self-documenting dependencies

### Pattern 4: Builder Pattern Generation

**Intent**: Fluent configuration API without manual implementation

**Implementation**:
- Auto-generate `with_{field_name}` methods
- Return `Self` for chaining
- Extract doc comments from field attributes

**Benefits**:
- Consistent API across plugins
- No boilerplate builder code
- Chainable configuration

### Pattern 5: Extension Point

**Intent**: Balance automation with flexibility

**Implementation**:
- Generated code handles common cases
- User can add custom logic in `Plugin::build()` after auto-generated code
- Comment marker indicates extension point

**Benefits**:
- Common patterns automated
- Edge cases handled manually
- Clear separation of concerns

---

## ๐Ÿ”ง Implementation Constraints

### Constraint 1: Clone Requirement

**Rule**: All `#[config]` and `#[resource]` fields must implement `Clone`

**Rationale**: `Plugin::build(&self, app)` has `&self` signature, requiring clone to insert resources

**Enforcement**: Compile-time error if Clone not implemented

**Documentation**: Explicit requirement in macro documentation

### Constraint 2: Proc Macro Limitations

**Limitation**: Cannot access other crate information during macro expansion

**Impact**:
- Dependency validation is runtime (not compile-time)
- Cannot auto-generate topologically sorted plugin list
- Cannot detect circular dependencies at compile time

**Mitigation**: Runtime checks with clear error messages

### Constraint 3: Naming Convention Dependency

**Assumption**: Plugins follow `{Name}Plugin` naming convention

**Impact**: Marker resource naming relies on this pattern

**Enforcement**: Not enforced, but documented as best practice

---

## ๐Ÿงช Testing Coverage

### Test Categories

**T1: Basic Resource Registration**
- Resource fields are correctly registered
- Builder methods work as expected
- Skip attribute is respected

**T2: Type Registration (Reflection)**
- Types are registered in AppTypeRegistry when enabled
- Can be retrieved via reflection API

**T3: Event Registration**
- Events are registered and can be sent/received
- Multiple event types are supported

**T4: Component Registration**
- Components are registered for Reflection
- Can be dynamically accessed

**T5: System Registration**
- Startup systems run on Startup schedule
- Update systems run on Update schedule

**T6: Dependency Validation**
- Missing dependencies cause panic with helpful message
- Dependency order is enforced
- auto_require_core works correctly

**T7: Builder Pattern**
- Builder methods enable fluent configuration
- Values are correctly set

---

## ๐Ÿ’ก Best Practices

### For Plugin Authors

1. **Follow Naming Conventions**: Use `{Name}Plugin` pattern for consistency
2. **Implement Clone**: All resource fields must implement Clone
3. **Declare Dependencies**: Use `requires` for explicit dependency declaration
4. **Document Bevy Dependencies**: Use `requires_bevy` for standard plugin requirements
5. **Use Extension Point**: Add custom logic in `Plugin::build()` after generated code
6. **Keep Resources Simple**: Avoid complex Clone implementations

### For Plugin Users

1. **Respect Dependency Order**: Add plugins in topological order
2. **Start with IssunCorePlugin**: Add it first unless `auto_require_core = false`
3. **Read Error Messages**: Panic messages include fix suggestions
4. **Use Builder Methods**: Prefer `Plugin::default().with_config(...)` over direct field access

---

## ๐ŸŽ“ Lessons Learned

### What Works Well

1. **Declarative Attributes**: Clear, self-documenting plugin structure
2. **Automatic Code Generation**: Eliminates ~10-20 lines of boilerplate per plugin
3. **Marker Resource Pattern**: Simple, zero-cost dependency detection
4. **Builder Pattern**: Fluent API without manual implementation
5. **Extension Point**: Balances automation with flexibility

### Design Trade-offs

| Aspect | Choice | Alternative | Rationale |
|--------|--------|-------------|-----------|
| Resource Cloning | Required | Reference counting | Simplicity, Bevy API constraint |
| Dependency Validation | Runtime | Compile-time | Proc macro limitation |
| Default Core Requirement | Opt-out | Opt-in | Most plugins need IssunCorePlugin |
| SystemSet Support | Not included | Full support | Complexity vs benefit |
| Builder Pattern | Auto-generated | Manual | Consistency and DX |

### Known Limitations

1. **Compile-Time Dependency Graph**: Not feasible with current proc macro capabilities
2. **Circular Dependency Detection**: Only detected at runtime (potential infinite loop)
3. **Bevy Plugin Validation**: `requires_bevy` is documentation-only (no runtime check)
4. **Clone Performance**: Large resources may have cloning overhead

---

## ๐Ÿ”ฎ Future Considerations

### Potential Enhancements

**Feature: Advanced SystemSet Support**
- Syntax: `systems(schedule, set) = [...]`
- Challenge: Complex syntax, user-defined SystemSet types
- Decision: Deferred (users can manually add via extension point)

**Feature: Compile-Time Dependency Graph**
- Idea: Validate dependencies at compile time
- Challenge: Proc macro cannot access other crate information
- Decision: Not feasible with current Rust proc macro capabilities

**Feature: Automatic Topological Sorting**
- Idea: Auto-reorder plugins based on dependencies
- Challenge: Requires modifying user code (App::new() chain)
- Decision: Too invasive, current manual ordering is acceptable

**Feature: Bevy Plugin Detection**
- Idea: Runtime validation for `requires_bevy`
- Challenge: No consistent detection mechanism for Bevy plugins
- Decision: Keep as documentation-only, revisit if Bevy adds plugin markers

---

## ๐Ÿ“š References

### Bevy Documentation

- **Plugin Trait**: `bevy::app::Plugin`
- **Resource System**: `bevy::ecs::system::Resource`
- **Reflection**: `bevy::reflect::Reflect`
- **Event System**: `bevy::ecs::event::Event` / `bevy::ecs::event::Message`

### Rust Language

- **Procedural Macros**: The Rust Programming Language - Chapter 19.5
- **Derive Macros**: `proc_macro_derive` attribute
- **Quote Crate**: Code generation utilities

---

**Document Version**: 1.0
**Last Updated**: 2025-11-27
**Scope**: IssunBevyPlugin Macro (Complete Feature Set)