Porting Old Sites (Part 1)
Motivation
Before the most recent version of this site, I had a ton of different webpages scattered across different domains and web servers. This caused a number of obvious issues for me:
- SSL cert renewal was way more difficult than it needed to be
- The sites could not reliably link to each other
- Design varied wildly between the different sites
I could have very easily just moved all of the code into a single Python project and been done with it, but rewriting my website provided a really good opportunity for me to just try something completely different.
Switching to Java
Previously, all of my server-side code was written in Python, and it was a horrible tangled mess. Moving all of it over to Java seemed appealing for a couple reasons.
Probably most importantly, I've only been learning Java for a bit over a year now, but I've become a lot more familiar with it after writing a GUI editor for my friend's upcoming game, Tynk! and the Final Phonorecord. Making a website in Java seemed like a good way to get out of my comfort zone a bit and hopefully improve my skills with the language.
Another thing that really appealed to me was the fact that a website written in Java can be compiled into a single jar file that "just works" as long as the system has the right version of Java installed. When writing a website using a Python web framework like Django or Flask, however, you also have to contend with some of the issues involved with Python's package management. While tools like Poetry have made this much less of an issue, it's really not the kind of thing I feel like dealing with when I'm not at work.
GameBoy Camera Filter
This application is written in JavaScript, and the source code for the original version I wrote can be found on GitHub. Since the entire thing runs on the client-side, this was the easiest thing for me to port over. All I really had to do was copy and paste the existing HTML into a container inside of my new site's template, adjust some stuff in the CSS, and call it a day. I'm really happy with how smoothly this went-- the only hiccups along the way were caused by my previous code assuming that the browser would be using default light-mode styles.
For the time being, I just overwrote the background-color and color properties, but down the line I really should extend dark mode support into the application itself. Other than that, however, it's done and can be seen here.
Oblivion Dialog Tool
Getting it Working
Since this application involves literally zero lines of JavaScript, it was a lot trickier for me to port over. The original code made use of some basic features of the extremely useful Python Imaging Library to perform the following procedure:
- Determine the appropriate offsets and line wrapping to place a user-provided string of text on the image using the Oblivion font's metrics
- Draw the wrapped string onto a transparent image with a black stroke around the glyphs
- Stretch the image 200 pixels horizontally, because for some unknown reason the original game has all of the dialog text stretched a bit horizontally
- Superimpose the transparent text layer on top of the chosen character's image.
If you're curious, you can see the original Python code on GitHub. It's an incredibly short process in Python thanks to PIL.
Luckily for me, the vast majority of these things can be done very easily just using Java's built in Graphics2D methods. (The extremely batteries-included nature of the Java Class Library is one of the reasons I really like using the language.)
There was just one issue, however-- the built-in method for drawing text does not allow you to draw the text with a stroke around it. Luckily we can achieve this effect by manually drawing the individual glyphs as shapes with the appropriate stroke and fill, which I learned how to do from this life-saving StackOverflow answer. Once that particular issue was dealt with, I was pretty much done, and can be found here.
Room for Improvement
While getting the dialog tool working in Java, I became painfully aware of how janky the original code surrounding the actual image processing was. Previously, the flask application just populated the drop-down menu with a list of filenames from a directory listing (with the extension chopped off) to present the user with a list of options.
I really hate how difficult this makes it to add additional images to the tool. It's really obvious that I didn't know how to work with a DB or object storage when I made the original.
My solution here was just to create a DB table and associated "OblivionFace" entity that would keep track of each individual character, as well as a string with a link to the character's image file on the cdn. As a bonus, the service also will automatically upload an image to object storage when creating a new "OblivionFace" object. This will make it really easy for me to add an admin interface that allows me to upload additional images for characters down the line.
Closing Thoughts
While there have definitely been some challenges with this project so far, it's been much more fun and immediately rewarding than I expected. Java has a bad reputation for being verbose and painful to write, so I was surprised by just how quickly I got everything up and running.
Once I'm done polishing things up a bit around here, my next move is probably going to be adding back in some forum / image board functionality that I had on a previous version of this site. I'll just need to find some free time.