Skip to content

Commit

Permalink
Update some code examples to modern standards (#126)
Browse files Browse the repository at this point in the history
- `Entity<TComp>`
- Use the methods on AppearanceSystem.SetData instead of obsolete
AppearanceComponent methods.
- Add previously undefined `FooVisualData` in ECS example. Code actually
compiles now.
- Fix some minor formatting mistakes.
  • Loading branch information
0x6273 authored Jan 6, 2024
1 parent e4e29c4 commit 702db60
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 45 deletions.
40 changes: 22 additions & 18 deletions src/en/robust-toolbox/ecs.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ Systems can also have public methods that other entity systems can call, and the
// Other Entity Systems can interact with FooComponent using the public API here.
public sealed class FooSystem : EntitySystem
{
[Dependency] protected readonly SharedAppearanceSystem _appearanceSystem = default!;

// Always subscribe to events here, on initialize
public override void Initialize()
{
Expand All @@ -172,66 +174,62 @@ public sealed class FooSystem : EntitySystem
}

// This is called when a FooComponent is initialized.
private void OnFooInit(EntityUid uid, FooComponent foo, ComponentInit _)
private void OnFooInit(Entity<FooComponent> ent, ref ComponentInit _)
{
// Initialize your FooComponent here
}

// Example handler for when FooComponent is interacted with by an user.
private void Handle(EntityUid uid, FooComponent foo, InteractUsingEvent args)
private void Handle(Entity<FooComponent> ent, ref InteractUsingEvent args)
{
// Increase interact counter by one
// We call this method as it handles everything for us.
SetInteractCounter(uid, foo, foo.InteractCounter + 1);
SetInteractCounter((ent, ent.Comp), ent.Comp.InteractCounter + 1);
}

// This is called whenever an entity moves.
private void OnEntityMove(MoveEvent ev)
private void OnEntityMove(ref MoveEvent ev)
{
// Do something here! Although we do nothing because this is an example...
}

// Public method that other systems can call to interact with FooComponent
public void ResetInteractCounter(EntityUid uid, FooComponent? foo = null)
public void ResetInteractCounter(Entity<FooComponent?> ent)
{
// Try to resolve the component...
if(!Resolve(uid, ref foo))
return;

// We just call our other method, which handles everything for us.
SetInteractCounter(uid, 0, foo);
SetInteractCounter(ent, 0);
}

// Public method that other systems can call to interact with FooComponent
public void SetInteractCounter(EntityUid uid, int count, FooComponent? foo = null)
public void SetInteractCounter(Entity<FooComponent?> ent, int count)
{
// Try to resolve the component...
if(!Resolve(uid, ref foo))
if (!Resolve(ent, ref ent.Comp))
return;

// Store the old counter, for later...
var oldCounter = foo.InteractCounter;
var oldCounter = ent.Comp.InteractCounter;

// Set the new interact counter
foo.InteractCounter = count;
ent.Comp.InteractCounter = count;

// Now we set some appearance data, if the entity has an appearance comp
if(TryComp(uid, out AppearanceComponent? appear))
appear.SetData(FooVisualData.InteractCounter, count);
if (TryComp(ent, out AppearanceComponent? appearance))
_appearanceSystem.SetData(ent, FooVisualData.InteractCounter, count, appearance);

// Now, we raise an event to let everyone know InteractCounter changed
// Because the third argument is false, this event will not be broadcast.
// This is raised as a directed event only!
RaiseLocalEvent(uid, new FooInteractCounterChangedEvent(oldCounter, foo.InteractCounter));
RaiseLocalEvent(ent, new FooInteractCounterChangedEvent(oldCounter, ent.Comp.InteractCounter));
}

}

[RegisterComponent]
public sealed partial class FooComponent : Component
{
// This will be increased every time an user interacts with us.
// Notice how the logic for this is not in this component, but in the system.
[DataField]
public int InteractCounter = 0;
}

Expand All @@ -249,6 +247,12 @@ public sealed class FooInteractCounterChangedEvent : EntityEventArgs
NewCounter = newCounter;
}
}

