Skip to content

Commit

Permalink
Use hash of archive for signature
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeDoctorDE committed Nov 13, 2024
1 parent 7f9a26a commit 9becc11
Show file tree
Hide file tree
Showing 16 changed files with 774 additions and 634 deletions.
17 changes: 9 additions & 8 deletions api/lib/src/event/event.mapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ class WorldInitializedMapper extends SubClassMapperBase<WorldInitialized> {
ServerWorldEventMapper.ensureInitialized().addSubMapper(_instance!);
GameTableMapper.ensureInitialized();
GameInfoMapper.ensureInitialized();
FileMetadataMapper.ensureInitialized();
SignatureMetadataMapper.ensureInitialized();
}
return _instance!;
}
Expand All @@ -216,9 +216,9 @@ class WorldInitializedMapper extends SubClassMapperBase<WorldInitialized> {
static int? _$id(WorldInitialized v) => v.id;
static const Field<WorldInitialized, int> _f$id =
Field('id', _$id, opt: true);
static Map<String, FileMetadata>? _$packsSignature(WorldInitialized v) =>
static Map<String, SignatureMetadata>? _$packsSignature(WorldInitialized v) =>
v.packsSignature;
static const Field<WorldInitialized, Map<String, FileMetadata>>
static const Field<WorldInitialized, Map<String, SignatureMetadata>>
_f$packsSignature = Field('packsSignature', _$packsSignature, opt: true);

@override
Expand Down Expand Up @@ -305,15 +305,16 @@ abstract class WorldInitializedCopyWith<$R, $In extends WorldInitialized, $Out>
GameInfoCopyWith<$R, GameInfo, GameInfo>? get info;
MapCopyWith<$R, String, Set<int>, ObjectCopyWith<$R, Set<int>, Set<int>>>?
get teamMembers;
MapCopyWith<$R, String, FileMetadata,
FileMetadataCopyWith<$R, FileMetadata, FileMetadata>>? get packsSignature;
MapCopyWith<$R, String, SignatureMetadata,
SignatureMetadataCopyWith<$R, SignatureMetadata, SignatureMetadata>>?
get packsSignature;
@override
$R call(
{GameTable? table,
GameInfo? info,
Map<String, Set<int>>? teamMembers,
int? id,
Map<String, FileMetadata>? packsSignature});
Map<String, SignatureMetadata>? packsSignature});
WorldInitializedCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t);
}
Expand Down Expand Up @@ -341,8 +342,8 @@ class _WorldInitializedCopyWithImpl<$R, $Out>
(v) => call(teamMembers: v))
: null;
@override
MapCopyWith<$R, String, FileMetadata,
FileMetadataCopyWith<$R, FileMetadata, FileMetadata>>?
MapCopyWith<$R, String, SignatureMetadata,
SignatureMetadataCopyWith<$R, SignatureMetadata, SignatureMetadata>>?
get packsSignature => $value.packsSignature != null
? MapCopyWith($value.packsSignature!, (v, t) => v.copyWith.$chain(t),
(v) => call(packsSignature: v))
Expand Down
8 changes: 4 additions & 4 deletions api/lib/src/event/process/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ bool isValidServerEvent(ServerWorldEvent event, WorldState state) =>
sealed class FatalServerEventError {}

