Last time this year, I was at Epoch. Almost 200 teenagers, all put into a hack­er­space and 48 hours of pure fun and code. It was like the Hunger Games mi­nus the death and the vi­o­lence and the bat­tle-royale for­mat and the com­peti­ton and ba­si­cally every­thing that made the Hunger Games what it is. Also I have not seen Hunger Games, I’ve read half of the first book and I thought it’d be a cool thing to say. I won­der if there’s a party scene in Hunger Games cause we had a banger of a New Year’s party and I ba­si­cally lost my mind shout­ing and freak­ing out.

Anyways, a lot of fun things has hap­pened since then. I will ad­mit, how­ever, that this year lacked the proper vibes or feels” (whatever gen-z says, pick up an Urban Dictionary). I think it’s be­cause halfway through the year, I cut down on a lot of things (at least I was sup­posed to) be­cause of The Boards. We don’t talk about it, all we know is that it’s a se­ries of mys­te­ri­ous ex­am­i­na­tions con­ducted by mys­te­ri­ous fig­ures from India. It’s like the Hunger Games but with all the death and vi­o­lence. Just like how Bobbin was beat to death by Coriander some­thing (edit: her name is Coriolanus), par­ents of­ten beat their kids with NCERT text­books.

I was eating during all those gray boxes.



my video game ad­dic­tion ac­tiv­i­ties

Apart from FNATIC win­ning three in­ter­na­tional VALORANT tour­na­ments (two of­fi­cial and one off-sea­son) and China fi­nally get­ting their win against NAVI with EDG KangKang show­ing up, I was quite in­vested in VALORANT. If my par­ents or any­body con­cerned about my men­tal health is read­ing, I’d like to in­form you that I’ve only played the game for a to­tal of 260 hours in the past two years, so I don’t think I am ad­dicted. According to on­line-stop­watch.com, that is 10 days and 20 hours. In 10 days and 20 hours (out of 730 days), light­ing will hit the earth 86,666,667 times! However, here’s where it gets in­ter­est­ing.

VALORANT has an in-game store that sells cos­met­ics for the game which trans­lates to no ac­tual use in the real world or the vir­tual world.

Its pur­pose is purely aes­thet­i­cal.

https://www.reddit.com/r/starterpacks/comments/jr3qmu/aesthetic_starter_pack/

There ex­ists a cos­metic item, or skin”, called the Prime Vandal.

THE HOLY PRIME VANDAL

Over the years, it has at­tained an over­rated sta­tus but it’s not for no rea­son. My love for the skin is purely aes­thet­i­cal. If Apple ever made a video game item for VALORANT, it would be the Prime Vandal. It’s like a lightsaber but in­fi­nitely more sat­is­fy­ing. It has sleek edges and a geo­met­ri­cally sat­is­fy­ing sur­face. As a de­signer and artist at heart, I felt bad for a small in­die-game com­pany like Riot Games for re­leas­ing free pop­u­lar video-games with lit­tle to no re­turns. For the ~250 hours I had spent on the game, I felt like the Prime Vandal skin would be a fair com­pen­sa­tion - Riot gets ap­pre­ci­ated, I get good-look­ing pix­els with ear­gas­mic sounds.

Here’s the prob­lem - I can’t just get it if I want it. VALORANTs store is in­ter­est­ing, to say the least. The VALORANT store con­sists of 4 ran­dom skins that re­freshes every­day. Purely ran­dom. Skins that you al­ready own do not show up, so un­less you’ve bought a large num­ber of skins, the chances of get­ting one par­tic­u­lar skin can be slim. How slim? Let’s do the math. (thanks Reddit)

According to r/​VAL­O­RANT, as of April 2023, there are 489 avail­able skins for the ro­tat­ing store. With four skins per day, there is a (1/489 + 1/488 + 1/487 + 1/486)*100% = 0.82% chance per day to see any given skin if you own no skins. For every skin you own, this per­cent­age will in­crease slightly as owned skins do not ap­pear in the ro­tat­ing shop pool. 0.82 is less than 1, and any num­ber less than 1 is a bad idea, as any math­e­mati­cian deal­ing with prob­a­bil­ity will tell you. Essentially, the chances were short.

