Categories
Coding Games

Upgrading All My Unity Apps

Google and Apple have both had a lot of policy changes in the last little while. Google’s was far less annoying than Apple’s. Both require me to rebuild my Unity games.

Google requires 64bit build support in all App store apps as of August 2019 (with a few exceptions). Most of my older games are exempt until 2021, but since a couple were not, I opted to update them all.

Apple’s implemented some arbitrary policy that they can pull your apps from the store if they’re not updated for some unknown amount of time. One of my games is on the block and will be removed in 30 days. Who knows how many others will follow. Apple has also deemed my perfectly functional 2009 Macbook Pro to be obsolete, so I can no longer even build for iOS on this hardware. A whole different story.

So I’ll update my Android apps.

The Process

The process to upgrade everything to 64bit is a bit of a crap shoot. I didn’t know how long it would take or what I was really in for, so here’s a rough list of what I had to do in Unity:

  1. Update Unity to the latest LTS version.
  2. Open your old projects and let Unity update what it can.
  3. Change the build system to “Gradle” – internal is now deprecated.
  4. Check the “Build App Bundle (Google Play)” if you are uploading to Google
  5. Change your Target API to the Highest Level.
  6. Change your Android build settings to use .NET 4.x since 3.x is deprecated.
  7. Change your Android build tool to use IL2CPP (required for 64bit)
  8. Check off the ARM64 box.
  9. And Build…
Unity Build Settings Dialog
Unity Player Settings for Android

What Really Happened

Everything broke.

If you’re like me, You’ve probably used some extra libraries. I use Text Mesh Pro, Google Ads, Firebase Analytics, and Google Play Game Services in all of my apps. This process required all of them to be updated.

If you use these, in order to cleanly update, you must delete the old versions. The latest Google Play and Google Ads packages from their Git Hub repos install pretty cleanly. The tricky parts were with Firebase and Text Mesh Pro (TMP).

You must import the dotnet4 packages. Once you do that, the dependency resolver should fire up automatically and get any required bits and pieces from the Android SDK.

The original version of Text Mesh Pro wasn’t an official package in Unity. So needless to say, I had to re-do most of my TMP objects. The rest of the code worked fine, but it was a little more time consuming than I would have hoped for.

Other Unity Problems

I ran into a few minor issues with NDK (Native development kit) which is required by Unity to use the IL2CPP compiler. You’ll need to make sure you get the specific version and point Unity to it. At time of writing, Unity requires NDK r16b (r20-something is current). It will send you to a link to download it if it can not find it on your machine.

Final Thoughts

All in all, it was a somewhat bearable process that took a few hours per game. I’ve got the process down, so I’ll be good to go on the rest.

As a bonus prize, I was able to convert to Google Play’s signing management and use App bundles, which greatly reduced the download size of my Android apps.

Maybe this update will increase downloads a bit.

Categories
Facebook Security

Secure your Facebook Account with Two Easy Steps

Step 1. Enable Two Factor Authentication via an anonymous Security App.

Enabling two factor authentication (2FA) is one of the best ways to secure your account. Facebook provides two methods.

  1. SMS via your phone – requires service
  2. App based codes via your phone (or tablet) – this does not require an active data connection

If you’re not a fan of Facebook knowing your phone number and don’t want to enable two factor authentication using that method, then you’re in luck! Simply go to the two factor settings page and select “add an app”.

Facebook 2 Factor Settings

You can download the Google Authentication application to your phone and enable it using the steps provided on Facebook’s page. This code generator is 100% anonymous and based on an open standard called “Time-based One Time Password” algorithm.

Once enabled, anyone who attempts to login with your account with a correct password will be required to enter a generated number. This number changes every 30 seconds. Facebook will generally ask you to use the 2FA code when you attempt to sign in to an unknown computer or device.

Step 2. Remove Those Old Apps

If you’ve ever been a “victim” of spam posts, it’s likely an old rogue app posting on your behalf and tagging your friends.

You’ve probably added a lot of apps in your life time. Some may be dead, and some may be harvesting your data as you sleep. Head on over to the applications and websites settings and you’ll be able to see them all.

Just review and edit ones you think you no longer use. You can remove them outright by checking the box and clicking “Remove.”

You can also use this to report bad apps that you may have.

Hopefully this helps you out.

Categories
Coding PHP

WordPress and it’s Broken Core

When I develop with PHP (7.2+) I develop with strict mode and xdebug enabled. I do this on purpose because notices and warnings are both important to your quality of code. Constantly I am running into one issue with WordPress core that is quite frankly annoying.

