create-eigen-game 0.14.2 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +18 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/{src-B8zHulnO.js → src-u6yY0kJD.js} +2 -2
- package/dist/src-u6yY0kJD.js.map +1 -0
- package/package.json +9 -9
- package/src/index.ts +1 -1
- package/src/prompt.ts +16 -3
- package/templates/app-overlay/lib/game/v1/local_rules.dart.template +115 -0
- package/templates/app-overlay/lib/game/v1/rules.dart.template +6 -0
- package/templates/app-overlay/web/README.md +11 -0
- package/templates/app-overlay/web/drift_worker.js +13453 -0
- package/templates/app-overlay/web/eigen_offline_sw.js +82 -0
- package/templates/app-overlay/web/flutter_bootstrap.js.template +11 -0
- package/templates/app-overlay/web/sqlite3.wasm +0 -0
- package/templates/worker/game-contract.json +242 -0
- package/templates/worker/src/module/fixtures/v1/counter.json +179 -0
- package/templates/worker/src/module/fixtures/v1/rng.json +26 -0
- package/templates/worker/src/module/v1.ts +11 -4
- package/dist/src-B8zHulnO.js.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import 'package:eigen_flutter/eigen_flutter.dart';
|
|
2
|
+
|
|
3
|
+
import '../generated/payloads.dart';
|
|
4
|
+
|
|
5
|
+
/// The offline half of version 1: the same four hooks the Worker owns,
|
|
6
|
+
/// transcribed so the game can be played on the device with no network.
|
|
7
|
+
///
|
|
8
|
+
/// Entirely optional. Delete this file and the `local` override in
|
|
9
|
+
/// `rules.dart` and the game is unchanged, minus on-device play. What it buys
|
|
10
|
+
/// is a match a player can start on a train: the device commits every move
|
|
11
|
+
/// through these hooks, and the server replays the whole log through the
|
|
12
|
+
/// TypeScript unit when the device is next online, which is why the two must
|
|
13
|
+
/// agree move for move. The shared fixtures under `test/game/fixtures/` are
|
|
14
|
+
/// what keeps them agreeing.
|
|
15
|
+
///
|
|
16
|
+
/// Read it beside `server/src/module/v1.ts`; the hook and parameter names are
|
|
17
|
+
/// deliberately identical.
|
|
18
|
+
class ExampleGameLocalRulesV1 extends ExampleGameV1LocalRulesBase {
|
|
19
|
+
const ExampleGameLocalRulesV1();
|
|
20
|
+
|
|
21
|
+
@override
|
|
22
|
+
Envelope<ExampleGameV1State> initialState({
|
|
23
|
+
required ExampleGameV1Config config,
|
|
24
|
+
required Rng rng,
|
|
25
|
+
required int playerCount,
|
|
26
|
+
}) => Envelope(
|
|
27
|
+
state: ExampleGameV1State(count: 0),
|
|
28
|
+
pendingPlayers: const [0],
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
@override
|
|
32
|
+
Envelope<ExampleGameV1State> applyAction({
|
|
33
|
+
required ExampleGameV1State state,
|
|
34
|
+
required List<int> pending,
|
|
35
|
+
required ExampleGameV1Action data,
|
|
36
|
+
required int playerIndex,
|
|
37
|
+
required Rng rng,
|
|
38
|
+
required ExampleGameV1Config config,
|
|
39
|
+
}) {
|
|
40
|
+
final count = state.count + data.amount;
|
|
41
|
+
final finished = count >= config.target;
|
|
42
|
+
return Envelope(
|
|
43
|
+
state: ExampleGameV1State(count: count),
|
|
44
|
+
pendingPlayers: finished ? const [] : [1 - playerIndex],
|
|
45
|
+
outcome: finished ? _outcome(playerIndex) : null,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@override
|
|
50
|
+
Envelope<ExampleGameV1State> applyLifecycle({
|
|
51
|
+
required ExampleGameV1State state,
|
|
52
|
+
required List<int> pending,
|
|
53
|
+
required LifecycleType type,
|
|
54
|
+
required LifecycleAction data,
|
|
55
|
+
required Rng rng,
|
|
56
|
+
required ExampleGameV1Config config,
|
|
57
|
+
}) {
|
|
58
|
+
final loser = type == LifecycleType.timeout
|
|
59
|
+
? (pending.isEmpty ? 0 : pending.first)
|
|
60
|
+
: data.playerIndex!;
|
|
61
|
+
return Envelope(
|
|
62
|
+
state: state,
|
|
63
|
+
pendingPlayers: const [],
|
|
64
|
+
outcome: _outcome(1 - loser),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@override
|
|
69
|
+
ObservationSlice<ExampleGameV1Observation> computeObservation({
|
|
70
|
+
required ExampleGameV1State state,
|
|
71
|
+
required List<int> pending,
|
|
72
|
+
required int? playerIndex,
|
|
73
|
+
required int participantCount,
|
|
74
|
+
required TransitionCause<ExampleGameV1Action> cause,
|
|
75
|
+
required bool isReplay,
|
|
76
|
+
required ExampleGameV1Config config,
|
|
77
|
+
}) => ObservationSlice(
|
|
78
|
+
data: ExampleGameV1Observation(count: state.count),
|
|
79
|
+
pendingPlayers: pending,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
/// The brains this build can run, keyed by the bot registry's `username`.
|
|
83
|
+
///
|
|
84
|
+
/// An operator registers a row with this username and type `local`, and it
|
|
85
|
+
/// becomes an opponent in the solo picker's untimed mode. A username that
|
|
86
|
+
/// also has a TypeScript `botActions` entry is one bot playable both on the
|
|
87
|
+
/// device and on the server.
|
|
88
|
+
@override
|
|
89
|
+
Map<
|
|
90
|
+
String,
|
|
91
|
+
LocalBotAction<
|
|
92
|
+
ExampleGameV1Action,
|
|
93
|
+
ExampleGameV1Observation,
|
|
94
|
+
ExampleGameV1Config
|
|
95
|
+
>
|
|
96
|
+
>
|
|
97
|
+
get botActions => {
|
|
98
|
+
'example-bot': (args) => ExampleGameV1Action(amount: 1),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
List<Outcome> _outcome(int winner) => [
|
|
103
|
+
Outcome(
|
|
104
|
+
playerIndex: winner,
|
|
105
|
+
result: OutcomeResultEnum.win,
|
|
106
|
+
placement: 1,
|
|
107
|
+
teamIndex: winner,
|
|
108
|
+
),
|
|
109
|
+
Outcome(
|
|
110
|
+
playerIndex: 1 - winner,
|
|
111
|
+
result: OutcomeResultEnum.loss,
|
|
112
|
+
placement: 2,
|
|
113
|
+
teamIndex: 1 - winner,
|
|
114
|
+
),
|
|
115
|
+
];
|
|
@@ -2,6 +2,7 @@ import 'package:eigen_flutter/eigen_flutter.dart';
|
|
|
2
2
|
import 'package:flutter/material.dart';
|
|
3
3
|
|
|
4
4
|
import '../generated/payloads.dart';
|
|
5
|
+
import 'local_rules.dart';
|
|
5
6
|
|
|
6
7
|
class ExampleGameRulesV1 extends ExampleGameV1RulesBase {
|
|
7
8
|
const ExampleGameRulesV1();
|
|
@@ -40,6 +41,11 @@ class ExampleGameRulesV1 extends ExampleGameV1RulesBase {
|
|
|
40
41
|
|
|
41
42
|
@override
|
|
42
43
|
bool botSeatable(BotSeatableArgs args) => true;
|
|
44
|
+
|
|
45
|
+
/// Offline play, opt-in. Remove this override and `local_rules.dart` if the
|
|
46
|
+
/// game should only ever be played against the server.
|
|
47
|
+
@override
|
|
48
|
+
ExampleGameLocalRulesV1 get local => const ExampleGameLocalRulesV1();
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
class _CounterBoard extends StatelessWidget {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Web assets
|
|
2
|
+
|
|
3
|
+
`sqlite3.wasm` and `drift_worker.js` are drift's web runtime, taken verbatim
|
|
4
|
+
from the [drift 2.35.0
|
|
5
|
+
release](https://github.com/simolus3/drift/releases/tag/drift-2.35.0). They are
|
|
6
|
+
served from the app's own origin because that is where `LocalDatabase` looks for
|
|
7
|
+
them, and they are what gives a browser the storage offline play needs.
|
|
8
|
+
|
|
9
|
+
Replace both together whenever the `drift` constraint in `eigen_flutter`'s
|
|
10
|
+
pubspec moves, and take them from the matching release: the worker and the
|
|
11
|
+
module are one pair.
|