I started wait­ing for the skin on 29 May, 2023. A lot hap­pened dur­ing that time. Grass grew, the world aged, and the deserts be­came drier. In a des­per­ate at­tempt, I emailed Riot Games. Begging them to give me the skin in the store. Attached be­low is my cor­re­spon­dence with some video-game char­ac­ters.

On July 21, 2023 09:26, ipay­forhacks wrote
Email with Riot Games - Part 1

On July 21, 2023 22:05, Ditto replied
Email with Riot Games - Part 2

They also sent a GIF af­ter that, I made it my in-game spray ever since - you never know.

Jett VALORANT Saranghae Spray

Now, it was sup­posed to end there, but I’m a kind per­son. I had to ex­press my thanks. It turns out my sup­port ticket was closed, and my thanks” ba­si­cally trig­gered Zendesk to re­open my ticket, which prompted one last re­ply from them.

On July 22, 2023 09:35, ipay­forhacks said
Email with Riot Games - Part 3

On July 22, 2023 10:18, hi­tur­rcilual replied
Email with Riot Games - Part 4

Writing this now, I re­al­ize they had ter­ri­ble luck. If any­thing the skin wishes de­creased all my chances. And every­day felt like a tease. I was con­vinced the Riot devs were man­u­ally chang­ing my skins every morn­ing to see me de­pressed at my luck for all the em­ploy­ees to have a good laugh at their break­fast table. Every time I checked my store, I’d look through my we­b­cam to make sure my life was­n’t some­thing like The Truman Show.

my big-brain 200iq mas­ter­class plan

That was when it struck me. Archimedes or some­one shouted Eureka”, I shouted HOLY COW. You see, VALORANT does not of­fer any of its game data pub­licly for your use un­less you ap­ply to be­come a Riot Developer”. However, that has not stopped de­vel­op­ers from scrap­ing VALORANT to find its in­ter­nal APIs and doc­u­ment­ing them. The prob­lem is that if you re­lease an ap­pli­ca­tion us­ing in­ter­nal APIs for pub­lic use, Riot Games will serve you a DMCA take­down on your ap­pli­ca­tion. Meaning, you are now legally obliged to re­move your app from wher­ever it ex­ists on the Internet. You can, of course, con­test the DMCA take­down but it’s re­ally point­less when your ap­pli­ca­tion is en­tirely based on VALORANT.

My plan was akin to a stand­off based on bluffs and de­ceit. I would pub­licly re­lease a mo­bile app that would use their in­ter­nal APIs to get my daily store, and when they ask me to take­down the app, I would ask for the Prime Vandal skin in my store in ex­change. It was a flaw­less plan. It was a win-win sit­u­a­tion - Riot gets to take down my app, I get the skin in my store.

Trade Offer

And so, I be­gan. What is pro­gram­ming for, if not to spend hours build­ing au­toma­tions for mean­ing­less tasks that would oth­er­wise take barely three min­utes man­u­ally. I ended up mak­ing an Android app that would track my VALORANT store every sin­gle day and give me a no­ti­fi­ca­tion if the Prime Vandal showed up.


Click to read more tech­ni­cal de­tails (or skip ahead)

in­tro­duc­tion to flut­ter

Getting a bit tech­ni­cal, the app build­ing was very in­ter­est­ing. I chose to go with Flutter, de­spite hav­ing zero ex­pe­ri­ence with it. It was pretty easy to use Flutter as a be­gin­ner, be­cause Dart’s syn­tax is ba­si­cally JavaScript. If you’ve used a lot of JavaScript, you’ll be com­fort­able with Flutter in no time. The only thing I was a bit in­tim­i­dated by was how large Flutter files can get, es­pe­cially if you don’t know or don’t want to (out of lazi­ness - like me) split your wid­gets into mul­ti­ple files. Another ad­van­tage is that for the most part you won’t have to worry about styling, as long as you’re us­ing Material Design 3.

Flutter com­piles to a wide va­ri­ety of plat­forms in­clud­ing Windows and iOS (requires ad­di­tional con­fig), which made de­bug­ging a breeze be­cause I could pre­view the app on the web for the most part. However, I would rec­om­mend us­ing an Android Studio sim­u­la­tor to test out Android-specific fea­tures or be­hav­iour in your app. Additionally, it works seam­lessly with VSCode, so you re­ally don’t have to sweat.

