Last time this year, I was at Epoch. Almost 200 teenagers, all put into a hackerspace and 48 hours of pure fun and code. It was like the Hunger Games minus the death and the violence and the battle-royale format and the competiton and basically everything 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 wonder if there’s a party scene in Hunger Games ’cause we had a banger of a New Year’s party and I basically lost my mind shouting and freaking out.
Anyways, a lot of fun things has happened since then. I will admit, however, that this year lacked the proper vibes or “feels” (whatever gen-z says, pick up an Urban Dictionary). I think it’s because halfway through the year, I cut down on a lot of things (at least I was supposed to) because of The Boards. We don’t talk about it, all we know is that it’s a series of mysterious examinations conducted by mysterious figures from India. It’s like the Hunger Games but with all the death and violence. Just like how Bobbin was beat to death by Coriander something (edit: her name is Coriolanus), parents often beat their kids with NCERT textbooks.
my video game addiction activities
Apart from FNATIC winning three international VALORANT tournaments (two official and one off-season) and China finally getting their win against NAVI with EDG KangKang showing up, I was quite invested in VALORANT. If my parents or anybody concerned about my mental health is reading, I’d like to inform you that I’ve only played the game for a total of 260 hours in the past two years, so I don’t think I am addicted. According to online-stopwatch.com, that is 10 days and 20 hours. In 10 days and 20 hours (out of 730 days), lighting will hit the earth 86,666,667 times! However, here’s where it gets interesting.
VALORANT has an in-game store that sells cosmetics for the game which translates to no actual use in the real world or the virtual world.
Its purpose is purely aesthetical.
There exists a cosmetic item, or “skin”, called the Prime Vandal.
Over the years, it has attained an overrated status but it’s not for no reason. My love for the skin is purely aesthetical. If Apple ever made a video game item for VALORANT, it would be the Prime Vandal. It’s like a lightsaber but infinitely more satisfying. It has sleek edges and a geometrically satisfying surface. As a designer and artist at heart, I felt bad for a small indie-game company like Riot Games for releasing free popular video-games with little to no returns. For the ~250 hours I had spent on the game, I felt like the Prime Vandal skin would be a fair compensation - Riot gets appreciated, I get good-looking pixels with eargasmic sounds.
Here’s the problem - I can’t just get it if I want it. VALORANT’s store is interesting, to say the least. The VALORANT store consists of 4 random skins that refreshes everyday. Purely random. Skins that you already own do not show up, so unless you’ve bought a large number of skins, the chances of getting one particular skin can be slim. How slim? Let’s do the math. (thanks Reddit)
According to r/VALORANT, as of April 2023, there are 489 available skins for the rotating 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 percentage will increase slightly as owned skins do not appear in the rotating shop pool. 0.82 is less than 1, and any number less than 1 is a bad idea, as any mathematician dealing with probability will tell you. Essentially, the chances were short.
I started waiting for the skin on 29 May, 2023. A lot happened during that time. Grass grew, the world aged, and the deserts became drier. In a desperate attempt, I emailed Riot Games. Begging them to give me the skin in the store. Attached below is my correspondence with some video-game characters.
On July 21, 2023 09:26, ipayforhacks wrote
On July 21, 2023 22:05, Ditto replied
They also sent a GIF after that, I made it my in-game spray ever since - you never know.
Now, it was supposed to end there, but I’m a kind person. I had to express my thanks. It turns out my support ticket was closed, and my “thanks” basically triggered Zendesk to reopen my ticket, which prompted one last reply from them.
On July 22, 2023 09:35, ipayforhacks said
On July 22, 2023 10:18, hiturrcilual replied
Writing this now, I realize they had terrible luck. If anything the skin wishes decreased all my chances. And everyday felt like a tease. I was convinced the Riot devs were manually changing my skins every morning to see me depressed at my luck for all the employees to have a good laugh at their breakfast table. Every time I checked my store, I’d look through my webcam to make sure my life wasn’t something like The Truman Show.
my big-brain 200iq masterclass plan
That was when it struck me. Archimedes or someone shouted “Eureka”, I shouted “HOLY COW”. You see, VALORANT does not offer any of its game data publicly for your use unless you apply to become a “Riot Developer”. However, that has not stopped developers from scraping VALORANT to find its internal APIs and documenting them. The problem is that if you release an application using internal APIs for public use, Riot Games will serve you a DMCA takedown on your application. Meaning, you are now legally obliged to remove your app from wherever it exists on the Internet. You can, of course, contest the DMCA takedown but it’s really pointless when your application is entirely based on VALORANT.
My plan was akin to a standoff based on bluffs and deceit. I would publicly release a mobile app that would use their internal APIs to get my daily store, and when they ask me to takedown the app, I would ask for the Prime Vandal skin in my store in exchange. It was a flawless plan. It was a win-win situation - Riot gets to take down my app, I get the skin in my store.
And so, I began. What is programming for, if not to spend hours building automations for meaningless tasks that would otherwise take barely three minutes manually. I ended up making an Android app that would track my VALORANT store every single day and give me a notification if the Prime Vandal showed up.
Click to read more technical details (or skip ahead)
introduction to flutter
Getting a bit technical, the app building was very interesting. I chose to go with Flutter, despite having zero experience with it. It was pretty easy to use Flutter as a beginner, because Dart’s syntax is basically JavaScript. If you’ve used a lot of JavaScript, you’ll be comfortable with Flutter in no time. The only thing I was a bit intimidated by was how large Flutter files can get, especially if you don’t know or don’t want to (out of laziness - like me) split your widgets into multiple files. Another advantage is that for the most part you won’t have to worry about styling, as long as you’re using Material Design 3.
Flutter compiles to a wide variety of platforms including Windows and iOS (requires additional config), which made debugging a breeze because I could preview the app on the web for the most part. However, I would recommend using an Android Studio simulator to test out Android-specific features or behaviour in your app. Additionally, it works seamlessly with VSCode, so you really don’t have to sweat.
All my app code was in a single file. Which is probably not how you should be doing things. It resulted in a ~500 line file and made it extremely difficult to navigate around.
I used Dio to communicate with VALORANT’s APIs [NOTE: I interachangeably use the terms VALORANT API and Riot Games API although they’re ultimately the same thing in this context]. The API would often return cookies which would be required in subsequent requests, so we use something called a CookieJar
. For unknown reasons, the requests wouldn’t go through unless I used HTTP 2, and I wasn’t going to question 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 requests had never been so easier - although 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:
- A valid token from
auth.riotgames.com/api/v1/authorization
- The region where your account is registered (also called a shard)
- The player’s UUID
- A second token called the ‘Entitlement Token’ that would be used for subsequent requests
To get 4., I’d need to get 2. and 3. somehow. I could ask the user to input it, but that wouldn’t be a very smooth user experience. After poking around for a bit, I discovered that the JWT token returned by 1. has 2. and 3. embedded in the token.
For the most part, the code was indent 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 stateful widgets and endless children.
Despite all this, the app actually worked. Here’s a few screenshots from my emulator.
Shout out to my like ashley boys. You know who y’all are.
Sun Tzu once said that (he did not, but it sounds cooler) having a plan is one thing; following it is an entirely different thing. Needless to say, my plan didn’t exactly work out. You see, halfway through completing the app, I lost the motivation to make it fully functional. Turns out there was already an app made using the official APIs on the Play Store that did what I wanted. I wasn’t in the mood to reinvent the wheel, but I have to admit it was a good learning experience.
The skin ended up showing in my store on 6 December, 2023. That was indeed a long time.
touching grass
At this point, any sensible person would go out, and feel the sun and touch some grass, which is exactly what I did! I ended up joining my good friends from CodeDay in Musoorie to hike my way to the top of Benog Tibba.
Here’s me being bullied while murdered sleeping at the top after moving so many muscles - it was more than I had ever used all my life.
The trek was totally like the Hunger Games (minus the deaths and violence). A group of people all put into a forest with treacherous landscapes and survival of the fittest. I was by no means the fittest (I tried to walk on a log and ended up hugging it halfway through), but fortunately our trek leader knew how to make Maggi. Spending time in the wilderness without Wi-fi, camping amidst snakes and tigers (okay it wasn’t that dangerous, there were barely insects) and peeing in sawdust definitely gave me a newfound gratitude for my home (lmao).
The real struggle was going to a place that speaks Hindi for the most part. I do not speak Hindi at all. If someone talked to me in Hindi, I’d just nod and say accha accha. Lao Tzu said (he did not) to fake it till you make it. It has worked so far for me, and I’d advise you to try it if you’re ever in a situation similar to mine.
one of us is lying
Over the summer, I got so bored that I ended up going to a hospital as part of an “observership”. It’s like an internship, but instead of actually working for them, you just observe them. As if you’re stalking them (something I’m familiar with).
Every day during that week felt like a game of Among Us because there were other people with actual aspirations of working in the medical field. Then there was me. When the doctors and nurses would go around asking everyone what they wanted to be (in a medical environment), I would feel guilty if I said I was there not because of my interests. Instead, I would say, “I love machines”. If they asked me to elaborate, I would talk about the machines in radiology and drop it at that. Honestly, I still don’t know what I was thinking when I chose to go there. The program offered an option involving computers but I felt like it’d be too boring for me (YES CRITICIZE ME ALL YOU WANT), and that’s how I ended up going to a hospital because I wanted to learn something new and challenging.
It wasn’t all pointless though, I ended up making friends with nurses; I even had a discussion about Star Wars and Din Djarin and the Mandalorian with one of them. Jokes aside, being a doctor is really hard and I did pick up on a few useful things that I wouldn’t have otherwise known.
glitch (and more to come)
As part of Glitch’s CodeJam, I ended up making a small website to convey my (and everyone else’s) thanks for everything that happened. Anything with a 3D model of the Earth is based and anything involving MapBox is dope.
closing thoughts (very important)
I’m on Mastodon now. Personally, I like it better than Twitter, you can bring your own custom domain, making it really personal.
They also suspended my already inactive Twitter account?
NEXT UP: CodeDay Abu Dhabi, 2024?