final class InvalidPacksError extends FatalServerEventError {
final Map<String, FileMetadata> signature;
final Map<String, SignatureMetadata> signature;

InvalidPacksError({required this.signature});

Expand All @@ -61,8 +61,8 @@ final class InvalidPacksError extends FatalServerEventError {
'Server requested packs, that are not available on the client (or is empty): $signature';
}

bool isServerSupported(Map<String, FileMetadata> mySignature,
Map<String, FileMetadata> serverSignature) {
bool isServerSupported(Map<String, SignatureMetadata> mySignature,
Map<String, SignatureMetadata> serverSignature) {
for (final entry in serverSignature.entries) {
final current = mySignature[entry.key];
if (current == null || !current.supports(entry.value)) {
Expand All @@ -82,7 +82,7 @@ class ServerProcessed {
ServerProcessed processServerEvent(
ServerWorldEvent event,
WorldState state, {
required Map<String, FileMetadata> signature,
required Map<String, SignatureMetadata> signature,
}) {
if (!isValidServerEvent(event, state)) return ServerProcessed(null);
switch (event) {
Expand Down
2 changes: 1 addition & 1 deletion api/lib/src/event/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class WorldInitialized extends ServerWorldEvent
final GameInfo? info;
final Map<String, Set<Channel>>? teamMembers;
final Channel? id;
final Map<String, FileMetadata>? packsSignature;
final Map<String, SignatureMetadata>? packsSignature;

WorldInitialized({
this.table,
Expand Down
10 changes: 7 additions & 3 deletions api/lib/src/models/data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,8 @@ class SetonixData extends ArchiveData<SetonixData> {
SetonixData updateState(ArchiveState state) =>
SetonixData(archive, state: state);

Digest getChecksum() {
final metadata = getMetadataOrDefault().toJson();
return sha512256.convert(utf8.encode(metadata));
String createIdentifier() {
return createPackIdentifier(exportAsBytes());
}

TranslationsStore getTranslationsStore(
Expand All @@ -216,6 +215,11 @@ class SetonixData extends ArchiveData<SetonixData> {
);
}

String createPackIdentifier(Uint8List data) {
final hash = sha512256.convert(data);
return base64Encode(hash.bytes);
}

final class PackItem<T> {
final SetonixData pack;
final ItemLocation location;
Expand Down
25 changes: 13 additions & 12 deletions api/lib/src/models/meta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ final class FileMetadata with FileMetadataMappable {
this.dependencies = const {},
this.fileVersion = kFileVersion,
});
}

@MappableClass()
final class SignatureMetadata with SignatureMetadataMappable {
final String id;
final FileMetadata metadata;

SignatureMetadata({
required this.id,
required this.metadata,
});

bool supports(FileMetadata metadata) {
if (metadata.fileVersion != fileVersion ||
metadata.type != type ||
metadata.name != name) {
return false;
}
if (metadata.dependencies.isNotEmpty) {
for (final dependency in metadata.dependencies) {
if (!dependencies.contains(dependency)) return false;
}
}
return true;
bool supports(SignatureMetadata other) {
return id == other.id;
}
}
118 changes: 118 additions & 0 deletions api/lib/src/models/meta.mapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,121 @@ class _FileMetadataCopyWithImpl<$R, $Out>
Then<$Out2, $R2> t) =>
_FileMetadataCopyWithImpl($value, $cast, t);
}

class SignatureMetadataMapper extends ClassMapperBase<SignatureMetadata> {
SignatureMetadataMapper._();

static SignatureMetadataMapper? _instance;
static SignatureMetadataMapper ensureInitialized() {
if (_instance == null) {
MapperContainer.globals.use(_instance = SignatureMetadataMapper._());
FileMetadataMapper.ensureInitialized();
}
return _instance!;
}

@override
final String id = 'SignatureMetadata';

static String _$id(SignatureMetadata v) => v.id;
static const Field<SignatureMetadata, String> _f$id = Field('id', _$id);
static FileMetadata _$metadata(SignatureMetadata v) => v.metadata;
static const Field<SignatureMetadata, FileMetadata> _f$metadata =
Field('metadata', _$metadata);

@override
final MappableFields<SignatureMetadata> fields = const {
#id: _f$id,
#metadata: _f$metadata,
};

static SignatureMetadata _instantiate(DecodingData data) {
return SignatureMetadata(
id: data.dec(_f$id), metadata: data.dec(_f$metadata));
}

@override
final Function instantiate = _instantiate;

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

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

mixin SignatureMetadataMappable {
String toJson() {
return SignatureMetadataMapper.ensureInitialized()
.encodeJson<SignatureMetadata>(this as SignatureMetadata);
}

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

SignatureMetadataCopyWith<SignatureMetadata, SignatureMetadata,
SignatureMetadata>
get copyWith => _SignatureMetadataCopyWithImpl(
this as SignatureMetadata, $identity, $identity);
@override
String toString() {
return SignatureMetadataMapper.ensureInitialized()
.stringifyValue(this as SignatureMetadata);
}

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

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

extension SignatureMetadataValueCopy<$R, $Out>
on ObjectCopyWith<$R, SignatureMetadata, $Out> {
SignatureMetadataCopyWith<$R, SignatureMetadata, $Out>
get $asSignatureMetadata =>
$base.as((v, t, t2) => _SignatureMetadataCopyWithImpl(v, t, t2));
}

abstract class SignatureMetadataCopyWith<$R, $In extends SignatureMetadata,
$Out> implements ClassCopyWith<$R, $In, $Out> {
FileMetadataCopyWith<$R, FileMetadata, FileMetadata> get metadata;
$R call({String? id, FileMetadata? metadata});
SignatureMetadataCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t);
}

class _SignatureMetadataCopyWithImpl<$R, $Out>
extends ClassCopyWithBase<$R, SignatureMetadata, $Out>
implements SignatureMetadataCopyWith<$R, SignatureMetadata, $Out> {
_SignatureMetadataCopyWithImpl(super.value, super.then, super.then2);

@override
late final ClassMapperBase<SignatureMetadata> $mapper =
SignatureMetadataMapper.ensureInitialized();
@override
FileMetadataCopyWith<$R, FileMetadata, FileMetadata> get metadata =>
$value.metadata.copyWith.$chain((v) => call(metadata: v));
@override
$R call({String? id, FileMetadata? metadata}) => $apply(FieldCopyWithData(
{if (id != null) #id: id, if (metadata != null) #metadata: metadata}));
@override
SignatureMetadata $make(CopyWithData data) => SignatureMetadata(
id: data.get(#id, or: $value.id),
metadata: data.get(#metadata, or: $value.metadata));

@override
SignatureMetadataCopyWith<$R2, SignatureMetadata, $Out2> $chain<$R2, $Out2>(
Then<$Out2, $R2> t) =>
_SignatureMetadataCopyWithImpl($value, $cast, t);
}
9 changes: 6 additions & 3 deletions api/lib/src/services/asset.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ abstract class AssetManager {

Iterable<MapEntry<String, SetonixData>> get packs;

Map<String, FileMetadata> createSignature([Set<String>? packs]) {
final signature = <String, FileMetadata>{};
Map<String, SignatureMetadata> createSignature([Set<String>? packs]) {
final signature = <String, SignatureMetadata>{};
for (final entry in this.packs) {
if (!(packs?.contains(entry.key) ?? true)) continue;
signature[entry.key] = entry.value.getMetadataOrDefault();
signature[entry.key] = SignatureMetadata(
metadata: entry.value.getMetadataOrDefault(),
id: entry.value.createIdentifier(),
);
}
return signature;
}
Expand Down
4 changes: 2 additions & 2 deletions api/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ packages:
dependency: transitive
description:
name: code_builder
sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37
sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e"
url: "https://pub.dev"
source: hosted
version: "4.10.0"
version: "4.10.1"
collection:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions app/lib/bloc/world/bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import 'package:setonix/bloc/multiplayer.dart';
import 'package:setonix_api/setonix_api.dart';

ServerProcessed _compute(
(ServerWorldEvent, WorldState, Map<String, FileMetadata>) m) =>
(ServerWorldEvent, WorldState, Map<String, SignatureMetadata>) m) =>
processServerEvent(m.$1, m.$2, signature: m.$3);

SetonixData _saveState(WorldState state) => state.save();
Expand Down Expand Up @@ -56,7 +56,7 @@ class WorldBloc extends Bloc<PlayableWorldEvent, ClientWorldState> {
final signature = state.assetManager.createSignature();
final world = state.world;
final processed = await compute<
(ServerWorldEvent, WorldState, Map<String, FileMetadata>),
(ServerWorldEvent, WorldState, Map<String, SignatureMetadata>),
ServerProcessed>(_compute, (event, world, signature));
final newWorld = processed.state;
processed.responses.forEach(process);
Expand Down
Loading

0 comments on commit 9becc11

Please sign in to comment.