Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions assets/weapons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ The PNGs are unmodified and retain transparency. `WeaponIcon` fits their visible
| marshal.png | [Marshal](https://media.valorant-api.com/weapons/c4883e50-4494-202c-3ec3-6b8a9284f00b/killstreamicon.png) |
| spectre.png | [Spectre](https://media.valorant-api.com/weapons/462080d1-4035-2937-7c09-27aa2a5c27a7/killstreamicon.png) |
| stinger.png | [Stinger](https://media.valorant-api.com/weapons/f7e1b454-4ad4-1063-ec0a-159e56b58941/killstreamicon.png) |
| warden.png | [Warden](https://media.valorant-api.com/weapons/8db0a1bf-4a50-832a-4566-faaaa6d250ca/killstreamicon.png), retrieved 2026-10-15 |
Binary file added assets/weapons/warden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/const/placed_classes.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/const/weapons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ enum WeaponType {
outlaw('Outlaw', WeaponCategory.snipers),
operator('Operator', WeaponCategory.snipers),
ares('Ares', WeaponCategory.heavies),
odin('Odin', WeaponCategory.heavies);
odin('Odin', WeaponCategory.heavies),
warden('Warden', WeaponCategory.rifles);

const WeaponType(this.displayName, this.category);

Expand Down
4 changes: 4 additions & 0 deletions lib/hive/hive_adapters.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion lib/hive/hive_adapters.g.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ types:
index: 6
WeaponType:
typeId: 38
nextIndex: 20
nextIndex: 21
fields:
none:
index: 0
Expand Down Expand Up @@ -581,6 +581,8 @@ types:
index: 18
odin:
index: 19
warden:
index: 20
CloudMediaJobState:
typeId: 39
nextIndex: 3
Expand Down
1 change: 1 addition & 0 deletions lib/replay/replay_weapons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const List<(String, WeaponType)> _weaponsByPathPart = [
('/Rifles/DMR/', WeaponType.guardian),
('/Rifles/Carbine/', WeaponType.phantom),
('/Rifles/AK/', WeaponType.vandal),
('/Rifles/BattleRifle/', WeaponType.warden),
('/Sniper/LeverSniperRifle/', WeaponType.marshal),
('/Sniper/DoubleSniper/', WeaponType.outlaw),
('/Sniper/BoltSniper/', WeaponType.operator),
Expand Down
1 change: 1 addition & 0 deletions lib/widgets/draggable_widgets/agents/weapon_icon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,5 @@ const _artworkBounds = <WeaponType, (Size, Rect)>{
WeaponType.operator: (Size(512, 96), Rect.fromLTRB(18, 0, 494, 95)),
WeaponType.ares: (Size(512, 96), Rect.fromLTRB(18, 1, 495, 96)),
WeaponType.odin: (Size(384, 96), Rect.fromLTRB(18, 1, 361, 96)),
WeaponType.warden: (Size(512, 140), Rect.fromLTRB(4, 4, 505, 137)),
};
2 changes: 1 addition & 1 deletion test/agent_weapon_widgets_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ void main() {
});
await tester.pumpAndSettle();
expect(tester.takeException(), isNull);
expect(find.byType(WeaponIcon), findsNWidgets(19));
expect(find.byType(WeaponIcon), findsNWidgets(20));
final sizes = tester
.elementList(find.byType(AgentWidget))
.map(
Expand Down
116 changes: 115 additions & 1 deletion test/desktop_4_6_3_adapters_test_support.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Desktop 4.6.3's adapters for the typeIds this build writes by hand, copied
// verbatim from the desktop-stable-v4.6.3+103 tag (only the class names
// changed). Every other adapter is unchanged since that release. Rollback
// changed), plus its WeaponTypeAdapter, which this build extended with the
// Warden. Every other adapter is unchanged since that release. Rollback
// tests decode with these to prove 4.6.3 opens, and keeps, what this build
// saves. Never edit them to match this build.

Expand Down Expand Up @@ -505,6 +506,119 @@ class Desktop463EllipseDrawingAdapter extends TypeAdapter<EllipseDrawing> {
}
}

class Desktop463WeaponTypeAdapter extends TypeAdapter<WeaponType> {
@override
final typeId = 38;

@override
WeaponType read(BinaryReader reader) {
switch (reader.readByte()) {
case 0:
return WeaponType.none;
case 1:
return WeaponType.classic;
case 2:
return WeaponType.shorty;
case 3:
return WeaponType.frenzy;
case 4:
return WeaponType.ghost;
case 5:
return WeaponType.bandit;
case 6:
return WeaponType.sheriff;
case 7:
return WeaponType.bulldog;
case 8:
return WeaponType.guardian;
case 9:
return WeaponType.phantom;
case 10:
return WeaponType.vandal;
case 11:
return WeaponType.bucky;
case 12:
return WeaponType.judge;
case 13:
return WeaponType.stinger;
case 14:
return WeaponType.spectre;
case 15:
return WeaponType.marshal;
case 16:
return WeaponType.outlaw;
case 17:
return WeaponType.operator;
case 18:
return WeaponType.ares;
case 19:
return WeaponType.odin;
default:
return WeaponType.none;
}
}

@override
void write(BinaryWriter writer, WeaponType obj) {
switch (obj) {
case WeaponType.none:
writer.writeByte(0);
case WeaponType.classic:
writer.writeByte(1);
case WeaponType.shorty:
writer.writeByte(2);
case WeaponType.frenzy:
writer.writeByte(3);
case WeaponType.ghost:
writer.writeByte(4);
case WeaponType.bandit:
writer.writeByte(5);
case WeaponType.sheriff:
writer.writeByte(6);
case WeaponType.bulldog:
writer.writeByte(7);
case WeaponType.guardian:
writer.writeByte(8);
case WeaponType.phantom:
writer.writeByte(9);
case WeaponType.vandal:
writer.writeByte(10);
case WeaponType.bucky:
writer.writeByte(11);
case WeaponType.judge:
writer.writeByte(12);
case WeaponType.stinger:
writer.writeByte(13);
case WeaponType.spectre:
writer.writeByte(14);
case WeaponType.marshal:
writer.writeByte(15);
case WeaponType.outlaw:
writer.writeByte(16);
case WeaponType.operator:
writer.writeByte(17);
case WeaponType.ares:
writer.writeByte(18);
case WeaponType.odin:
writer.writeByte(19);
// Not in 4.6.3, which can never hold one; only Dart's exhaustive
// switch needs the case.
case WeaponType.warden:
throw StateError('Desktop 4.6.3 has no Warden');
}
}

@override
int get hashCode => typeId.hashCode;

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Desktop463WeaponTypeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

int _readDrawingHiveColorValue(
Map<int, dynamic> fields, {
required int colorFieldIndex,
Expand Down
22 changes: 20 additions & 2 deletions test/hive_desktop_rollback_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ HiveImpl _currentRegistry() {
}

/// What desktop 4.6.3 registers: this build's adapters, which are unchanged
/// since that release, except the eight this build writes by hand.
/// since that release, except the eight this build writes by hand and the
/// weapon list, which gained the Warden.
HiveImpl _desktop463Registry() {
final registry = _currentRegistry();
// hive_ce warns on every override, which is the point here.
Expand All @@ -45,7 +46,8 @@ HiveImpl _desktop463Registry() {
..registerAdapter(Desktop463FreeDrawingAdapter(), override: true)
..registerAdapter(Desktop463LineAdapter(), override: true)
..registerAdapter(Desktop463RectangleDrawingAdapter(), override: true)
..registerAdapter(Desktop463EllipseDrawingAdapter(), override: true);
..registerAdapter(Desktop463EllipseDrawingAdapter(), override: true)
..registerAdapter(Desktop463WeaponTypeAdapter(), override: true);
} finally {
Logger.level = previousLevel;
}
Expand Down Expand Up @@ -191,6 +193,22 @@ void main() {
expect(opened.lineUpOrigins.single.agent.weapon, WeaponType.sheriff);
});

test('desktop 4.6.3 opens a Warden this build saved as no weapon', () {
final page = _richPage();
page.agentData.first.weapon = WeaponType.warden;
page.lineUpOrigins.single.agent.weapon = WeaponType.warden;
final opened = _across(current, desktop463, page);

expect(
opened.agentData.map((agent) => agent.weapon),
[WeaponType.none, WeaponType.operator, WeaponType.none],
);
expect(opened.lineUpOrigins.single.agent.weapon, WeaponType.none);
page.agentData.first.weapon = WeaponType.none;
page.lineUpOrigins.single.agent.weapon = WeaponType.none;
_expectSamePage(opened, page);
});

test('what desktop 4.6.3 saves back, this build opens whole', () {
final page = _richPage();
final rolledBack = _across(current, desktop463, page);
Expand Down
Loading