This bug is also affecting WPEngine users a lot.

Warning: Parameter 1 to wp_default_scripts() expected to be a reference, value given in /[..]/your-directory/wp-includes/class-wp-hook.php on line 286
Warning: Parameter 1 to wp_default_packages() expected to be a reference, value given in /[..]/your-directory/wp-includes/class-wp-hook.php on line 286
Warning: Parameter 1 to wp_default_styles() expected to be a reference, value given in /[..]/your-directory/wp-includes/class-wp-hook.php on line 286

The Error

The Error is pretty self evident that somewhere in the core wp_default_scripts, wp_default_packages, and wp_default_styles are all being called incorrectly. But where? and why?

Diving into class-wp-hook.php we’ll find that this is error is emitted from inside the apply_filters code. Unfortunately for us, the apply_filters code uses a lot of magic in the form of call_user_func_array – a built in PHP function that calls a user’s function with an array of arguments. Blammo. That should already be setting off your alarms. If wp_default_scripts expects a reference passing an array of values is definitely going to blow it up.

The Investigations

You’ve probably found yourself here by googling the above error message(s). You’ve probably already sifted through a few forum posts that tell you to “ignore errors” or “fix your theme” or “we have no idea!”

I’m going to start with ignoring warnings is a terrible suggestion. It always has been. Fix your code, increase your code quality. But what happens when your code isn’t the problem?

Unfortunately, a bug in core code takes time to fix. So you can report it (it’s a 5 month old bug, but the problems show up on the internet long before that). You can wait. And you can hack your core files to get rid of the error yourself.

Disclaimer: hacking your core files will void your warranty.

The Actual Problem

Since I’ve been tracking down this problem, I’ve discovered that it’s not super simple. The problem is how parts of WordPress core handle the wp_scripts object. If you write themes you’re probably aware of wp_equeue_script (and it’s friends). If you look at wp_enqueue_script you’ll notice the first thing it does is obtains a global object of $wp_scripts (I also despise global variables, but that’s another issue) and if this object doesn’t exist, it creates a new one. Easy enough.

The part that breaks is when the filter gets run for WordPress’ default filters. In there it adds add_action( 'wp_default_scripts', 'wp_default_scripts' ); and as one would expect, it tries it’s hardest to set up the default scripts. But that’s when it breaks. wp_default_scripts expects the reference to the global $wp_scripts to be passed. It’s not. It’s passed as a value and that breaks.

It would be a lot easier (and likely better) if it wasn’t passing the instance wp scripts at all and used the global wp_scripts() function, the same way wp_enqueue_script does. It would be even better if WP_Scripts was an actual singleton since that’s what they’re attempting to do with the global variable. But what the heck do I know?

The Hack

To fix this, jump into your core files and find class-wp-hook.php, roll on down to line apply_filters and make the function look like this:

public function apply_filters($value, $args)
{
    if (!$this->callbacks) {
        return $value;
    }

    $nesting_level = $this->nesting_level++;

    $this->iterations[$nesting_level] = array_keys($this->callbacks);
    $num_args = count($args);

    do {
        $this->current_priority[$nesting_level] = $priority = current($this->iterations[$nesting_level]);

        foreach ($this->callbacks[$priority] as $the_) {
            if (!$this->doing_action) {
                $args[0] = $value;
            }

            // Avoid the array_slice if possible.
            if ($the_['accepted_args'] == 0) {
                $value = call_user_func_array($the_['function'], array());
            } elseif ($the_['accepted_args'] >= $num_args) {
                $special_cases = array('wp_default_scripts', 'wp_default_packages', 'wp_default_styles');
                if (in_array($the_['function'], $special_cases)) {
                    $arg = $args[0];
                    $args = array(&$arg);
                }
                $value = call_user_func_array($the_['function'], $args);
            } else {
                $value = call_user_func_array($the_['function'], array_slice($args, 0, (int)$the_['accepted_args']));
            }
        }
    } while (false !== next($this->iterations[$nesting_level]));

    unset($this->iterations[$nesting_level]);
    unset($this->current_priority[$nesting_level]);

    $this->nesting_level--;

    return $value;
}

This will get rid of the warnings by passing the arguments to the default functions as references. Of course, if you upgrade PHP this hack will get overwritten and you’ll have to do it again if the fix isn’t actually put in the core.

Hope that helps you out and thanks for visiting!

Categories
how-to

How to Watch US TV With Firefox