All my app code was in a sin­gle file. Which is prob­a­bly not how you should be do­ing things. It re­sulted in a ~500 line file and made it ex­tremely dif­fi­cult to nav­i­gate around.

I used Dio to com­mu­ni­cate with VALORANTs APIs [NOTE: I in­ter­achange­ably use the terms VALORANT API and Riot Games API al­though they’re ul­ti­mately the same thing in this con­text]. The API would of­ten re­turn cook­ies which would be re­quired in sub­se­quent re­quests, so we use some­thing called a CookieJar. For un­known rea­sons, the re­quests would­n’t go through un­less I used HTTP 2, and I was­n’t go­ing to ques­tion code that works.

import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:dio_http2_adapter/dio_http2_adapter.dart';

...

final cookieJar = CookieJar();
final dio = Dio()
..interceptors.add(LogInterceptor())
..interceptors.add(DioNetworkLogger())
..interceptors.add(CookieManager(cookieJar))
..options.headers['content-Type'] = 'application/json'
..options.headers['Accept'] = 'application/json'
..options.headers['user-agent'] = 'trapwire/khaleelgibran.com'
..httpClientAdapter = Http2Adapter(
ConnectionManager(idleTimeout: Duration(seconds: 10)),
);

Future<void> prepareJar() async {
final Directory appDocDir = await getApplicationDocumentsDirectory();
final String appDocPath = appDocDir.path;
final jar = PersistCookieJar(
ignoreExpires: true,
storage: FileStorage(appDocPath + "/.cookies/"),
);
dio.interceptors.add(CookieManager(jar));
}

Making HTTP re­quests had never been so eas­ier - al­though not as easy as Fetch.

var authCookies = await dio.request(
"https://auth.riotgames.com/api/v1/authorization",
data: {
"client_id": "play-valorant-web-prod",
"nonce": "1",
"redirect_uri": "https://playvalorant.com/opt_in",
"response_type": "token id_token",
},
options: Options(method: "POST"),
);

To fetch my daily store, the Riot Games API needs 4 things:

  1. A valid to­ken from auth.riotgames.com/api/v1/authorization
  2. The re­gion where your ac­count is reg­is­tered (also called a shard)
  3. The play­er’s UUID
  4. A sec­ond to­ken called the Entitlement Token’ that would be used for sub­se­quent re­quests

To get 4., I’d need to get 2. and 3. some­how. I could ask the user to in­put it, but that would­n’t be a very smooth user ex­pe­ri­ence. After pok­ing around for a bit, I dis­cov­ered that the JWT to­ken re­turned by 1. has 2. and 3. em­bed­ded in the to­ken.

JWT

For the most part, the code was in­dent hell:


Widget build(BuildContext context) {
return Scaffold(
body: Form(
key: _formKey,
child: Stack(
children: [
Visibility(
visible: _showLoading,
child: LinearProgressIndicator(
value: null,
semanticsLabel: 'Linear progress indicator',
),
),
Padding(
padding: EdgeInsets.all(30.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(height: 50),
Align(
alignment: Alignment.centerLeft,
child: Image.asset("assets/images/Trapwire.png",
height: 50, width: 50),
),
SizedBox(height: 20),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Login to your Riot account",
textAlign: TextAlign.left,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 23.0,
color: Color.fromARGB(255, 185, 144, 255)),

It was filled with state­ful wid­gets and end­less chil­dren.

Despite all this, the app ac­tu­ally worked. Here’s a few screen­shots from my em­u­la­tor.

Trapwire Trapwire

Shout out to my like ash­ley boys. You know who y’all are.


Sun Tzu once said that (he did not, but it sounds cooler) hav­ing a plan is one thing; fol­low­ing it is an en­tirely dif­fer­ent thing. Needless to say, my plan did­n’t ex­actly work out. You see, halfway through com­plet­ing the app, I lost the mo­ti­va­tion to make it fully func­tional. Turns out there was al­ready an app made us­ing the of­fi­cial APIs on the Play Store that did what I wanted. I was­n’t in the mood to rein­vent the wheel, but I have to ad­mit it was a good learn­ing ex­pe­ri­ence.

The skin ended up show­ing in my store on 6 December, 2023. That was in­deed a long time.




touch­ing grass

At this point, any sen­si­ble per­son would go out, and feel the sun and touch some grass, which is ex­actly what I did! I ended up join­ing my good friends from CodeDay in Musoorie to hike my way to the top of Benog Tibba.

Here’s me be­ing bul­lied while mur­dered sleep­ing at the top af­ter mov­ing so many mus­cles - it was more than I had ever used all my life.

Benog Tibba Peak Group Photo

The trek was to­tally like the Hunger Games (minus the deaths and vi­o­lence). A group of peo­ple all put into a for­est with treach­er­ous land­scapes and sur­vival of the fittest. I was by no means the fittest (I tried to walk on a log and ended up hug­ging it halfway through), but for­tu­nately our trek leader knew how to make Maggi. Spending time in the wilder­ness with­out Wi-fi, camp­ing amidst snakes and tigers (okay it was­n’t that dan­ger­ous, there were barely in­sects) and pee­ing in saw­dust def­i­nitely gave me a new­found grat­i­tude for my home (lmao).

The real strug­gle was go­ing to a place that speaks Hindi for the most part. I do not speak Hindi at all. If some­one talked to me in Hindi, I’d just nod and say ac­cha ac­cha. Lao Tzu said (he did not) to fake it till you make it. It has worked so far for me, and I’d ad­vise you to try it if you’re ever in a sit­u­a­tion sim­i­lar to mine.




one of us is ly­ing

Over the sum­mer, I got so bored that I ended up go­ing to a hos­pi­tal as part of an observership”. It’s like an in­tern­ship, but in­stead of ac­tu­ally work­ing for them, you just ob­serve them. As if you’re stalk­ing them (something I’m fa­mil­iar with).

Every day dur­ing that week felt like a game of Among Us be­cause there were other peo­ple with ac­tual as­pi­ra­tions of work­ing in the med­ical field. Then there was me. When the doc­tors and nurses would go around ask­ing every­one what they wanted to be (in a med­ical en­vi­ron­ment), I would feel guilty if I said I was there not be­cause of my in­ter­ests. Instead, I would say, I love ma­chines”. If they asked me to elab­o­rate, I would talk about the ma­chines in ra­di­ol­ogy and drop it at that. Honestly, I still don’t know what I was think­ing when I chose to go there. The pro­gram of­fered an op­tion in­volv­ing com­put­ers but I felt like it’d be too bor­ing for me (YES CRITICIZE ME ALL YOU WANT), and that’s how I ended up go­ing to a hos­pi­tal be­cause I wanted to learn some­thing new and chal­leng­ing.

It was­n’t all point­less though, I ended up mak­ing friends with nurses; I even had a dis­cus­sion about Star Wars and Din Djarin and the Mandalorian with one of them. Jokes aside, be­ing a doc­tor is re­ally hard and I did pick up on a few use­ful things that I would­n’t have oth­er­wise known.




glitch (and more to come)

As part of Glitch’s CodeJam, I ended up mak­ing a small web­site to con­vey my (and every­one else’s) thanks for every­thing that hap­pened. Anything with a 3D model of the Earth is based and any­thing in­volv­ing MapBox is dope.



clos­ing thoughts (very im­por­tant)

I’m on Mastodon now. Personally, I like it bet­ter than Twitter, you can bring your own cus­tom do­main, mak­ing it re­ally per­sonal.

They also sus­pended my al­ready in­ac­tive Twitter ac­count?

NEXT UP: CodeDay Abu Dhabi, 2024?


Professional foot­notes

  1. FOR LEGAL REASONS, THIS IS A JOKE. CONTACT MY LAWYER FOR FURTHER QUERIES.
  2. I am aware this sen­tence makes no sense to the vast ma­jor­ity of my read­ers; how­ever, I do have a few peo­ple read­ing who share my es­ports in­ter­ests. I’d ad­vise you to move on.
  3. Prime 2.0 Skin Trailer - VALORANT
  4. A world­wide com­pany with ~4500 em­ploy­ees and a ru­moured an­nual rev­enue of $1.5B. They’re also owned by Tencent. One of the biggest Chinese con­golom­er­ates in the world. So yeah, small in­die-game com­pany.
  5. Spoiler alert: It was not.