Skip to content

Commit 0121b11

Browse files
authored
Merge pull request #43 from LinwoodDev/feature/plugin-system
Feature/plugin system
2 parents a33f791 + db50181 commit 0121b11

File tree

131 files changed

+11933
-1848
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+11933
-1848
lines changed

.github/workflows/build.yml

+27-5
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,14 @@ jobs:
205205
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
206206
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
207207
- name: ✅ Enable platforms
208-
run: flutter config --enable-linux-desktop
208+
run: |
209+
rm -f "$(dirname "$(dirname "$(command -v flutter)")")/engine/src/.gn"
210+
flutter config --enable-linux-desktop
209211
- name: 📦 Get dependencies
210212
run: |
211213
flutter clean
212-
flutter pub get
213214
flutter doctor -v
215+
flutter pub get
214216
- name: Build nessesary files
215217
working-directory: ./
216218
run: |
@@ -231,6 +233,10 @@ jobs:
231233
- name: 🏭 Make binary executable
232234
run: |
233235
chmod +x build/linux/${{ matrix.arch.dir }}/release/bundle/setonix
236+
- name: Update files to arm64
237+
if: ${{ matrix.arch.name == 'arm64' }}
238+
run: |
239+
sed -i 's/^Architecture: amd64/Architecture: arm64/' linux/debian/DEBIAN/control
234240
- name: Build .deb executable
235241
run: |
236242
cp -fr build/linux/${{ matrix.arch.dir }}/release/bundle linux/debian/usr/bin
@@ -335,7 +341,9 @@ jobs:
335341
cache-key: 'flutter-:os:-:channel:-:version:-:arch:-:hash:'
336342
cache-path: '${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:'
337343
- name: ✅ Enable platforms
338-
run: flutter config --enable-linux-desktop
344+
run: |
345+
rm -f "$(dirname "$(dirname "$(command -v flutter)")")/engine/src/.gn"
346+
flutter config --enable-linux-desktop
339347
- name: 📦 Get dependencies
340348
run: |
341349
flutter clean
@@ -519,12 +527,16 @@ jobs:
519527
os:
520528
- name: ubuntu-24.04
521529
label: linux-x86_64
530+
rust: libsetonix_plugin.so
522531
- name: ubuntu-24.04-arm
523532
label: linux-arm64
533+
rust: libsetonix_plugin.so
524534
- name: windows-2025
525535
label: windows-x86_64
536+
rust: setonix_plugin.dll
526537
- name: macos-latest
527538
label: macos
539+
rust: libsetonix_plugin.dylib
528540
runs-on: ${{ matrix.os.name }}
529541
steps:
530542
- name: ⬆️ Checkout
@@ -544,6 +556,10 @@ jobs:
544556
flutter clean
545557
flutter pub get
546558
flutter doctor -v
559+
- name: Compile rust
560+
working-directory: plugin/rust
561+
run: |
562+
cargo build --release
547563
- name: Compile
548564
run: |
549565
dart compile exe bin/setonix_server.dart
@@ -552,6 +568,10 @@ jobs:
552568
mkdir -p server-build
553569
mv bin/setonix_server.exe server-build/
554570
mkdir -p server-build/packs
571+
- name: Move rust lib
572+
working-directory: ./
573+
run: |
574+
cp plugin/rust/target/release/${{ matrix.os.rust }} server/server-build/
555575
- name: Build nessesary files
556576
working-directory: ./
557577
run: |
@@ -676,7 +696,9 @@ jobs:
676696
path: server-build-macos/
677697
- name: 📦 Zip artifacts
678698
run: |
679-
zip -r linwood-setonix-windows-x86_64.zip windows-build/*
699+
cd windows-build
700+
zip -r ../linwood-setonix-windows-x86_64.zip *
701+
cd ..
680702
tar -C linux-x86_64-build -czf linwood-setonix-linux-x86_64.tar.gz .
681703
tar -C linux-arm64-build -czf linwood-setonix-linux-arm64.tar.gz .
682704
zip -r linwood-setonix-server-windows-x86_64.zip server-build-windows-x86_64/*
@@ -855,7 +877,7 @@ jobs:
855877
- name: Setup Fastlane
856878
uses: ruby/setup-ruby@v1
857879
with:
858-
ruby-version: "3.3.6"
880+
ruby-version: "3.3.7"
859881
bundler-cache: true
860882
working-directory: app/android
861883
- name: 🚀 Deploy to Play Store

.github/workflows/dart.yml

+13-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
continue-on-error: true
99
strategy:
1010
matrix:
11-
projects: [app, api, server, tools]
11+
projects: [app, api, plugin, server, tools]
1212
defaults:
1313
run:
1414
working-directory: ${{ matrix.projects }}
@@ -33,13 +33,25 @@ jobs:
3333
- name: Install dependencies
3434
run: |
3535
flutter pub get
36+
- name: Install app specific dependencies
37+
if: matrix.projects == 'app'
38+
run: |
39+
cd rust_builder
40+
flutter pub get
41+
cd cargokit/build_tool
42+
flutter pub get
3643
# Uncomment this step to verify the use of 'dart format' on each commit.
3744
- name: Verify formatting
3845
run: dart format --output=none --set-exit-if-changed .
3946
# Consider passing '--fatal-infos' for slightly stricter analysis.
4047
- name: Analyze project source
4148
run: |
4249
flutter analyze --fatal-infos
50+
- name: Build flutter_rust_bridge bindings
51+
if: matrix.projects == 'plugin'
52+
run: |
53+
cargo install [email protected]
54+
flutter_rust_bridge_codegen generate
4355
- name: Run build_runner
4456
if: matrix.projects == 'api' || matrix.projects == 'app'
4557
run: dart run build_runner build --delete-conflicting-outputs

.github/workflows/release.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ jobs:
231231
echo '' >> $GITHUB_ENV
232232
echo 'EOF' >> $GITHUB_ENV
233233
- name: Discord Webhook Action
234-
uses: tsickert/discord-webhook@v6.0.0
234+
uses: tsickert/discord-webhook@v7.0.0
235235
if: ${{ github.event.inputs.stable == 'true' || github.ref == 'refs/heads/main' }}
236236
with:
237237
webhook-url: ${{ secrets.WEBHOOK_URL }}
@@ -243,7 +243,7 @@ jobs:
243243
Download it here: https://setonix.world/downloads
244244
https://github.com/LinwoodDev/Setonix/releases/tag/v${{ env.SETONIX_VERSION }}
245245
- name: Discord Webhook Action
246-
uses: tsickert/discord-webhook@v6.0.0
246+
uses: tsickert/discord-webhook@v7.0.0
247247
if: ${{ github.event.inputs.stable == 'false' && github.ref == 'refs/heads/develop' }}
248248
with:
249249
webhook-url: ${{ secrets.WEBHOOK_URL }}

api/lib/models.dart

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export 'src/models/definition.dart';
66
export 'src/models/dialog.dart';
77
export 'src/models/info.dart';
88
export 'src/models/meta.dart';
9+
export 'src/models/mode.dart';
910
export 'src/models/server.dart';
1011
export 'src/models/table.dart';
1112
export 'src/models/translation.dart';

api/lib/src/event/client.dart

+9
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,12 @@ final class ImagesRequest extends ClientWorldEvent with ImagesRequestMappable {
148148

149149
ImagesRequest(this.ids);
150150
}
151+
152+
@MappableClass()
153+
final class ModeChangeRequest extends ClientWorldEvent
154+
with ModeChangeRequestMappable {
155+
final ItemLocation? location;
156+
157+
ModeChangeRequest(this.location);
158+
ModeChangeRequest.plain() : location = null;
159+
}

api/lib/src/event/event.mapper.dart

+139-5
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ class WorldInitializedMapper extends SubClassMapperBase<WorldInitialized> {
220220
v.packsSignature;
221221
static const Field<WorldInitialized, List<SignatureMetadata>>
222222
_f$packsSignature = Field('packsSignature', _$packsSignature, opt: true);
223+
static bool _$clearUserInterface(WorldInitialized v) => v.clearUserInterface;
224+
static const Field<WorldInitialized, bool> _f$clearUserInterface =
225+
Field('clearUserInterface', _$clearUserInterface, opt: true, def: false);
223226

224227
@override
225228
final MappableFields<WorldInitialized> fields = const {
@@ -228,6 +231,7 @@ class WorldInitializedMapper extends SubClassMapperBase<WorldInitialized> {
228231
#teamMembers: _f$teamMembers,
229232
#id: _f$id,
230233
#packsSignature: _f$packsSignature,
234+
#clearUserInterface: _f$clearUserInterface,
231235
};
232236

233237
@override
@@ -244,7 +248,8 @@ class WorldInitializedMapper extends SubClassMapperBase<WorldInitialized> {
244248
info: data.dec(_f$info),
245249
teamMembers: data.dec(_f$teamMembers),
246250
id: data.dec(_f$id),
247-
packsSignature: data.dec(_f$packsSignature));
251+
packsSignature: data.dec(_f$packsSignature),
252+
clearUserInterface: data.dec(_f$clearUserInterface));
248253
}
249254

250255
@override
@@ -314,7 +319,8 @@ abstract class WorldInitializedCopyWith<$R, $In extends WorldInitialized, $Out>
314319
GameInfo? info,
315320
Map<String, Set<int>>? teamMembers,
316321
int? id,
317-
List<SignatureMetadata>? packsSignature});
322+
List<SignatureMetadata>? packsSignature,
323+
bool? clearUserInterface});
318324
WorldInitializedCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
319325
Then<$Out2, $R2> t);
320326
}
@@ -354,21 +360,25 @@ class _WorldInitializedCopyWithImpl<$R, $Out>
354360
Object? info = $none,
355361
Object? teamMembers = $none,
356362
Object? id = $none,
357-
Object? packsSignature = $none}) =>
363+
Object? packsSignature = $none,
364+
bool? clearUserInterface}) =>
358365
$apply(FieldCopyWithData({
359366
if (table != $none) #table: table,
360367
if (info != $none) #info: info,
361368
if (teamMembers != $none) #teamMembers: teamMembers,
362369
if (id != $none) #id: id,
363-
if (packsSignature != $none) #packsSignature: packsSignature
370+
if (packsSignature != $none) #packsSignature: packsSignature,
371+
if (clearUserInterface != null) #clearUserInterface: clearUserInterface
364372
}));
365373
@override
366374
WorldInitialized $make(CopyWithData data) => WorldInitialized(
367375
table: data.get(#table, or: $value.table),
368376
info: data.get(#info, or: $value.info),
369377
teamMembers: data.get(#teamMembers, or: $value.teamMembers),
370378
id: data.get(#id, or: $value.id),
371-
packsSignature: data.get(#packsSignature, or: $value.packsSignature));
379+
packsSignature: data.get(#packsSignature, or: $value.packsSignature),
380+
clearUserInterface:
381+
data.get(#clearUserInterface, or: $value.clearUserInterface));
372382

373383
@override
374384
WorldInitializedCopyWith<$R2, WorldInitialized, $Out2> $chain<$R2, $Out2>(
@@ -1650,6 +1660,7 @@ class ClientWorldEventMapper extends SubClassMapperBase<ClientWorldEvent> {
16501660
BoardMoveRequestMapper.ensureInitialized();
16511661
DialogCloseRequestMapper.ensureInitialized();
16521662
ImagesRequestMapper.ensureInitialized();
1663+
ModeChangeRequestMapper.ensureInitialized();
16531664
HybridWorldEventMapper.ensureInitialized();
16541665
}
16551666
return _instance!;
@@ -3095,6 +3106,129 @@ class _ImagesRequestCopyWithImpl<$R, $Out>
30953106
_ImagesRequestCopyWithImpl($value, $cast, t);
30963107
}
30973108

3109+
class ModeChangeRequestMapper extends SubClassMapperBase<ModeChangeRequest> {
3110+
ModeChangeRequestMapper._();
3111+
3112+
static ModeChangeRequestMapper? _instance;
3113+
static ModeChangeRequestMapper ensureInitialized() {
3114+
if (_instance == null) {
3115+
MapperContainer.globals.use(_instance = ModeChangeRequestMapper._());
3116+
ClientWorldEventMapper.ensureInitialized().addSubMapper(_instance!);
3117+
ItemLocationMapper.ensureInitialized();
3118+
}
3119+
return _instance!;
3120+
}
3121+
3122+
@override
3123+
final String id = 'ModeChangeRequest';
3124+
3125+
static ItemLocation? _$location(ModeChangeRequest v) => v.location;
3126+
static const Field<ModeChangeRequest, ItemLocation> _f$location =
3127+
Field('location', _$location);
3128+
3129+
@override
3130+
final MappableFields<ModeChangeRequest> fields = const {
3131+
#location: _f$location,
3132+
};
3133+
3134+
@override
3135+
final String discriminatorKey = 'type';
3136+
@override
3137+
final dynamic discriminatorValue = 'ModeChangeRequest';
3138+
@override
3139+
late final ClassMapperBase superMapper =
3140+
ClientWorldEventMapper.ensureInitialized();
3141+
3142+
static ModeChangeRequest _instantiate(DecodingData data) {
3143+
return ModeChangeRequest(data.dec(_f$location));
3144+
}
3145+
3146+
@override
3147+
final Function instantiate = _instantiate;
3148+
3149+
static ModeChangeRequest fromMap(Map<String, dynamic> map) {
3150+
return ensureInitialized().decodeMap<ModeChangeRequest>(map);
3151+
}
3152+
3153+
static ModeChangeRequest fromJson(String json) {
3154+
return ensureInitialized().decodeJson<ModeChangeRequest>(json);
3155+
}
3156+
}
3157+
3158+
mixin ModeChangeRequestMappable {
3159+
String toJson() {
3160+
return ModeChangeRequestMapper.ensureInitialized()
3161+
.encodeJson<ModeChangeRequest>(this as ModeChangeRequest);
3162+
}
3163+
3164+
Map<String, dynamic> toMap() {
3165+
return ModeChangeRequestMapper.ensureInitialized()
3166+
.encodeMap<ModeChangeRequest>(this as ModeChangeRequest);
3167+
}
3168+
3169+
ModeChangeRequestCopyWith<ModeChangeRequest, ModeChangeRequest,
3170+
ModeChangeRequest>
3171+
get copyWith => _ModeChangeRequestCopyWithImpl(
3172+
this as ModeChangeRequest, $identity, $identity);
3173+
@override
3174+
String toString() {
3175+
return ModeChangeRequestMapper.ensureInitialized()
3176+
.stringifyValue(this as ModeChangeRequest);
3177+
}
3178+
3179+
@override
3180+
bool operator ==(Object other) {
3181+
return ModeChangeRequestMapper.ensureInitialized()
3182+
.equalsValue(this as ModeChangeRequest, other);
3183+
}
3184+
3185+
@override
3186+
int get hashCode {
3187+
return ModeChangeRequestMapper.ensureInitialized()
3188+
.hashValue(this as ModeChangeRequest);
3189+
}
3190+
}
3191+
3192+
extension ModeChangeRequestValueCopy<$R, $Out>
3193+
on ObjectCopyWith<$R, ModeChangeRequest, $Out> {
3194+
ModeChangeRequestCopyWith<$R, ModeChangeRequest, $Out>
3195+
get $asModeChangeRequest =>
3196+
$base.as((v, t, t2) => _ModeChangeRequestCopyWithImpl(v, t, t2));
3197+
}
3198+
3199+
abstract class ModeChangeRequestCopyWith<$R, $In extends ModeChangeRequest,
3200+
$Out> implements ClientWorldEventCopyWith<$R, $In, $Out> {
3201+
ItemLocationCopyWith<$R, ItemLocation, ItemLocation>? get location;
3202+
@override
3203+
$R call({ItemLocation? location});
3204+
ModeChangeRequestCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
3205+
Then<$Out2, $R2> t);
3206+
}
3207+
3208+
class _ModeChangeRequestCopyWithImpl<$R, $Out>
3209+
extends ClassCopyWithBase<$R, ModeChangeRequest, $Out>
3210+
implements ModeChangeRequestCopyWith<$R, ModeChangeRequest, $Out> {
3211+
_ModeChangeRequestCopyWithImpl(super.value, super.then, super.then2);
3212+
3213+
@override
3214+
late final ClassMapperBase<ModeChangeRequest> $mapper =
3215+
ModeChangeRequestMapper.ensureInitialized();
3216+
@override
3217+
ItemLocationCopyWith<$R, ItemLocation, ItemLocation>? get location =>
3218+
$value.location?.copyWith.$chain((v) => call(location: v));
3219+
@override
3220+
$R call({Object? location = $none}) =>
3221+
$apply(FieldCopyWithData({if (location != $none) #location: location}));
3222+
@override
3223+
ModeChangeRequest $make(CopyWithData data) =>
3224+
ModeChangeRequest(data.get(#location, or: $value.location));
3225+
3226+
@override
3227+
ModeChangeRequestCopyWith<$R2, ModeChangeRequest, $Out2> $chain<$R2, $Out2>(
3228+
Then<$Out2, $R2> t) =>
3229+
_ModeChangeRequestCopyWithImpl($value, $cast, t);
3230+
}
3231+
30983232
class HybridWorldEventMapper extends SubClassMapperBase<HybridWorldEvent> {
30993233
HybridWorldEventMapper._();
31003234

api/lib/src/event/process/client.dart

+8
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ bool isValidClientEvent(
6969
.tiles
7070
.length -
7171
1),
72+
ModeChangeRequest() => channel == kAuthorityChannel,
7273
_ => true,
7374
};
7475

@@ -271,5 +272,12 @@ ServerResponse? processClientEvent(
271272
return MapEntry(e, image);
272273
}).nonNulls)),
273274
channel);
275+
case ModeChangeRequest():
276+
final location = event.location;
277+
final mode = location == null
278+
? null
279+
: assetManager.getPack(location.namespace)?.getMode(location.id);
280+
return ServerResponse.builder(
281+
WorldInitialized.fromMode(mode, state), channel);
274282
}
275283
}

0 commit comments

Comments
 (0)