There’s this nifty little service out there called Locast (Local broadcast) and it’s geo-fenced for very specific reasons. While you can temporarily change your Geo Location (browser based) with Chrome, it reverts automatically every time you close your tab. So here’s a way to use Firefox to permanently (if you want) have this service work.

(1) Go to “about:config” in you Firefox browser and void your warranty.

Void your firefox warranty.
Make sure you check the box and “Accept the risk”

(2) In the search box type in geo.

locate the geo.wifi.uri
Find the geo.wifi.uri

(3) Double click on the geo.wifi.uri and input this geo location (for new york city):

data:application/json,{"location": {"lat": 40.7590, "lng": -73.9845}, "accuracy": 27000.0}

enter some data
you can always ‘reset’ the value, so don’t worry about saving the old value.

(4) Browse on over to Locast.org and accept the Geo Location permissions that it asks for.

Allow location access in firefox
Click on ‘remember this decision’ and ‘allow location access’

(5) You should see that you’re in New York!

New York City!

(6) Watch TV!

Go RAMS!
et voila! It would be better if they were giving out Dodge Rams, eh?

And that’s pretty much it. Just ahead of the Super Bowl. You can now watch US commercials that roll in at about $5.1M per 30 seconds.

Categories
Coding Games PHP

The Triviosity Rewrite

The Rewind

In 2010 I put a game online. Triviosity, a daily trivia game with occasional specially crafted challenges, has been online for over 8 year. It’s a game that people play on a regular basis and it’s always held a piece of my heart. When I originally wrote it I had full intent to make it a mobile app. An iOS app specifically. The original was built with Zend Framework 1, had a clunky API back-end with intent for the mobile app, and quite frankly it was rock solid. It ran without issues. Unfortunately the iOS app never happened, and as other frameworks and tools blossomed, ZF1 became outdated and not worth the time to build upon it.

Fast Forward

On thanksgiving weekend in October 2017 I decided it was time to rewrite my old game. It was time to switch up the technology and actually make the mobile app. At first glance I thought it was going to be a very daunting task. Switching from ZF1 to Laravel 5.5 seemed like it was going to be a huge undertaking. But it wasn’t. My data models from the original game were so awesome that porting the “beef” of it (I like to work with fat models) only took me a few days.

I sat on that small victory for months. Enter the void of hesitation. Was it too easy? Was I going about it all wrong? Was I doing this the right way? Is anyone new even going to play this rewrite?

If there’s one thing I absolutely detest it’s doing something over. I had to do this, but I hated doing this. There was a necessary evil at play – I want to build the new mobile apps. But I need to redo the old game to get there.

Then I got rolling. I don’t know what changed. I got about 90% complete then I stopped.

Who’s going to play this thing? Why am I doing this? Question, doubt, rinse, repeat.

Then the tidal wave hit. Frack it. “I’m putting this live.” It’s “good enough” and I can fix the missing parts. As a matter of fact, once I put it live, my desire to finish it and make it better went up exponentially.

On July 30, 2018 the unscheduled launch of the new Triviosity happened. A few hundred error emails later, and a bunch of random fixes, the dust had settled. And it’s alive.

Performance

There are two things that take precedence in my work. Security and Performance. Without going into too much detail about security (I can’t give away all my secrets) the new API includes request signing, encryption, and wonderful third party oAuth based authentication.

For performance, It was critical that I make this as fast as I possibly can while still leveraging my old (affordable) web servers. After launching you can see a substantial drop in load times and render times. (This isn’t just the home page either, it’s all pages.)

look at those performances
super graphs

The kicker was simple. Use the tool-set you have properly. As I mentioned, this was being built with Laravel 5.5 (and upgraded to 5.6 before my actual launch). As such, there’s one hell of a generally under-utilized tool-set available to me to use. So here’s a simplified rundown:

  1. CacheCache all the things you can. Cache your config files, routes, database queries. There are pages (score listings) that have a substantial amount of queries of data that doesn’t change often. Caching this turned render time from 500ms to 100ms.
  2. Compile / Minify CSS and JS – Laravel has a webpack config that utilizes a basic Laravel Mix out of the box. It has many nifty plugins to do everything you need. I only really needed the sass compiler, minifier, and JS minifier. This task is often overlooked and it yields some of the greatest performance boosts. The production build tool is A+.
  3. Offload to the Queue! – Using an asynchronous queue to handle things that don’t need to happen for the end user to continue is also a huge boost to performance. Things that can happen in the background: big database updates, sending emails, generating images – all done without the user feeling the slightest bit of a slowdown.
  4. Use the F’ing Framework – Far too often (I’m guilty of this too) I see code that “uses” a framework, but then it doesn’t actually use the framework. Laravel and it’s dependencies have been built up over the years to do a lot of the repetitious work. If I told you the code for the game controller was only 230 lines, you probably wouldn’t believe me. I leverage the framework’s models and view renderer to do the majority of the work. For reference, the old game play code was almost 1000 lines. Less code, same game, more efficient.
  5. Ditch The Cruft – I don’t use any external third party JS on this site with the exception of Google Analytics and Google AdSense (non blocking). Facebook, Google, and Twitter authentication is completely via server side redirects. The share buttons are just good old fashioned native links (which, as a bonus, launch the native apps on most mobile devices).

