Skip to content

Commit

Permalink
Add customizable background, add send event
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Aug 11, 2024
1 parent 2eff3c5 commit 779dd8f
Show file tree
Hide file tree
Showing 26 changed files with 733 additions and 143 deletions.
14 changes: 13 additions & 1 deletion app/lib/bloc/board.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
..events.listen(add)
..inits.listen((e) {
if (e == 0) return;
print('$e has joined');
state.multiplayer.send(TableChanged(state.table), e);
});

on<TableChanged>((event, emit) {
emit(state.copyWith(table: event.table));
return save();
});
on<BackgroundChanged>((event, emit) {
emit(state.copyWith.table(background: event.background));
});
on<ColorSchemeChanged>((event, emit) {
emit(state.copyWith(colorScheme: event.colorScheme));
});
Expand Down Expand Up @@ -63,6 +65,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
var from = state.table.cells[event.from] ?? TableCell();
var to = state.table.cells[event.to] ?? TableCell();
final toRemove = event.objects;
if (event.objects.any((e) => e >= from.objects.length)) return null;
final toAdd = toRemove.map((e) => from.objects[e]).toList();
final newObjects = List<GameObject>.from(from.objects);
for (final i in toRemove.sorted((a, b) => b.compareTo(a))) {
Expand Down Expand Up @@ -135,4 +138,13 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
super.onEvent(event);
if (event.isMultiplayer) state.multiplayer.send(event);
}

void send(BoardEvent event) {
if (event.isMultiplayer && state.multiplayer.isConnected) {
if (state.multiplayer.isServer) add(event);
state.multiplayer.send(event);
} else {
add(event);
}
}
}
14 changes: 14 additions & 0 deletions app/lib/bloc/board_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ final class TableChanged extends BoardEvent with TableChangedMappable {

TableChanged(this.table, {super.isRemoteEvent});

@override
bool get isMultiplayer => true;
}

Expand All @@ -60,6 +61,14 @@ final class ColorSchemeChanged extends BoardEvent
ColorSchemeChanged(this.colorScheme, {super.isRemoteEvent});
}

@MappableClass()
final class BackgroundChanged extends BoardEvent
with BackgroundChangedMappable {
final ItemLocation background;

BackgroundChanged(this.background, {super.isRemoteEvent});
}

@MappableClass()
final class HandChanged extends BoardEvent with HandChangedMappable {
final ItemLocation? deck;
Expand All @@ -83,6 +92,7 @@ final class ObjectsSpawned extends BoardEvent with ObjectsSpawnedMappable {

ObjectsSpawned(this.cell, this.objects, {super.isRemoteEvent});

@override
bool get isMultiplayer => true;
}

Expand All @@ -93,6 +103,7 @@ final class ObjectsMoved extends BoardEvent with ObjectsMovedMappable {

ObjectsMoved(this.objects, this.from, this.to, {super.isRemoteEvent});

@override
bool get isMultiplayer => true;
}

Expand All @@ -108,6 +119,7 @@ final class CellHideChanged extends BoardEvent with CellHideChangedMappable {
CellHideChanged.hide(this.cell, {this.object, super.isRemoteEvent})
: hide = true;

@override
bool get isMultiplayer => true;
}

Expand All @@ -120,6 +132,7 @@ final class CellShuffled extends BoardEvent with CellShuffledMappable {
CellShuffled.random(this.cell, {super.isRemoteEvent})
: seed = DateTime.now().millisecondsSinceEpoch;

@override
bool get isMultiplayer => true;
}

Expand All @@ -132,5 +145,6 @@ final class ObjectIndexChanged extends BoardEvent

ObjectIndexChanged(this.cell, this.object, this.index, {super.isRemoteEvent});

@override
bool get isMultiplayer => true;
}
135 changes: 135 additions & 0 deletions app/lib/bloc/board_event.mapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class BoardEventMapper extends ClassMapperBase<BoardEvent> {
TableChangedMapper.ensureInitialized();
CellSwitchedMapper.ensureInitialized();
ColorSchemeChangedMapper.ensureInitialized();
BackgroundChangedMapper.ensureInitialized();
HandChangedMapper.ensureInitialized();
ObjectsSpawnedMapper.ensureInitialized();
ObjectsMovedMapper.ensureInitialized();
Expand Down Expand Up @@ -463,6 +464,140 @@ class _ColorSchemeChangedCopyWithImpl<$R, $Out>
_ColorSchemeChangedCopyWithImpl($value, $cast, t);
}

class BackgroundChangedMapper extends SubClassMapperBase<BackgroundChanged> {
BackgroundChangedMapper._();

static BackgroundChangedMapper? _instance;
static BackgroundChangedMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = BackgroundChangedMapper._());
BoardEventMapper.ensureInitialized().addSubMapper(_instance!);
ItemLocationMapper.ensureInitialized();
}
return _instance!;
}