[Serializable, NetSerializable]
public enum FooVisualData
{
InteractCounter,
}
```

### Creation and use
Expand Down
6 changes: 3 additions & 3 deletions src/en/space-station-14/device-network.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ public override void Initialize()
}
...
private void OnPacketReceived(EntityUid uid, DeviceNetworkComponent component, DeviceNetworkPacketEvent args)
private void OnPacketReceived(Entity<DeviceNetworkComponent> ent, ref DeviceNetworkPacketEvent args)
{
//Since we are doing it the recommended way of using the command constant we try to get it from the payload
if (args.Data.TryGetValue(DeviceNetworkConstants.COMMAND, out String command))
Expand All @@ -373,8 +373,8 @@ private void OnPacketReceived(EntityUid uid, DeviceNetworkComponent component, D
};
//And send the response to that ping
_deviceNetworkSystem.QueuePacket(uid, args.SenderAddress, payload, args.Frequency);
_deviceNetworkSystem.QueuePacket(ent, args.SenderAddress, payload, args.Frequency);
}
}
}
```
```
6 changes: 3 additions & 3 deletions src/en/ss14-by-example/adding-a-simple-bikehorn.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public sealed class PlaySoundOnUseSystem : EntitySystem
SubscribeLocalEvent<PlaySoundOnUseComponent, UseInHandEvent>(OnUseInHand);
}
private void OnUseInHand(EntityUid uid, PlaySoundOnUseComponent component, UseInHandEvent args)
private void OnUseInHand(Entity<PlaySoundOnUseComponent> ent, ref UseInHandEvent args)
{
}
Expand All @@ -291,9 +291,9 @@ We're almost there. Now, the method `OnUseInHand` will be called when we activat
Also, we've added `[Dependency] private readonly SharedAudioSystem` to class. It will allow us to play audio in modern way (instead of using obsolete `SoundSystem.Play`) further.

```csharp
private void OnUseInHand(EntityUid uid, PlaySoundOnUseComponent component, UseInHandEvent args)
private void OnUseInHand(Entity<PlaySoundOnUseComponent> ent, ref UseInHandEvent args)
{
_audio.PlayPvs(component.Sound, uid);
_audio.PlayPvs(ent.Comp.Sound, uid);
}
```

Expand Down
20 changes: 11 additions & 9 deletions src/en/ss14-by-example/basic-networking-and-you.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ Let's see how this state is constructed on the server:
...

// In the event handlers..
private void GetCompState(EntityUid uid, AmbientSoundComponent component, ref ComponentGetState args)
private void GetCompState(Entity<AmbientSoundComponent> ent, ref ComponentGetState args)
{
args.State = new AmbientSoundComponentState
{
Enabled = component.Enabled,
Range = component.Range,
Volume = component.Volume,
Enabled = ent.Comp.Enabled,
Range = ent.Comp.Range,
Volume = ent.Comp.Volume,
};
}
```
Expand All @@ -102,12 +102,14 @@ And on the client (technically still in shared, but this code is only run on the
/// SharedAmbientSoundSystem.cs
...

private void HandleCompState(EntityUid uid, AmbientSoundComponent component, ref ComponentHandleState args)
private void HandleCompState(Entity<AmbientSoundComponent> ent, ref ComponentHandleState args)
{
if (args.Current is not AmbientSoundComponentState state) return;
component.Enabled = state.Enabled;
component.Range = state.Range;
component.Volume = state.Volume;
if (args.Current is not AmbientSoundComponentState state)
return;

ent.Comp.Enabled = state.Enabled;
ent.Comp.Range = state.Range;
ent.Comp.Volume = state.Volume;
}
```

Expand Down
16 changes: 7 additions & 9 deletions src/en/ss14-by-example/making-a-sprite-dynamic.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,13 @@ Data is sent and received using the `AppearanceComponent`, specifically the func
Here's a really simple server-side setting of appearance data, in `ItemCabinetSystem`:

```csharp=
private void UpdateAppearance(EntityUid uid,
ItemCabinetComponent? cabinet = null,
AppearanceComponent? appearance = null)
private void UpdateAppearance(Entity<ItemCabinetComponent?, AppearanceComponent?> ent)
{
if (!Resolve(uid, ref cabinet, ref appearance, false))
if (!Resolve(ent, ref ent.Comp1, ref ref ent.Comp2, logMissing: false))
return;
appearance.SetData(ItemCabinetVisuals.IsOpen, cabinet.Opened);
appearance.SetData(ItemCabinetVisuals.ContainsItem, cabinet.CabinetSlot.HasItem);
_appearanceSystem.SetData(ent, ItemCabinetVisuals.IsOpen, ent.Comp1.Opened, ent.Comp2);
_appearanceSystem.SetData(ent, ItemCabinetVisuals.ContainsItem, ent.Comp1.CabinetSlot.HasItem, ent.Comp2);
}
```

Expand All @@ -47,9 +45,9 @@ Let's look at the client-side `ItemCabinetSystem` to see how it retrieves and us
```csharp=
public sealed class ItemCabinetSystem : VisualizerSystem<ItemCabinetVisualsComponent>
{
protected override void OnAppearanceChange(EntityUid uid, ItemCabinetVisualsComponent component, ref AppearanceChangeEvent args)
protected override void OnAppearanceChange(Entity<ItemCabinetVisualsComponent> ent, ref AppearanceChangeEvent args)
{
if (TryComp(uid, out SpriteComponent? sprite)
if (TryComp(ent, out SpriteComponent? sprite)
&& args.Component.TryGetData(ItemCabinetVisuals.IsOpen, out bool isOpen)
&& args.Component.TryGetData(ItemCabinetVisuals.ContainsItem, out bool contains))
{
Expand Down Expand Up @@ -149,4 +147,4 @@ Layers can be mapped to enum keys. This means that any sprite operations (set vi

## Animations

TODO
TODO
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,14 @@ This doesn't use `InitializeEntity` but if it did the full class would look like
SubscribeLocalEvent<ItemCabinetVisualsComponent, ComponentInit>(OnComponentInit);
}

private void OnComponentInit(EntityUid uid, ItemCabinetVisualsComponent component, ComponentInit args)
private void OnComponentInit(Entity<ItemCabinetVisualsComponent> ent, ref ComponentInit args)
{
// behavior!
}
}

protected override void OnChangeData(EntityUid uid, ItemCabinetVisualsComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite != null)
if (args.Sprite != null
&& component.TryGetData(ItemCabinetVisuals.IsOpen, out bool isOpen)
&& component.TryGetData(ItemCabinetVisuals.ContainsItem, out bool contains))
{
Expand Down

0 comments on commit 702db60

Please sign in to comment.