Finally Contributing Actual Code to Open Source

udayrana

Uday Rana

Posted on October 13, 2024

Finally Contributing Actual Code to Open Source

So I'm participating in Hacktoberfest, and for my first contribution, I worked on a project called libplanet, which is a .NET library for creating peer-to-peer multiplayer online games using blockchain technology.

GitHub logo planetarium / libplanet

Blockchain in C#/.NET for on-chain, decentralized gaming

Libplanet

Discord Build Status (CircleCI) Codecov NuGet NuGet (prerelease)

Libplanet is a .NET library for creating multiplayer online game in decentralized fashion, which means the whole gameplay occurs on a peer-to-peer network among equal nodes rather than an authorized central server. Under the hood, it incorporates many features (e.g digital signature, BFT consensus, data replication) of a blockchain.

It has competitive advantages over other solutions for decentralized gaming:

  • Embeddable: A game app does not have to communicate with another running process, hence it doesn't require extra marshaling or processes management To draw a parallel, Libplanet is closer to SQLite than MySQL or PostgreSQL.

  • Isomorphic: Libplanet is a .NET library, so every game logic can be written in the same language, C#, and run on the blockchain. No glue code or "smart contracts" are needed.

  • Token-independent: Unlike almost every blockchain system, it does not force users to create and deal with yet-another-cryptocurrency. Your game…

My contribution wasn't as exciting as that makes it sound - I fixed a bug in a script that generated the version names for the project releases. The timestamps in the version names were in the wrong order when sorted alphanumerically.

Invalid order of NuGet dev releases #3955

Background

When I looked at Libplanet's NuGet dev releases, they were not well ordered by release date.

image

It is because the version suffix is generated without zerofill. (20240901 with zerofill, 202491 without zerofill)

Work items

To resolve this issue, you can amend scripts/determine-versions.js file. You can see the logic to determine a version suffix at the below lines:

https://github.com/planetarium/libplanet/blob/f6cd63d7fcb58870785ed5ce3829327b38ed30f1/scripts/determine-version.js#L120-L126

You should update the part to declare ts variable.

You can test the script easily by running the node scripts/determine-version.js command.

$ node --version
v20.4.0
$ node scripts/determine-version.js 
VersionPrefix: 5.3.0
VersionSuffix: dev.202491004320+f6cd63d
PackageVersion: 5.3.0-dev.202491004320
VersionType: dev

If you amended well, it expects to generate VersionSuffix: dev.20240910010203+xxxxxxx for the date (year: 2024, month: 9, day: 10, hour: 1, minutes: 2, seconds: 3)

Discovering the issue

I discovered the issue using a bottom up approach where I'd search for open issues on GitHub and try to find one that looked like a good fit. This was the first time I'd be contributing actual code to someone else's project, and not just documentation, so I wanted to start with something small. The maintainer included the snippet of code that needed to be worked on when filing the issue, and I saw it was in JavaScript, which I'm very familiar with, so I thought I'd give it a shot and asked if I could work on it.

// The original code
const timestamp = await getCommitTimestamp(); 
     const ts = `${timestamp.getUTCFullYear()}${ 
       timestamp.getUTCMonth() + 1 
     }${timestamp.getUTCDate()}${timestamp.getUTCHours()}${ 
       timestamp.getUTCMinutes() + 0 
     }${timestamp.getUTCSeconds()}`; 
     versionSuffix = `dev.${ts}`; 
Enter fullscreen mode Exit fullscreen mode

Getting to work

When I got to work, I was surprised to find that the rest of the project was in C#. For a second, I thought this issue would end up being trickier than I expected. But on closer inspection, the file I had to work on was a standalone JavaScript script that didn't interact with the rest of the project. The maintainer was even kind enough to include the command to test the script when filing the issue.

The actual fix was very straightforward. I just had to add zero padding to date strings so that the timestamps generated for the version numbers would be sorted in chronological order when sorting alphanumerically. I remembered handling this same situation for an earlier JavaScript project.

To be honest, my initial attempt looked pretty ugly. The original code used a template literal, and in the spirit of sticking to the maintainers' vision, I added a bunch of extra lines to format and store the date values in variables and then pass them to the template literal.

// My initial fix
const timestamp = await getCommitTimestamp();
    const formattedMonth = (timestamp.getUTCMonth() + 1)
      .toString()
      .padStart(2, "0");
    const formattedDate = timestamp.getUTCDate().toString().padStart(2, "0");
    const formattedHours = timestamp.getUTCHours().toString().padStart(2, "0");
    const formattedMinutes = timestamp
      .getUTCMinutes()
      .toString()
      .padStart(2, "0");
    const formattedSeconds = timestamp
      .getUTCSeconds()
      .toString()
      .padStart(2, "0");
    const ts = `${timestamp.getUTCFullYear()}${formattedMonth}${formattedDate}${formattedHours}${formattedMinutes}${formattedSeconds}`;
Enter fullscreen mode Exit fullscreen mode

Making it prettier

One of the maintainers mentioned that with my fix, the template literal ended up being over 80 characters in a line, and asked if it could be changed. So I split the template literal on each variable.

// Failed formatting attempt
    const ts = `${timestamp.getUTCFullYear()
    }${formattedMonth
    }${formattedDate
    }${formattedHours
    }${formattedMinutes
    }${formattedSeconds}`;
Enter fullscreen mode Exit fullscreen mode

I noticed my editor would undo this change on saving (because I had the "format on save" setting enabled) but assumed that was just a problem on my end, and went with it anyway. The maintainer then responded saying his editor would also undo the changes I made, and proposed splitting the template literal using +s.

// The maintainer's suggestion
    const ts =
      `${timestamp.getUTCFullYear()}` +
      `${formattedMonth}` +
      `${formattedDate}` +
      `${formattedHours}` +
      `${formattedMinutes}` +
      `${formattedSeconds}`;
Enter fullscreen mode Exit fullscreen mode

This change was much more visually appealing. Since it broke up the template literal, I figured it'd also be okay to just get rid of it entirely. The extra horizontal space gained by splitting the literal also allowed us to do the formatting in-line and not have to declare any variables.

// The final change
    const ts =
      timestamp.getUTCFullYear().toString() +
      (timestamp.getUTCMonth() + 1).toString().padStart(2, "0") +
      timestamp.getUTCDate().toString().padStart(2, "0") +
      timestamp.getUTCHours().toString().padStart(2, "0") +
      timestamp.getUTCMinutes().toString().padStart(2, "0") +
      timestamp.getUTCSeconds().toString().padStart(2, "0");
Enter fullscreen mode Exit fullscreen mode

With that, the maintainers approved the changes and merged the pull request. And so, I'd officially made my first Hacktoberfest contribution, and for the first time, written code for a real project.

fix: add zero padding to version timestamp #3957

Fixes https://github.com/planetarium/libplanet/issues/3955. I declared variables to store each formatted portion of the date for readability. Please let me know if you'd liked anything changed.

Moving forward

With two contributions under my belt, I was becoming comfortable with the open source workflow. I wanted to work on something bigger. I wanted to make the most of Hacktoberfest, so I decided that for my next PR, it was time to ramp things up and work on a feature.

More on that next week.

💖 💪 🙅 🚩
udayrana
Uday Rana

Posted on October 13, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related