@override
final String id = 'BackgroundChanged';

static ItemLocation _$background(BackgroundChanged v) => v.background;
static const Field<BackgroundChanged, ItemLocation> _f$background =
Field('background', _$background);
static bool _$isRemoteEvent(BackgroundChanged v) => v.isRemoteEvent;
static const Field<BackgroundChanged, bool> _f$isRemoteEvent =
Field('isRemoteEvent', _$isRemoteEvent, opt: true, def: false);

@override
final MappableFields<BackgroundChanged> fields = const {
#background: _f$background,
#isRemoteEvent: _f$isRemoteEvent,
};

@override
final String discriminatorKey = 'type';
@override
final dynamic discriminatorValue = 'BackgroundChanged';
@override
late final ClassMapperBase superMapper = BoardEventMapper.ensureInitialized();

@override
final MappingHook superHook = const IgnoreKeysHook({'isRemoteEvent'});

static BackgroundChanged _instantiate(DecodingData data) {
return BackgroundChanged(data.dec(_f$background),
isRemoteEvent: data.dec(_f$isRemoteEvent));
}

@override
final Function instantiate = _instantiate;

static BackgroundChanged fromMap(Map<String, dynamic> map) {
return ensureInitialized().decodeMap<BackgroundChanged>(map);
}

static BackgroundChanged fromJson(String json) {
return ensureInitialized().decodeJson<BackgroundChanged>(json);
}
}

mixin BackgroundChangedMappable {
String toJson() {
return BackgroundChangedMapper.ensureInitialized()
.encodeJson<BackgroundChanged>(this as BackgroundChanged);
}

Map<String, dynamic> toMap() {
return BackgroundChangedMapper.ensureInitialized()
.encodeMap<BackgroundChanged>(this as BackgroundChanged);
}

BackgroundChangedCopyWith<BackgroundChanged, BackgroundChanged,
BackgroundChanged>
get copyWith => _BackgroundChangedCopyWithImpl(
this as BackgroundChanged, $identity, $identity);
@override
String toString() {
return BackgroundChangedMapper.ensureInitialized()
.stringifyValue(this as BackgroundChanged);
}

@override
bool operator ==(Object other) {
return BackgroundChangedMapper.ensureInitialized()
.equalsValue(this as BackgroundChanged, other);
}

@override
int get hashCode {
return BackgroundChangedMapper.ensureInitialized()
.hashValue(this as BackgroundChanged);
}
}

extension BackgroundChangedValueCopy<$R, $Out>
on ObjectCopyWith<$R, BackgroundChanged, $Out> {
BackgroundChangedCopyWith<$R, BackgroundChanged, $Out>
get $asBackgroundChanged =>
$base.as((v, t, t2) => _BackgroundChangedCopyWithImpl(v, t, t2));
}

abstract class BackgroundChangedCopyWith<$R, $In extends BackgroundChanged,
$Out> implements BoardEventCopyWith<$R, $In, $Out> {
ItemLocationCopyWith<$R, ItemLocation, ItemLocation> get background;
@override
$R call({ItemLocation? background, bool? isRemoteEvent});
BackgroundChangedCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t);
}

