Skip to content

Commit aa0541a

Browse files
authored
Improve and update some codebase info (#25)
1 parent 010f5ac commit aa0541a

4 files changed

Lines changed: 81 additions & 30 deletions

File tree

src/SUMMARY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ General Development
3232
- [General programming](en/general-development/codebase-info/conventions/general.md)
3333
- [Project programming](en/general-development/codebase-info/conventions/project.md)
3434
- [ECS Conventions](en/general-development/codebase-info/conventions/ecs.md)
35-
- [Architecture](en/general-development/codebase-info/conventions/architecture.md)
35+
- [Architecture Conventions](en/general-development/codebase-info/conventions/architecture.md)
3636
- [Networking Conventions](en/general-development/codebase-info/conventions/networking.md)
3737
- [Resource Conventions](en/general-development/codebase-info/conventions/resources.md)
38-
- [Module Conventions](en/general-development/codebase-info/conventions/modules.md)
3938
- [Pull Request Guidelines](en/general-development/codebase-info/pull-request-guidelines.md)
4039
- [Codebase Organization](en/general-development/codebase-info/codebase-organization.md)
40+
- [Modules](en/general-development/codebase-info/modules.md)
4141
- [Goob Reforged](en/general-development/codebase-info/goob-reforged/goob-reforged.md)
4242
- [Reforged Modules](en/general-development/codebase-info/goob-reforged/reforged-modules.md)
4343
- [Feature Proposals](en/general-development/feature-proposals.md)

src/en/general-development/codebase-info/conventions/ecs.md

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,94 @@ When possible, try using the `EntitySystem` [proxy methods](https://github.com/s
6060
<summary>Examples (click to expand)</summary>
6161

6262
```csharp
63-
// Without proxy methods...
63+
// Without proxy methods - bad
6464
EntityManager.GetComponent<MetaDataComponent>(uid).EntityName;
6565

66-
// With proxy methods
66+
// With proxy methods - good
6767
Name(uid);
6868

69-
// Without proxy methods...
69+
// Without proxy methods - bad
7070
EntityManager.GetComponent<TransformComponent>(uid).Coordinates;
7171

72-
// With proxy methods
72+
// With proxy methods - good
7373
Transform(uid).Coordinates;
7474
```
7575

7676
</details>
7777

78+
### Update loops
79+
A lot of old code is accumulating frametime inside update loops to decide when to next run it.
80+
81+
Accumulator example (bad):
82+
```csharp
83+
public override void Update(float frameTime)
84+
{
85+
var query = EntityQueryEnumerator<UpdateLoopExampleComponent>();
86+
while (query.MoveNext(out var uid, out var comp))
87+
{
88+
comp.Accumulator += frameTime;
89+
90+
if (comp.Accumulator < UpdateInterval)
91+
continue;
92+
93+
comp.Accumulator -= UpdateInterval;
94+
95+
// Code here
96+
}
97+
```
98+
99+
This is bad because of those reasons:
100+
1. This makes the update loop impossible to synchronize between server and client, causing prediction and networking issues.
101+
2. This approach uses the `float` type, and it is not precise enough in case of update loops, so it may cause rounding issues when the game is launched for a long time.
102+
3. This constantly does the addition operation, which isn't bad on its own, but when there are hundreds of systems doing that the overhead can beocme noticeable.
103+
104+
All of the above problems can be fixed by using `TimeSpan` type and `IGameTiming`.
105+
106+
TimeSpan example (good):
107+
```csharp
108+
[Dependency] private readonly IGameTiming _timing = default!;
109+
110+
public override void Initialize()
111+
{
112+
SubscribeLocalEvent<UpdateLoopExampleComponent, MapInitEvent>(OnMapInit)
113+
}
114+
115+
private void OnMapInit(Entity<UpdateLoopExampleComponent> ent, ref MapInitEvent args)
116+
{
117+
// Set the first update time after the entity is spawned.
118+
// Without this it would update every single tick until NextUpdate catches up with the server time.
119+
ent.Comp.NextUpdate = _timing.CurTime + ent.Comp.UpdateInterval;
120+
Dirty(ent);
121+
}
122+
123+
public override void Update(float frameTime)
124+
{
125+
// CurTime is calculated so we do it only once outside the update loop instead of for every sigle entity.
126+
var curTime = _timing.Curtime;
127+
// Loop over all components, ignoring paused entities.
128+
var query = EntityQueryEnumerator<UpdateLoopExampleComponent>();
129+
while (query.MoveNext(out var uid, out var comp))
130+
{
131+
if (comp.NextUpdate < curTime)
132+
continue; // Not enough time has passed since the last update.
133+
134+
// Set the time for the next update.
135+
// Don't use
136+
// comp.NextUpdate = curTime + UpdateInterval;
137+
// because that eats the remainder with every update, causing the update loop to run slightly less often
138+
// than given by UpdateInterval, which will be imprecise and can cause problems over large time durations.
139+
comp.NextUpdate += UpdateInterval;
140+
141+
// Dirty the component so that the client can reroll the NextUpdate datafield during predcition.
142+
// Without this you will get mispredicts.
143+
Dirty(uid, comp);
144+
145+
// Do stuff here.
146+
}
147+
}
148+
```
149+
150+
78151
## Events
79152

80153
### Method Events vs Entity System Methods

src/en/general-development/codebase-info/goob-reforged/reforged-modules.md

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ flowchart TD
6262
style GoobShared stroke:#3498db
6363
GoobCommon[Content.Goobstation.Common]
6464
style GoobCommon stroke:#3498db
65-
66-
ModuleServer[Content.Modules.Server]
67-
style GoobShared stroke:#3498db
68-
ModuleClient[Content.Modules.Client]
69-
style GoobCommon stroke:#3498db
7065
7166
subgraph CoreModules["Core Modules"]
7267
CoreServer
@@ -97,8 +92,6 @@ flowchart TD
9792
CoreShared --> GoobShared
9893
CoreServer --> GoobServer
9994
CoreClient --> GoobClient
100-
GoobServer --> ModuleServer
101-
GoobClient --> ModuleClient
10295
```
10396

10497
This means:
@@ -137,8 +130,6 @@ flowchart TD
137130
style Lavaland stroke:#6b9bb3
138131
Utils[Utils]
139132
style Utils stroke:#6b9bb3
140-
Modules[".Modules projects (end)"]
141-
style Utils stroke:#6b9bb3
142133
143134
subgraph CustomModules["Custom Modules"]
144135
Goobstation
@@ -150,10 +141,6 @@ flowchart TD
150141
Core --> Goobstation
151142
Core --> Lavaland
152143
Core --> Utils
153-
154-
Goobstation --> Modules
155-
Lavaland --> Modules
156-
Utils --> Modules
157144
```
158145

159146
The only exception for that convention are **library modules** that provide some general tools or API for other modules to use.
@@ -174,8 +161,6 @@ flowchart TD
174161
style Lavaland stroke:#6b9bb3
175162
Utils[Utils]
176163
style Utils stroke:#6b9bb3
177-
Modules[".Modules projects (end)"]
178-
style Utils stroke:#6b9bb3
179164
180165
subgraph CustomModules["Custom Modules"]
181166
Goobstation
@@ -188,9 +173,6 @@ flowchart TD
188173
189174
Utils --> Goobstation
190175
Utils --> Lavaland
191-
192-
Goobstation --> Modules
193-
Lavaland --> Modules
194176
```
195177

196178
## Special module projects

src/en/general-development/codebase-info/conventions/modules.md renamed to src/en/general-development/codebase-info/modules.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
# Modules Conventions
2-
3-
```admonish warning "Attention: Placeholder!"
4-
This section is a placeholder, pending an updated guide to be written
5-
```
1+
# Modules
62

73
## What?
84

@@ -100,4 +96,4 @@ When building your project:
10096

10197
## Verification
10298

103-
If you've done everything correctly, Content.Client or Content.Server should load your custom module on startup, with everything registering and initializing properly.
99+
If you've done everything correctly, Content.Client or Content.Server should load your custom module on startup, with everything registering and initializing properly.

0 commit comments

Comments
 (0)