This is how you get a double A’s on speed tests.

The Future

Now that I have successfully released the best performing site of my life, I can finally work on the native mobile apps. I have no direct timeline for these. I’ll be building them as 100% native apps (Swift for iOS and Kotlin for Android) and not using some goofy cross-platform build tool so that will have some affect on the time frame. But they’ll be fast. They’ll be secure. They’ll be just as awesome and performance ready as the site itself.

Now with an even more rock-solid foundation I can build on this. We can all expect more curated challenges with great features.

TL;DR

It took me about 10 months to complete the rewrite. But in reality only 40 days. It kicks ass. It’s fast. It’s great. The mobile versions are coming soon.

Now go play some Triviosity. And let me know if you break something.

Categories
Things You Didn't Know

Murder, He Wrote

Today’s short and bittersweet jury duty process shook me to my roots.

It started off innocuous enough. Get to the courthouse on time, check in, sit and wait in a large wood panelled room that was built some time in the late 60s. With little to no information provided we waited. People slowly trickled in well past the posted time of “9am” but that didn’t seem to matter.

At some point around 9:30 we were provided with a start time. “The judge will be in at 10am.” followed by a collective sigh. Nobody really wanted to be here. But, a las, it is our civic duty.

As time rolled on, in seemingly slow motion, the court clerk did a mic test and other menial tasks to prepare the court.

Finally at around 10:15 the important people shuffle in through a door to the left followed by the defacto “all rise.”

The charges are read and a plea is submitted. “Not guilty,” — If it were the other way, this story is over. Potential jurors go home. However, not the situation, this case is going the distance now.

Thus begins the juror elimination round. The judge reads out some basic instructions followed by a few questions, in my informal summation:

Anyone know the defendant, the lawyers, or me? No, cool.

Anyone know any of these witnesses? (Reads a huge list) No, cool.

Does anyone have a personal reason why they may be unable to view this case with an open mind? A few people stir. A few hands pop up. People are directed to the right side of the court. A short line up builds. My insides start shaking like a scared little child. Apparently I’ve have something to say to this question.

I shuffle over to the line of about ten people and wait. One souls friend was killed recently, he was dismissed. Another had some strange story, I missed most of it for my internal fears, dismissed. A young lady in front of me tells the court her uncle was killed in a similar way. Dismissed.

I can only assume by now that what I am about to say is a valid answer. Unbeknownst to me I was about to tell a room full of strangers something that hardly any of my closest friends even know.

Sucking back the internal fears, focused solely on the judge, I leaned into the mic and said “In 1988 my father was shot.” The judge peered over to me about to say something else, I leaned back in and said “he was murdered.”

“You are dismissed” she said without hesitation.

I quickly exited the courtroom as fast as I could without running, while the court was still reading my juror number and confirmation of dismissal. In the hall way the lady before me was also making her exit. We chatted a bit down the six flights of escalators.

“I wasn’t really prepared for those memories to be surfaced like that.” She noted.

“Same.” still shaking on the inside. “Definitely not what I ever expected.” I said with a deep sigh.

She too experienced the inner trembles of having to say a terrible truth in front of a room full of strangers.

“Have a nice day” we said. I guess.

We found the exit and went our separate ways in the greyness of the cold wet morning.

All joking aside from “how do I get out of Jury duty?” I had no idea that I already held an unwanted card up my sleeve. I had no idea. It’s inexplicably strange that I’m actually quite happy that I got out of this. But the circumstances and process were an absolutely terrible and unexpected experience.

The reality is though, the question asked and my answer given would in fact impede my ability to view this case with an open mind.

The irony is I didn’t have to do that, the case is set to last a fairly long time and I had a simpler, legit out. But hey, sometimes the hard ones come up first.

So now they know, and now you know.