class _BackgroundChangedCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, BackgroundChanged, $Out>
implements BackgroundChangedCopyWith<$R, BackgroundChanged, $Out> {
_BackgroundChangedCopyWithImpl(super.value, super.then, super.then2);

@override
late final ClassMapperBase<BackgroundChanged> $mapper =
BackgroundChangedMapper.ensureInitialized();
@override
ItemLocationCopyWith<$R, ItemLocation, ItemLocation> get background =>
$value.background.copyWith.$chain((v) => call(background: v));
@override
$R call({ItemLocation? background, bool? isRemoteEvent}) =>
$apply(FieldCopyWithData({
if (background != null) #background: background,
if (isRemoteEvent != null) #isRemoteEvent: isRemoteEvent
}));
@override
BackgroundChanged $make(CopyWithData data) =>
BackgroundChanged(data.get(#background, or: $value.background),
isRemoteEvent: data.get(#isRemoteEvent, or: $value.isRemoteEvent));

@override
BackgroundChangedCopyWith<$R2, BackgroundChanged, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t) =>
_BackgroundChangedCopyWithImpl($value, $cast, t);
}

class HandChangedMapper extends SubClassMapperBase<HandChanged> {
HandChangedMapper._();

Expand Down
4 changes: 3 additions & 1 deletion app/lib/bloc/multiplayer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ final class MultiplayerConnectedState extends MultiplayerState

MultiplayerConnectedState(this.networker, this.transformer);

@override
bool get isClient => networker is NetworkerClient;
@override
bool get isServer => networker is NetworkerServer;
}

Expand Down Expand Up @@ -62,11 +64,11 @@ class MultiplayerCubit extends Cubit<MultiplayerState> {
emit(MultiplayerConnectedState(base, transformer));
transformer.read.listen((event) {
if (event.data.isMultiplayer) {
print('Received multiplayer event: ${event.data.runtimeType}');
_eventController.add(event.data.copyWith(isRemoteEvent: true));
}
});
if (base is NetworkerServer) {
base.connect(EchoPipe(toChannel: kAnyChannel));
base.clientConnect.pipe(_initController);
}
}
Expand Down
31 changes: 29 additions & 2 deletions app/lib/board/background.dart
Original file line number Diff line number Diff line change
@@ -1,14 +1,41 @@
import 'dart:async';
import 'dart:ui';

import 'package:flame/components.dart';
import 'package:flame_bloc/flame_bloc.dart';
import 'package:quokka/bloc/board.dart';
import 'package:quokka/bloc/board_state.dart';
import 'package:quokka/board/game.dart';

class GameBoardBackground extends SpriteComponent
with HasGameReference<BoardGame> {
with
HasGameReference<BoardGame>,
FlameBlocListenable<BoardBloc, BoardState> {
GameBoardBackground({super.size})
: super(paint: Paint()..isAntiAlias = false);

@override
void onLoad() {
sprite = game.gridSprite;
sprite = game.selectionSprite;
}

@override
void onInitialState(BoardState state) => updateBackground(state);

@override
void onNewState(BoardState state) => updateBackground(state);

Future<void> updateBackground(BoardState state) async {
final backgroundLocation = state.table.background;
var background = backgroundLocation == null
? null
: (await game.assetManager.loadPack(backgroundLocation.namespace))
?.getBackgroundItem(backgroundLocation.id);
background ??= game.assetManager.packs
.map((pack) => pack.value.getBackgroundItems(pack.key).firstOrNull)
.nonNulls
.firstOrNull;
if (background == null) return;
sprite = await game.assetManager.loadSprite(background.item.texture);
}
}
8 changes: 4 additions & 4 deletions app/lib/board/cell.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ class GameCell extends HandItemDropZone
@override
void onTapUp(TapUpEvent event) {
if (isSelected) {
bloc.add(HandChanged.hide());
bloc.send(HandChanged.hide());
} else {
bloc.add(CellSwitched(toDefinition(), toggle: true));
bloc.send(CellSwitched(toDefinition(), toggle: true));
}
}

Expand Down Expand Up @@ -178,14 +178,14 @@ class GameCell extends HandItemDropZone
ContextMenuButtonItem(
label: AppLocalizations.of(context).toggleHide,
onPressed: () {
bloc.add(CellHideChanged(toDefinition()));
bloc.send(CellHideChanged(toDefinition()));
onClose();
},
),
ContextMenuButtonItem(
label: AppLocalizations.of(context).shuffle,
onPressed: () {
bloc.add(CellShuffled.random(toDefinition()));
bloc.send(CellShuffled.random(toDefinition()));
onClose();
},
),
Expand Down
15 changes: 4 additions & 11 deletions app/lib/board/game.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class BoardGame extends FlameGame
with ScrollDetector, KeyboardEvents, SecondaryTapDetector {
final ContextMenuController contextMenuController;
final AssetManager assetManager;
late final Sprite gridSprite, selectionSprite;
late final Sprite selectionSprite;
late final GameHand _hand;
late final BoardGrid grid;
final BoardBloc bloc;
Expand All @@ -30,10 +30,9 @@ class BoardGame extends FlameGame

BoardGame({
required this.bloc,
required this.assetManager,
required this.contextMenuController,
}) : assetManager = AssetManager(
bloc: bloc,
);
});

@override
FutureOr<void> onLoad() async {
Expand All @@ -43,12 +42,6 @@ class BoardGame extends FlameGame
provider.addAll([camera, world]);
const packName = '';
await assetManager.loadPack(packName);
final data = assetManager.getTexture('backgrounds/grid.png');
if (data == null) {
return;
}
final image = await decodeImageFromList(data);
gridSprite = Sprite(image);
selectionSprite = await Sprite.load('selection.png');
_hand = GameHand();
camera.viewport.add(_hand);
Expand Down Expand Up @@ -100,7 +93,7 @@ class BoardGame extends FlameGame
final nextColorScheme =
buildContext != null ? Theme.of(buildContext!).colorScheme : null;
if (nextColorScheme != bloc.state.colorScheme) {
bloc.add(ColorSchemeChanged(nextColorScheme));
bloc.send(ColorSchemeChanged(nextColorScheme));
}
}

Expand Down
Loading

0 comments on commit 779dd8f

Please sign in to comment.